static gboolean parse_finished (ParseThreadData *data) { if (data->reset_count != data->dialog->priv->reset_count) { rb_debug ("dialog reset while parsing"); rb_podcast_parse_channel_free (data->channel); g_object_unref (data->dialog); g_clear_error (&data->error); g_free (data->url); g_free (data); return FALSE; } if (data->error != NULL) { gtk_label_set_label (GTK_LABEL (data->dialog->priv->info_bar_message), _("Unable to load the feed. Check your network connection.")); gtk_widget_show (data->dialog->priv->info_bar); } else { gtk_widget_hide (data->dialog->priv->info_bar); } if (data->channel->is_opml) { GList *l; /* convert each item into its own channel */ for (l = data->channel->posts; l != NULL; l = l->next) { RBPodcastChannel *channel; RBPodcastItem *item; item = l->data; channel = g_new0 (RBPodcastChannel, 1); channel->url = g_strdup (item->url); channel->title = g_strdup (item->title); /* none of the other fields get populated anyway */ insert_search_result (data->dialog, channel, FALSE); } rb_podcast_parse_channel_free (data->channel); } else if (data->existing) { /* find the row for the feed, replace the channel */ GtkTreeIter iter; gboolean found = FALSE; if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (data->dialog->priv->feed_model), &iter)) { do { RBPodcastChannel *channel; gtk_tree_model_get (GTK_TREE_MODEL (data->dialog->priv->feed_model), &iter, FEED_COLUMN_PARSED_FEED, &channel, -1); if (g_strcmp0 (channel->url, data->url) == 0) { gtk_list_store_set (data->dialog->priv->feed_model, &iter, FEED_COLUMN_PARSED_FEED, data->channel, -1); found = TRUE; rb_podcast_parse_channel_free (channel); break; } } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (data->dialog->priv->feed_model), &iter)); } /* if the row is selected, create entries for the channel contents */ if (found == FALSE) { rb_podcast_parse_channel_free (data->channel); } else if (data->dialog->priv->have_selection) { GtkTreePath *a; GtkTreePath *b; a = gtk_tree_model_get_path (GTK_TREE_MODEL (data->dialog->priv->feed_model), &iter); b = gtk_tree_model_get_path (GTK_TREE_MODEL (data->dialog->priv->feed_model), &data->dialog->priv->selected_feed); if (gtk_tree_path_compare (a, b) == 0) { add_posts_for_feed (data->dialog, data->channel); } gtk_tree_path_free (a); gtk_tree_path_free (b); } } else { /* model owns data->channel now */ insert_search_result (data->dialog, data->channel, data->single); } g_object_unref (data->dialog); g_clear_error (&data->error); g_free (data->url); g_free (data); return FALSE; }
static void rb_mtp_source_constructed (GObject *object) { RBMtpSource *source; RBMtpSourcePrivate *priv; RBEntryView *tracks; RBShell *shell; RBShellPlayer *shell_player; GObject *player_backend; GtkIconTheme *theme; GdkPixbuf *pixbuf; #if defined(HAVE_GUDEV) GMount *mount; #endif gint size; RB_CHAIN_GOBJECT_METHOD (rb_mtp_source_parent_class, constructed, object); source = RB_MTP_SOURCE (object); priv = MTP_SOURCE_GET_PRIVATE (source); /* try to open the device. if gvfs has mounted it, unmount it first */ #if defined(HAVE_GUDEV) mount = find_mount_for_device (priv->udev_device); if (mount != NULL) { rb_debug ("device is already mounted, waiting until activated"); g_mount_unmount_with_operation (mount, G_MOUNT_UNMOUNT_NONE, NULL, NULL, unmount_done_cb, g_object_ref (source)); /* mount gets unreffed in callback */ } else #endif open_device (source); tracks = rb_source_get_entry_view (RB_SOURCE (source)); rb_entry_view_append_column (tracks, RB_ENTRY_VIEW_COL_RATING, FALSE); rb_entry_view_append_column (tracks, RB_ENTRY_VIEW_COL_LAST_PLAYED, FALSE); /* the source element needs our cooperation */ g_object_get (source, "shell", &shell, NULL); shell_player = RB_SHELL_PLAYER (rb_shell_get_player (shell)); g_object_get (shell_player, "player", &player_backend, NULL); g_signal_connect_object (player_backend, "prepare-source", G_CALLBACK (prepare_player_source_cb), source, 0); g_object_unref (player_backend); g_object_unref (shell); g_signal_connect_object (rb_encoder_factory_get (), "prepare-source", G_CALLBACK (prepare_encoder_source_cb), source, 0); g_signal_connect_object (rb_encoder_factory_get (), "prepare-sink", G_CALLBACK (prepare_encoder_sink_cb), source, 0); /* icon */ theme = gtk_icon_theme_get_default (); gtk_icon_size_lookup (GTK_ICON_SIZE_LARGE_TOOLBAR, &size, NULL); pixbuf = gtk_icon_theme_load_icon (theme, "multimedia-player", size, 0, NULL); rb_source_set_pixbuf (RB_SOURCE (source), pixbuf); g_object_unref (pixbuf); if (priv->album_art_supported) { RhythmDB *db; db = get_db_for_source (source); g_signal_connect_object (db, "entry-extra-metadata-notify::rb:coverArt", G_CALLBACK (artwork_notify_cb), source, 0); g_object_unref (db); } }
static gboolean device_opened_idle (DeviceOpenedData *data) { RBMtpSourcePrivate *priv = MTP_SOURCE_GET_PRIVATE (data->source); int i; gboolean has_mp3 = FALSE; if (data->name != NULL) { g_object_set (data->source, "name", data->name, NULL); } /* when the source name changes after this, try to update the device name */ g_signal_connect (G_OBJECT (data->source), "notify::name", (GCallback)rb_mtp_source_name_changed_cb, NULL); rb_media_player_source_load (RB_MEDIA_PLAYER_SOURCE (data->source)); for (i = 0; i < data->num_types; i++) { const char *mediatype; if (i <= LIBMTP_FILETYPE_UNKNOWN) { priv->supported_types[data->types[i]] = 1; } /* this has to work with the remapping done in * rb-removable-media-source.c:impl_paste. */ switch (data->types[i]) { case LIBMTP_FILETYPE_WAV: mediatype = "audio/x-wav"; break; case LIBMTP_FILETYPE_MP3: /* special handling for mp3: always put it at the front of the list * if it's supported. */ has_mp3 = TRUE; mediatype = NULL; break; case LIBMTP_FILETYPE_WMA: mediatype = "audio/x-ms-wma"; break; case LIBMTP_FILETYPE_OGG: mediatype = "application/ogg"; break; case LIBMTP_FILETYPE_MP4: case LIBMTP_FILETYPE_M4A: case LIBMTP_FILETYPE_AAC: mediatype = "audio/aac"; break; case LIBMTP_FILETYPE_WMV: mediatype = "audio/x-ms-wmv"; break; case LIBMTP_FILETYPE_ASF: mediatype = "video/x-ms-asf"; break; case LIBMTP_FILETYPE_FLAC: mediatype = "audio/flac"; break; case LIBMTP_FILETYPE_JPEG: rb_debug ("JPEG (album art) supported"); mediatype = NULL; priv->album_art_supported = TRUE; break; default: rb_debug ("unknown libmtp filetype %s supported", LIBMTP_Get_Filetype_Description (data->types[i])); mediatype = NULL; break; } if (mediatype != NULL) { rb_debug ("media type %s supported", mediatype); priv->mediatypes = g_list_prepend (priv->mediatypes, g_strdup (mediatype)); } } if (has_mp3) { rb_debug ("audio/mpeg supported"); priv->mediatypes = g_list_prepend (priv->mediatypes, g_strdup ("audio/mpeg")); } g_object_unref (data->source); free (data->types); g_free (data->name); g_free (data); return FALSE; }
static void impl_constructed (GObject *object) { RBGenericPlayerSource *source; RBGenericPlayerSourcePrivate *priv; RhythmDBEntryType *entry_type; char **playlist_formats; char **output_formats; char *mount_name; RBShell *shell; GFile *root; GFileInfo *info; GError *error = NULL; RB_CHAIN_GOBJECT_METHOD (rb_generic_player_source_parent_class, constructed, object); source = RB_GENERIC_PLAYER_SOURCE (object); priv = GET_PRIVATE (source); rb_device_source_set_display_details (RB_DEVICE_SOURCE (source)); g_object_get (source, "shell", &shell, "entry-type", &entry_type, NULL); g_object_get (shell, "db", &priv->db, NULL); priv->import_errors = rb_import_errors_source_new (shell, priv->error_type, entry_type, priv->ignore_type); g_object_unref (shell); root = g_mount_get_root (priv->mount); mount_name = g_mount_get_name (priv->mount); info = g_file_query_filesystem_info (root, G_FILE_ATTRIBUTE_FILESYSTEM_READONLY, NULL, &error); if (error != NULL) { rb_debug ("error querying filesystem info for %s: %s", mount_name, error->message); g_error_free (error); priv->read_only = FALSE; } else { priv->read_only = g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_FILESYSTEM_READONLY); g_object_unref (info); } g_free (mount_name); g_object_unref (root); g_object_get (priv->device_info, "playlist-formats", &playlist_formats, NULL); if (playlist_formats != NULL && g_strv_length (playlist_formats) > 0) { g_object_set (entry_type, "has-playlists", TRUE, NULL); } g_strfreev (playlist_formats); g_object_unref (entry_type); g_object_get (priv->device_info, "output-formats", &output_formats, NULL); if (output_formats != NULL) { GstEncodingTarget *target; int i; target = gst_encoding_target_new ("generic-player", "device", "", NULL); for (i = 0; output_formats[i] != NULL; i++) { const char *media_type = rb_gst_mime_type_to_media_type (output_formats[i]); if (media_type != NULL) { GstEncodingProfile *profile; profile = rb_gst_get_encoding_profile (media_type); if (profile != NULL) { gst_encoding_target_add_profile (target, profile); } } } g_object_set (source, "encoding-target", target, NULL); } g_strfreev (output_formats); }
static void current_folder_changed_cb (GtkFileChooser *chooser, RBImportDialog *dialog) { GSettings *settings; RBSource *source; GtkWidget *label; const char *uri; char **locations; int i; uri = gtk_file_chooser_get_uri (chooser); if (g_strcmp0 (uri, dialog->priv->current_uri) == 0) return; g_free (dialog->priv->current_uri); dialog->priv->current_uri = g_strdup (uri); if (dialog->priv->import_job != NULL) { rhythmdb_import_job_cancel (dialog->priv->import_job); } clear_info_bar (dialog); source = rb_shell_guess_source_for_uri (dialog->priv->shell, uri); if (source != NULL) { if (RB_IS_DEVICE_SOURCE (source)) { char *msg; char *name; GtkWidget *content; rhythmdb_entry_delete_by_type (dialog->priv->db, dialog->priv->entry_type); rhythmdb_entry_delete_by_type (dialog->priv->db, dialog->priv->ignore_type); rhythmdb_commit (dialog->priv->db); dialog->priv->info_bar = gtk_info_bar_new (); g_object_set (dialog->priv->info_bar, "hexpand", TRUE, NULL); g_object_get (source, "name", &name, NULL); /* this isn't a terribly helpful message. */ msg = g_strdup_printf (_("The location you have selected is on the device %s."), name); label = gtk_label_new (msg); g_free (msg); content = gtk_info_bar_get_content_area (GTK_INFO_BAR (dialog->priv->info_bar)); gtk_container_add (GTK_CONTAINER (content), label); msg = g_strdup_printf (_("Show %s"), name); gtk_info_bar_add_button (GTK_INFO_BAR (dialog->priv->info_bar), msg, GTK_RESPONSE_ACCEPT); g_free (msg); g_signal_connect (dialog->priv->info_bar, "response", G_CALLBACK (device_info_bar_response_cb), dialog); gtk_widget_show_all (dialog->priv->info_bar); gtk_container_add (GTK_CONTAINER (dialog->priv->info_bar_container), dialog->priv->info_bar); return; } } /* disable copy if the selected location is already inside the library */ settings = g_settings_new ("org.gnome.rhythmbox.rhythmdb"); locations = g_settings_get_strv (settings, "locations"); gtk_widget_set_sensitive (dialog->priv->copy_check, TRUE); for (i = 0; locations[i] != NULL; i++) { if (g_str_has_prefix (uri, locations[i])) { gtk_widget_set_sensitive (dialog->priv->copy_check, FALSE); break; } } g_strfreev (locations); g_object_unref (settings); if (dialog->priv->import_job != NULL) { /* wait for the previous job to finish up */ rb_debug ("need to wait for previous import job to finish"); g_signal_connect (dialog->priv->import_job, "complete", G_CALLBACK (start_deferred_scan), dialog); } else { start_scanning (dialog); } }
/** * rb_device_source_set_display_details: * @source: a #RBDeviceSource * * Sets the icon and display name for a device-based source. * The details come from the mount and/or volume. This should * be called in the source's constructed method. */ void rb_device_source_set_display_details (RBDeviceSource *source) { GMount *mount = NULL; GVolume *volume = NULL; GIcon *icon = NULL; char *display_name; GdkPixbuf *pixbuf = NULL; if (g_object_class_find_property (G_OBJECT_GET_CLASS (source), "volume")) { g_object_get (source, "volume", &volume, NULL); } if (g_object_class_find_property (G_OBJECT_GET_CLASS (source), "mount")) { g_object_get (source, "mount", &mount, NULL); } /* prefer mount details to volume details, as the nautilus sidebar does */ if (mount != NULL) { mount = g_object_ref (mount); } else if (volume != NULL) { mount = g_volume_get_mount (volume); } else { mount = NULL; } if (mount != NULL) { display_name = g_mount_get_name (mount); icon = g_mount_get_icon (mount); rb_debug ("details from mount: display name = %s, icon = %p", display_name, icon); } else if (volume != NULL) { display_name = g_volume_get_name (volume); icon = g_volume_get_icon (volume); rb_debug ("details from volume: display name = %s, icon = %p", display_name, icon); } else { display_name = g_strdup ("Unknown Device"); icon = g_themed_icon_new ("multimedia-player"); } g_object_set (source, "name", display_name, NULL); g_free (display_name); if (icon == NULL) { rb_debug ("no icon set"); pixbuf = NULL; } else if (G_IS_THEMED_ICON (icon)) { GtkIconTheme *theme; const char * const *names; gint size; int i; theme = gtk_icon_theme_get_default (); gtk_icon_size_lookup (RB_SOURCE_ICON_SIZE, &size, NULL); i = 0; names = g_themed_icon_get_names (G_THEMED_ICON (icon)); while (names[i] != NULL && pixbuf == NULL) { rb_debug ("looking up themed icon: %s", names[i]); pixbuf = gtk_icon_theme_load_icon (theme, names[i], size, 0, NULL); i++; } } else if (G_IS_LOADABLE_ICON (icon)) { rb_debug ("loading of GLoadableIcons is not implemented yet"); pixbuf = NULL; } if (pixbuf != NULL) { g_object_set (source, "pixbuf", pixbuf, NULL); g_object_unref (pixbuf); } if (mount != NULL) { g_object_unref (mount); } if (volume != NULL) { g_object_unref (volume); } if (icon != NULL) { g_object_unref (icon); } }
static char * impl_build_dest_uri (RBTransferTarget *target, RhythmDBEntry *entry, const char *media_type, const char *extension) { RBGenericPlayerSourcePrivate *priv = GET_PRIVATE (target); const char *in_artist; char *artist, *album, *title; gulong track_number, disc_number; const char *folders; char **audio_folders; char *mount_path; char *number; char *file = NULL; char *path; char *ext; rb_debug ("building dest uri for entry at %s", rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION)); if (extension != NULL) { ext = g_strconcat (".", extension, NULL); } else { ext = g_strdup (""); } in_artist = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ALBUM_ARTIST); if (in_artist[0] == '\0') { in_artist = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ARTIST); } artist = sanitize_path (in_artist); album = sanitize_path (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ALBUM)); title = sanitize_path (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_TITLE)); /* we really do need to fix this so untagged entries actually have NULL rather than * a translated string. */ if (strcmp (artist, _("Unknown")) == 0 && strcmp (album, _("Unknown")) == 0 && g_str_has_suffix (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION), title)) { /* file isn't tagged, so just use the filename as-is, replacing the extension */ char *p; p = g_utf8_strrchr (title, -1, '.'); if (p != NULL) { *p = '\0'; } file = g_strdup_printf ("%s%s", title, ext); } if (file == NULL) { int folder_depth; track_number = rhythmdb_entry_get_ulong (entry, RHYTHMDB_PROP_TRACK_NUMBER); disc_number = rhythmdb_entry_get_ulong (entry, RHYTHMDB_PROP_DISC_NUMBER); if (disc_number > 0) number = g_strdup_printf ("%.02u.%.02u", (guint)disc_number, (guint)track_number); else number = g_strdup_printf ("%.02u", (guint)track_number); g_object_get (priv->device_info, "folder-depth", &folder_depth, NULL); switch (folder_depth) { case 0: /* artist - album - number - title */ file = g_strdup_printf ("%s - %s - %s - %s%s", artist, album, number, title, ext); break; case 1: /* artist - album/number - title */ file = g_strdup_printf ("%s - %s" G_DIR_SEPARATOR_S "%s - %s%s", artist, album, number, title, ext); break; default: /* use this for players that don't care */ case 2: /* artist/album/number - title */ file = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s" G_DIR_SEPARATOR_S "%s - %s%s", artist, album, number, title, ext); break; } g_free (number); } g_free (artist); g_free (album); g_free (title); g_free (ext); if (file == NULL) return NULL; g_object_get (priv->device_info, "audio-folders", &audio_folders, NULL); if (audio_folders != NULL && g_strv_length (audio_folders) > 0) { folders = g_strdup (audio_folders[0]); } else { folders = ""; } g_strfreev (audio_folders); mount_path = rb_generic_player_source_get_mount_path (RB_GENERIC_PLAYER_SOURCE (target)); path = g_build_filename (mount_path, folders, file, NULL); g_free (file); g_free (mount_path); /* TODO: check for duplicates, or just overwrite by default? */ rb_debug ("dest file is %s", path); return path; }
static gboolean rb_tree_dnd_drag_motion_cb (GtkWidget *widget, GdkDragContext *context, gint x, gint y, guint time) { GtkTreeView *tree_view; GtkTreePath *path = NULL; GtkTreeModel *model; GtkTreeViewDropPosition pos; RbTreeDndData *priv_data; GdkDragAction action; rb_debug ("drag and drop motion: (%i,%i)", x, y); tree_view = GTK_TREE_VIEW (widget); model = gtk_tree_view_get_model (tree_view); priv_data = g_object_get_data (G_OBJECT (widget), RB_TREE_DND_STRING); gtk_tree_view_get_dest_row_at_pos (tree_view, x, y, &path, &pos); if ((priv_data->previous_dest_path == NULL) || (path == NULL) || gtk_tree_path_compare(path,priv_data->previous_dest_path)) { remove_select_on_drag_timeout(tree_view); } if (path == NULL) { gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (widget), NULL, GTK_TREE_VIEW_DROP_BEFORE); if (!(priv_data->dest_flags & RB_TREE_DEST_EMPTY_VIEW_DROP)) { /* Can't drop here. */ gdk_drag_status (context, 0, time); return TRUE; } else if (!filter_drop_position (widget, context, path, &pos)) { gdk_drag_status (context, 0, time); return TRUE; } } else { if (!filter_drop_position (widget, context, path, &pos)) { gdk_drag_status (context, 0, time); return TRUE; } if (priv_data->scroll_timeout == 0) { priv_data->scroll_timeout = g_timeout_add (150, scroll_row_timeout, tree_view); } } if (GTK_WIDGET (tree_view) == gtk_drag_get_source_widget (context) && context->actions & GDK_ACTION_MOVE) action = GDK_ACTION_MOVE; else action = context->suggested_action; if (path) { gtk_tree_view_set_drag_dest_row (tree_view, path, pos); if (priv_data->dest_flags & RB_TREE_DEST_SELECT_ON_DRAG_TIMEOUT) { if (priv_data->previous_dest_path != NULL) { gtk_tree_path_free (priv_data->previous_dest_path); } priv_data->previous_dest_path = path; if (priv_data->select_on_drag_timeout == 0) { rb_debug("Setting up a new select on drag timeout"); priv_data->select_on_drag_timeout = g_timeout_add_seconds (2, select_on_drag_timeout, tree_view); } } else { gtk_tree_path_free (path); } } gdk_drag_status (context, action, time); return TRUE; }
static gboolean emit_status_changed (RhythmDBImportJob *job) { g_mutex_lock (&job->priv->lock); job->priv->status_changed_id = 0; rb_debug ("emitting status changed: %d/%d", job->priv->processed, job->priv->total); g_signal_emit (job, signals[STATUS_CHANGED], 0, job->priv->total, job->priv->processed); g_object_notify (G_OBJECT (job), "task-progress"); g_object_notify (G_OBJECT (job), "task-detail"); /* temporary ref while emitting this signal as we're expecting the caller * to release the final reference there. */ g_object_ref (job); if (job->priv->scan_complete && job->priv->processed >= job->priv->total) { if (job->priv->retry_entries != NULL && job->priv->retried == FALSE) { gboolean processing = FALSE; char **details = NULL; GClosure *retry; GSList *l; int i; /* gather missing plugin details etc. */ i = 0; for (l = job->priv->retry_entries; l != NULL; l = l->next) { RhythmDBEntry *entry; char **bits; int j; entry = (RhythmDBEntry *)l->data; bits = g_strsplit (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_COMMENT), "\n", 0); for (j = 0; bits[j] != NULL; j++) { if (rb_str_in_strv (bits[j], (const char **)details) == FALSE) { details = g_realloc (details, sizeof (char *) * (i+2)); details[i++] = g_strdup (bits[j]); details[i] = NULL; } } g_strfreev (bits); } retry = g_cclosure_new ((GCallback) missing_plugins_retry_cb, g_object_ref (job), (GClosureNotify)g_object_unref); g_closure_set_marshal (retry, g_cclosure_marshal_VOID__BOOLEAN); processing = rb_missing_plugins_install ((const char **)details, FALSE, retry); g_strfreev (details); if (processing) { rb_debug ("plugin installation is in progress"); } else { rb_debug ("no plugin installation attempted; job complete"); job->priv->complete = TRUE; g_signal_emit (job, signals[COMPLETE], 0, job->priv->total); g_object_notify (G_OBJECT (job), "task-outcome"); } g_closure_sink (retry); } else { rb_debug ("emitting job complete"); job->priv->complete = TRUE; g_signal_emit (job, signals[COMPLETE], 0, job->priv->total); g_object_notify (G_OBJECT (job), "task-outcome"); } } else if (g_cancellable_is_cancelled (job->priv->cancel) && g_queue_is_empty (job->priv->processing)) { rb_debug ("cancelled job has no processing entries, emitting complete"); job->priv->complete = TRUE; g_signal_emit (job, signals[COMPLETE], 0, job->priv->total); g_object_notify (G_OBJECT (job), "task-outcome"); } g_mutex_unlock (&job->priv->lock); g_object_unref (job); return FALSE; }
static void rb_removable_media_manager_add_mount (RBRemovableMediaManager *mgr, GMount *mount) { RBRemovableMediaManagerPrivate *priv = GET_PRIVATE (mgr); RBRemovableMediaSource *source = NULL; GVolume *volume; GFile *mount_root; char *mountpoint; MPIDDevice *device_info; g_assert (mount != NULL); if (g_hash_table_lookup (priv->mount_mapping, mount) != NULL) { return; } #if GLIB_CHECK_VERSION(2, 20, 0) if (g_mount_is_shadowed (mount) != FALSE) { return; } #endif volume = g_mount_get_volume (mount); if (volume == NULL) { rb_debug ("Unhandled media, no volume for mount"); return; } /* if we've already created a source for the volume, * don't do anything with the mount. */ if (g_hash_table_lookup (priv->volume_mapping, volume) != NULL) { rb_debug ("already created a source for the volume, so ignoring the mount"); g_object_unref (volume); return; } dump_volume_identifiers (volume); g_object_unref (volume); /* look the device up in the device info database */ mount_root = g_mount_get_root (mount); if (mount_root == NULL) { rb_debug ("unable to get mount root, can't create a source for this mount"); return; } mountpoint = g_file_get_path (mount_root); g_object_unref (mount_root); device_info = mpid_device_new (mountpoint); g_free (mountpoint); g_signal_emit (G_OBJECT (mgr), rb_removable_media_manager_signals[CREATE_SOURCE_MOUNT], 0, mount, device_info, &source); if (source) { g_hash_table_insert (priv->mount_mapping, mount, source); rb_removable_media_manager_append_media_source (mgr, RB_SOURCE (source)); } else { rb_debug ("Unhandled media"); } g_object_unref (device_info); }
static void rb_grilo_plugin_init (RBGriloPlugin *plugin) { rb_debug ("RBGriloPlugin initialising"); }
static gboolean start_next (RBTrackTransferBatch *batch) { GstEncodingProfile *profile = NULL; if (batch->priv->cancelled == TRUE) { return FALSE; } if (batch->priv->entries == NULL) { /* guess we must be done.. */ g_signal_emit (batch, signals[COMPLETE], 0); return FALSE; } batch->priv->current_fraction = 0.0; rb_debug ("%d entries remain in the batch", g_list_length (batch->priv->entries)); while ((batch->priv->entries != NULL) && (batch->priv->cancelled == FALSE)) { RhythmDBEntry *entry; guint64 filesize; gulong duration; double fraction; GList *n; char *media_type; char *extension; n = batch->priv->entries; batch->priv->entries = g_list_remove_link (batch->priv->entries, n); entry = (RhythmDBEntry *)n->data; g_list_free_1 (n); rb_debug ("attempting to transfer %s", rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION)); /* calculate the fraction of the transfer that this entry represents */ filesize = rhythmdb_entry_get_uint64 (entry, RHYTHMDB_PROP_FILE_SIZE); duration = rhythmdb_entry_get_ulong (entry, RHYTHMDB_PROP_DURATION); if (batch->priv->total_duration > 0) { g_assert (duration > 0); /* otherwise total_duration would be 0 */ fraction = ((double)duration) / (double) batch->priv->total_duration; } else if (batch->priv->total_size > 0) { g_assert (filesize > 0); /* otherwise total_size would be 0 */ fraction = ((double)filesize) / (double) batch->priv->total_size; } else { int count = g_list_length (batch->priv->entries) + g_list_length (batch->priv->done_entries) + 1; fraction = 1.0 / ((double)count); } profile = NULL; if (select_profile_for_entry (batch, entry, &profile, FALSE) == FALSE) { rb_debug ("skipping entry %s, can't find an encoding profile", rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION)); rhythmdb_entry_unref (entry); batch->priv->total_fraction += fraction; continue; } if (profile != NULL) { media_type = rb_gst_encoding_profile_get_media_type (profile); extension = g_strdup (rb_gst_media_type_to_extension (media_type)); rb_gst_encoding_profile_set_preset (profile, NULL); g_signal_emit (batch, signals[CONFIGURE_PROFILE], 0, media_type, profile); } else { media_type = rhythmdb_entry_dup_string (entry, RHYTHMDB_PROP_MEDIA_TYPE); extension = g_strdup (rb_gst_media_type_to_extension (media_type)); if (extension == NULL) { extension = get_extension_from_location (entry); } } g_free (batch->priv->current_dest_uri); batch->priv->current_dest_uri = NULL; g_signal_emit (batch, signals[GET_DEST_URI], 0, entry, media_type, extension, &batch->priv->current_dest_uri); g_free (media_type); g_free (extension); if (batch->priv->current_dest_uri == NULL) { rb_debug ("unable to build destination URI for %s, skipping", rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION)); rhythmdb_entry_unref (entry); batch->priv->total_fraction += fraction; continue; } batch->priv->current = entry; batch->priv->current_entry_fraction = fraction; batch->priv->current_profile = profile; break; } if (batch->priv->current != NULL) { g_signal_emit (batch, signals[TRACK_STARTED], 0, batch->priv->current, batch->priv->current_dest_uri); start_encoding (batch, FALSE); } return TRUE; }
/** * rb_track_transfer_batch_check_profiles: * @batch: a #RBTrackTransferBatch * @missing_plugin_profiles: holds a #GList of #GstEncodingProfiles on return * @error_count: holds the number of entries that cannot be transferred on return * * Checks that all entries in the batch can be transferred in a format * supported by the destination. If no encoding profile is available for * some entries, but installing additional plugins could make a profile * available, a list of profiles that require additional plugins is returned. * * Return value: %TRUE if some entries can be transferred without additional plugins */ gboolean rb_track_transfer_batch_check_profiles (RBTrackTransferBatch *batch, GList **missing_plugin_profiles, int *error_count) { RBEncoder *encoder = rb_encoder_new (); gboolean ret = FALSE; const GList *l; rb_debug ("checking profiles"); /* first, figure out which profiles that we care about would require additional plugins to use */ g_list_free (batch->priv->missing_plugin_profiles); batch->priv->missing_plugin_profiles = NULL; for (l = gst_encoding_target_get_profiles (batch->priv->target); l != NULL; l = l->next) { GstEncodingProfile *profile = GST_ENCODING_PROFILE (l->data); char *profile_media_type; profile_media_type = rb_gst_encoding_profile_get_media_type (profile); if (profile_media_type != NULL && (rb_gst_media_type_is_lossless (profile_media_type) == FALSE) && rb_encoder_get_missing_plugins (encoder, profile, NULL, NULL)) { batch->priv->missing_plugin_profiles = g_list_append (batch->priv->missing_plugin_profiles, profile); } g_free (profile_media_type); } g_object_unref (encoder); rb_debug ("have %d profiles with missing plugins", g_list_length (batch->priv->missing_plugin_profiles)); for (l = batch->priv->entries; l != NULL; l = l->next) { RhythmDBEntry *entry = (RhythmDBEntry *)l->data; GstEncodingProfile *profile; profile = NULL; if (select_profile_for_entry (batch, entry, &profile, FALSE) == TRUE) { if (profile != NULL) { rb_debug ("found profile %s for %s", gst_encoding_profile_get_name (profile), rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION)); } else { rb_debug ("copying entry %s", rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION)); } ret = TRUE; continue; } (*error_count)++; if (select_profile_for_entry (batch, entry, &profile, TRUE) == FALSE) { rb_debug ("unable to transfer %s (media type %s)", rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION), rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_MEDIA_TYPE)); } else { rb_debug ("require additional plugins to transfer %s (media type %s)", rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION), rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_MEDIA_TYPE)); if (*missing_plugin_profiles == NULL) { *missing_plugin_profiles = g_list_copy (batch->priv->missing_plugin_profiles); } } } return ret; }
static void podcast_search_result_cb (RBPodcastSearch *search, RBPodcastChannel *feed, RBPodcastAddDialog *dialog) { rb_debug ("got result %s from podcast search %s", feed->url, G_OBJECT_TYPE_NAME (search)); insert_search_result (dialog, rb_podcast_parse_channel_copy (feed), FALSE); }
static void rhythmdb_directory_change_cb (GFileMonitor *monitor, GFile *file, GFile *other_file, GFileMonitorEvent event_type, RhythmDB *db) { char *canon_uri; char *other_canon_uri = NULL; RhythmDBEntry *entry; canon_uri = g_file_get_uri (file); if (other_file != NULL) { other_canon_uri = g_file_get_uri (other_file); } rb_debug ("directory event %d for %s", event_type, canon_uri); switch (event_type) { case G_FILE_MONITOR_EVENT_CREATED: { gboolean in_library = FALSE; int i; if (!g_settings_get_boolean (db->priv->settings, "monitor-library")) break; if (rb_uri_is_hidden (canon_uri)) break; /* ignore new files outside of the library locations */ for (i = 0; db->priv->library_locations[i] != NULL; i++) { if (g_str_has_prefix (canon_uri, db->priv->library_locations[i])) { in_library = TRUE; break; } } if (!in_library) break; } /* process directories immediately */ if (rb_uri_is_directory (canon_uri)) { actually_add_monitor (db, file, NULL); rhythmdb_add_uri (db, canon_uri); } else { add_changed_file (db, canon_uri); } break; case G_FILE_MONITOR_EVENT_CHANGED: case G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED: if (rhythmdb_entry_lookup_by_location (db, canon_uri)) { add_changed_file (db, canon_uri); } break; case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT: /* hmm.. */ break; case G_FILE_MONITOR_EVENT_DELETED: entry = rhythmdb_entry_lookup_by_location (db, canon_uri); if (entry != NULL) { g_hash_table_remove (db->priv->changed_files, entry->location); rhythmdb_entry_set_visibility (db, entry, FALSE); rhythmdb_commit (db); } break; case G_FILE_MONITOR_EVENT_MOVED: if (other_canon_uri == NULL) { break; } entry = rhythmdb_entry_lookup_by_location (db, other_canon_uri); if (entry != NULL) { rb_debug ("file move target %s already exists in database", other_canon_uri); entry = rhythmdb_entry_lookup_by_location (db, canon_uri); if (entry != NULL) { g_hash_table_remove (db->priv->changed_files, entry->location); rhythmdb_entry_set_visibility (db, entry, FALSE); rhythmdb_commit (db); } } else { entry = rhythmdb_entry_lookup_by_location (db, canon_uri); if (entry != NULL) { GValue v = {0,}; g_value_init (&v, G_TYPE_STRING); g_value_set_string (&v, other_canon_uri); rhythmdb_entry_set_internal (db, entry, TRUE, RHYTHMDB_PROP_LOCATION, &v); g_value_unset (&v); } } break; case G_FILE_MONITOR_EVENT_PRE_UNMOUNT: case G_FILE_MONITOR_EVENT_UNMOUNTED: default: break; } g_free (canon_uri); g_free (other_canon_uri); }
int main (int argc, char **argv) { ServiceData svc = {0,}; GError *error = NULL; const char *address = NULL; char *guid; #ifdef ENABLE_NLS /* initialize i18n */ bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR); bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); textdomain (GETTEXT_PACKAGE); #endif g_type_init (); gst_init (NULL, NULL); g_set_prgname ("rhythmbox-metadata"); if (argv[1] != NULL && strcmp(argv[1], "--debug") == 0) { argv++; rb_debug_init (TRUE); } else if (argv[1] != NULL && strcmp (argv[1], "--debug-match") == 0) { rb_debug_init_match (argv[2]); argv += 2; } else { rb_debug_init (FALSE); } /* bug report modes */ if (argv[1] != NULL && strcmp(argv[1], "--load") == 0) { return test_load (argv[2]); } if (argv[1] != NULL && strcmp(argv[1], "--saveable-types") == 0) { return test_saveable_types (); } if (argv[1] != NULL && strcmp (argv[1], "--external") == 0) { argv++; svc.external = TRUE; } if (argv[1] == NULL) { address = "unix:tmpdir=/tmp"; } else { address = argv[1]; } rb_debug ("initializing metadata service; pid = %d; address = %s", getpid (), address); svc.metadata = rb_metadata_new (); svc.loop = g_main_loop_new (NULL, TRUE); /* create the server */ guid = g_dbus_generate_guid (); svc.server = g_dbus_server_new_sync (address, G_DBUS_SERVER_FLAGS_NONE, guid, NULL, NULL, &error); g_free (guid); if (error != NULL) { g_warning ("D-Bus server init failed: %s", error->message); return -1; } /* set up interface info */ svc.node_info = g_dbus_node_info_new_for_xml (rb_metadata_iface_xml, &error); if (error != NULL) { g_warning ("D-Bus server init failed: %s", error->message); return -1; } g_signal_connect (svc.server, "new-connection", G_CALLBACK (new_connection_cb), &svc); g_dbus_server_start (svc.server); /* write the server address back to the parent process */ { const char *addr; addr = g_dbus_server_get_client_address (svc.server); rb_debug ("D-BUS server listening on address %s", addr); printf ("%s\n", addr); fflush (stdout); } /* run main loop until we get bored */ if (!svc.external) g_timeout_add_seconds (ATTENTION_SPAN / 2, (GSourceFunc) electromagnetic_shotgun, &svc); g_main_loop_run (svc.loop); if (svc.connection) { g_dbus_connection_close_sync (svc.connection, NULL, NULL); g_object_unref (svc.connection); } g_object_unref (svc.metadata); g_main_loop_unref (svc.loop); g_dbus_server_stop (svc.server); g_object_unref (svc.server); gst_deinit (); return 0; }
static void default_eject (RBDeviceSource *source) { GVolume *volume = NULL; GMount *mount = NULL; if (g_object_class_find_property (G_OBJECT_GET_CLASS (source), "volume")) { g_object_get (source, "volume", &volume, NULL); } if (g_object_class_find_property (G_OBJECT_GET_CLASS (source), "mount")) { g_object_get (source, "mount", &mount, NULL); } /* try ejecting based on volume first, then based on the mount, * and finally try unmounting. */ if (volume != NULL) { if (g_volume_can_eject (volume)) { rb_debug ("ejecting volume"); g_volume_eject_with_operation (volume, G_MOUNT_UNMOUNT_NONE, NULL, NULL, (GAsyncReadyCallback) eject_cb, NULL); } else { /* this should never happen; the eject command will be * insensitive if the selected source cannot be ejected. */ rb_debug ("don't know what to do with this volume"); } } else if (mount != NULL) { if (g_mount_can_eject (mount)) { rb_debug ("ejecting mount"); g_mount_eject_with_operation (mount, G_MOUNT_UNMOUNT_NONE, NULL, NULL, (GAsyncReadyCallback) eject_cb, NULL); } else if (g_mount_can_unmount (mount)) { rb_debug ("unmounting mount"); g_mount_unmount_with_operation (mount, G_MOUNT_UNMOUNT_NONE, NULL, NULL, (GAsyncReadyCallback) unmount_cb, NULL); } else { /* this should never happen; the eject command will be * insensitive if the selected source cannot be ejected. */ rb_debug ("don't know what to do with this mount"); } } if (volume != NULL) { g_object_unref (volume); } if (mount != NULL) { g_object_unref (mount); } }
static gboolean bus_cb (GstBus *bus, GstMessage *message, RBPlayerGst *mp) { const GstStructure *structure; g_return_val_if_fail (mp != NULL, FALSE); switch (GST_MESSAGE_TYPE (message)) { case GST_MESSAGE_ERROR: { char *debug; GError *error = NULL; GError *sig_error = NULL; int code; gboolean emit = TRUE; gst_message_parse_error (message, &error, &debug); /* If we've already got an error, ignore 'internal data flow error' * type messages, as they're too generic to be helpful. */ if (mp->priv->emitted_error && error->domain == GST_STREAM_ERROR && error->code == GST_STREAM_ERROR_FAILED) { rb_debug ("Ignoring generic error \"%s\"", error->message); emit = FALSE; } code = rb_gst_error_get_error_code (error); if (emit) { if (message_from_sink (mp->priv->audio_sink, message)) { rb_debug ("got error from sink: %s (%s)", error->message, debug); /* Translators: the parameter here is an error message */ g_set_error (&sig_error, RB_PLAYER_ERROR, code, _("Failed to open output device: %s"), error->message); } else { rb_debug ("got error from stream: %s (%s)", error->message, debug); g_set_error (&sig_error, RB_PLAYER_ERROR, code, "%s", error->message); } state_change_finished (mp, sig_error); mp->priv->emitted_error = TRUE; if (mp->priv->playbin_stream_changing) { emit_playing_stream_and_tags (mp, TRUE); } _rb_player_emit_error (RB_PLAYER (mp), mp->priv->stream_data, sig_error); } /* close if not already closing */ if (mp->priv->uri != NULL) rb_player_close (RB_PLAYER (mp), NULL, NULL); g_error_free (error); g_free (debug); break; } case GST_MESSAGE_EOS: _rb_player_emit_eos (RB_PLAYER (mp), mp->priv->stream_data, FALSE); break; case GST_MESSAGE_STATE_CHANGED: { GstState oldstate; GstState newstate; GstState pending; gst_message_parse_state_changed (message, &oldstate, &newstate, &pending); if (GST_MESSAGE_SRC (message) == GST_OBJECT (mp->priv->playbin)) { if (pending == GST_STATE_VOID_PENDING) { rb_debug ("playbin reached state %s", gst_element_state_get_name (newstate)); state_change_finished (mp, NULL); } } break; } case GST_MESSAGE_TAG: { GstTagList *tags; gst_message_parse_tag (message, &tags); if (mp->priv->stream_change_pending || mp->priv->playbin_stream_changing) { mp->priv->stream_tags = g_list_append (mp->priv->stream_tags, tags); } else { gst_tag_list_foreach (tags, (GstTagForeachFunc) process_tag, mp); gst_tag_list_free (tags); } break; } case GST_MESSAGE_BUFFERING: { gint progress; structure = gst_message_get_structure (message); if (!gst_structure_get_int (structure, "buffer-percent", &progress)) { g_warning ("Could not get value from BUFFERING message"); break; } if (progress >= 100) { mp->priv->buffering = FALSE; if (mp->priv->playing) { rb_debug ("buffering done, setting pipeline back to PLAYING"); gst_element_set_state (mp->priv->playbin, GST_STATE_PLAYING); } else { rb_debug ("buffering done, leaving pipeline PAUSED"); } } else if (mp->priv->buffering == FALSE && mp->priv->playing) { rb_debug ("buffering - temporarily pausing playback"); gst_element_set_state (mp->priv->playbin, GST_STATE_PAUSED); mp->priv->buffering = TRUE; } _rb_player_emit_buffering (RB_PLAYER (mp), mp->priv->stream_data, progress); break; } case GST_MESSAGE_APPLICATION: structure = gst_message_get_structure (message); _rb_player_emit_event (RB_PLAYER (mp), mp->priv->stream_data, gst_structure_get_name (structure), NULL); break; case GST_MESSAGE_ELEMENT: structure = gst_message_get_structure (message); if (gst_is_missing_plugin_message (message)) { handle_missing_plugin_message (mp, message); } else if (mp->priv->playbin_stream_changing && gst_structure_has_name (structure, "playbin2-stream-changed")) { rb_debug ("got playbin2-stream-changed message"); mp->priv->playbin_stream_changing = FALSE; emit_playing_stream_and_tags (mp, TRUE); } else if (gst_structure_has_name (structure, "redirect")) { const char *uri = gst_structure_get_string (structure, "new-location"); _rb_player_emit_redirect (RB_PLAYER (mp), mp->priv->stream_data, uri); } break; default: break; } /* emit message signals too, so plugins can process messages */ gst_bus_async_signal_func (bus, message, NULL); return TRUE; }
static void rb_gpm_plugin_init (RBGPMPlugin *plugin) { rb_debug ("RBGPMPlugin initialising"); }
static gboolean construct_pipeline (RBPlayerGst *mp, GError **error) { GstElement *sink; mp->priv->playbin = gst_element_factory_make ("playbin2", NULL); if (mp->priv->playbin == NULL) { g_set_error (error, RB_PLAYER_ERROR, RB_PLAYER_ERROR_GENERAL, _("Failed to create %s element; check your GStreamer installation"), "playbin2"); return FALSE; } g_signal_connect_object (G_OBJECT (mp->priv->playbin), "about-to-finish", G_CALLBACK (about_to_finish_cb), mp, 0); g_signal_connect_object (G_OBJECT (mp->priv->playbin), "deep-notify::volume", G_CALLBACK (volume_notify_cb), mp, 0); g_signal_connect_object (G_OBJECT (mp->priv->playbin), "notify::source", G_CALLBACK (source_notify_cb), mp, 0); gst_bus_add_watch (gst_element_get_bus (mp->priv->playbin), (GstBusFunc) bus_cb, mp); /* let plugins add bits to playbin */ g_object_notify (G_OBJECT (mp), "playbin"); g_object_notify (G_OBJECT (mp), "bus"); /* Use gsettingsaudiosink for audio if there's no audio sink yet */ g_object_get (mp->priv->playbin, "audio-sink", &mp->priv->audio_sink, NULL); if (mp->priv->audio_sink == NULL) { const char *try_sinks[] = { "gsettingsaudiosink", "gconfaudiosink", "autoaudiosink" }; int i; for (i = 0; i < G_N_ELEMENTS (try_sinks); i++) { mp->priv->audio_sink = rb_player_gst_try_audio_sink (try_sinks[i], NULL); if (mp->priv->audio_sink != NULL) { g_object_set (mp->priv->playbin, "audio-sink", mp->priv->audio_sink, NULL); break; } } if (mp->priv->audio_sink == NULL) { g_set_error (error, RB_PLAYER_ERROR, RB_PLAYER_ERROR_GENERAL, _("Failed to create %s element; check your GStreamer installation"), "autoaudiosink"); return FALSE; } } else { rb_debug ("existing audio sink found"); g_object_unref (mp->priv->audio_sink); } { GstPad *pad; GList *l; GstElement *queue; GstPad *ghostpad; /* setup filterbin */ mp->priv->filterbin = rb_gst_create_filter_bin (); /* set up the sinkbin with its tee element */ mp->priv->sinkbin = gst_bin_new (NULL); mp->priv->tee = gst_element_factory_make ("tee", NULL); queue = gst_element_factory_make ("queue", NULL); /* link it all together and insert */ gst_bin_add_many (GST_BIN (mp->priv->sinkbin), mp->priv->filterbin, mp->priv->tee, queue, mp->priv->audio_sink, NULL); gst_element_link_many (mp->priv->filterbin, mp->priv->tee, queue, mp->priv->audio_sink, NULL); pad = gst_element_get_pad (mp->priv->filterbin, "sink"); ghostpad = gst_ghost_pad_new ("sink", pad); gst_element_add_pad (mp->priv->sinkbin, ghostpad); gst_object_unref (pad); g_object_set (G_OBJECT (mp->priv->playbin), "audio-sink", mp->priv->sinkbin, NULL); /* add any tees and filters that were waiting for us */ for (l = mp->priv->waiting_tees; l != NULL; l = g_list_next (l)) { rb_player_gst_tee_add_tee (RB_PLAYER_GST_TEE (mp), GST_ELEMENT (l->data)); } g_list_free (mp->priv->waiting_tees); mp->priv->waiting_tees = NULL; for (l = mp->priv->waiting_filters; l != NULL; l = g_list_next (l)) { rb_player_gst_filter_add_filter (RB_PLAYER_GST_FILTER(mp), GST_ELEMENT (l->data)); } g_list_free (mp->priv->waiting_filters); mp->priv->waiting_filters = NULL; } /* Use fakesink for video if there's no video sink yet */ g_object_get (mp->priv->playbin, "video-sink", &sink, NULL); if (sink == NULL) { sink = gst_element_factory_make ("fakesink", NULL); g_object_set (mp->priv->playbin, "video-sink", sink, NULL); } else { g_object_unref (sink); } if (mp->priv->cur_volume > 1.0) mp->priv->cur_volume = 1.0; if (mp->priv->cur_volume < 0.0) mp->priv->cur_volume = 0; rb_debug ("pipeline construction complete"); return TRUE; }
static void impl_show_properties (RBMediaPlayerSource *source, GtkWidget *info_box, GtkWidget *notebook) { RBGenericPlayerSourcePrivate *priv = GET_PRIVATE (source); RhythmDBQueryModel *model; GtkBuilder *builder; GtkWidget *widget; GString *str; char *device_name; char *builder_file; char *vendor_name; char *model_name; char *serial_id; GObject *plugin; char *text; GList *output_formats; GList *t; g_object_get (source, "plugin", &plugin, NULL); builder_file = rb_find_plugin_data_file (plugin, "generic-player-info.ui"); g_object_unref (plugin); if (builder_file == NULL) { g_warning ("Couldn't find generic-player-info.ui"); return; } builder = rb_builder_load (builder_file, NULL); g_free (builder_file); if (builder == NULL) { rb_debug ("Couldn't load generic-player-info.ui"); return; } /* 'basic' tab stuff */ widget = GTK_WIDGET (gtk_builder_get_object (builder, "generic-player-basic-info")); gtk_box_pack_start (GTK_BOX (info_box), widget, TRUE, TRUE, 0); widget = GTK_WIDGET (gtk_builder_get_object (builder, "entry-device-name")); g_object_get (source, "name", &device_name, NULL); gtk_entry_set_text (GTK_ENTRY (widget), device_name); g_free (device_name); /* don't think we can support this.. g_signal_connect (widget, "focus-out-event", (GCallback)rb_mtp_source_name_changed_cb, source); */ g_object_get (source, "base-query-model", &model, NULL); widget = GTK_WIDGET (gtk_builder_get_object (builder, "num-tracks")); text = g_strdup_printf ("%d", gtk_tree_model_iter_n_children (GTK_TREE_MODEL (model), NULL)); gtk_label_set_text (GTK_LABEL (widget), text); g_free (text); g_object_unref (model); widget = GTK_WIDGET (gtk_builder_get_object (builder, "num-playlists")); text = g_strdup_printf ("%d", g_list_length (priv->playlists)); gtk_label_set_text (GTK_LABEL (widget), text); g_free (text); /* 'advanced' tab stuff */ widget = GTK_WIDGET (gtk_builder_get_object (builder, "generic-player-advanced-tab")); gtk_notebook_append_page (GTK_NOTEBOOK (notebook), widget, gtk_label_new (_("Advanced"))); g_object_get (priv->device_info, "model", &model_name, "vendor", &vendor_name, "serial", &serial_id, NULL); widget = GTK_WIDGET (gtk_builder_get_object (builder, "label-model-value")); gtk_label_set_text (GTK_LABEL (widget), model_name); widget = GTK_WIDGET (gtk_builder_get_object (builder, "label-manufacturer-value")); gtk_label_set_text (GTK_LABEL (widget), vendor_name); widget = GTK_WIDGET (gtk_builder_get_object (builder, "label-serial-number-value")); gtk_label_set_text (GTK_LABEL (widget), serial_id); g_free (model_name); g_free (vendor_name); g_free (serial_id); str = g_string_new (""); output_formats = rb_transfer_target_get_format_descriptions (RB_TRANSFER_TARGET (source)); for (t = output_formats; t != NULL; t = t->next) { if (t != output_formats) { g_string_append (str, "\n"); } g_string_append (str, t->data); } rb_list_deep_free (output_formats); widget = GTK_WIDGET (gtk_builder_get_object (builder, "audio-format-list")); gtk_label_set_text (GTK_LABEL (widget), str->str); g_string_free (str, TRUE); g_object_unref (builder); }
static void rb_generic_player_plugin_init (RBGenericPlayerPlugin *plugin) { rb_debug ("RBGenericPlayerPlugin initialising"); }
static void start_deferred_scan (RhythmDBImportJob *job, int total, RBImportDialog *dialog) { rb_debug ("previous import job finished"); start_scanning (dialog); }
gchar* rb_search_fold (const char *original) { GString *string; gchar *normalized; gunichar *unicode, *cur; g_return_val_if_fail (original != NULL, NULL); /* old behaviour is equivalent to: return g_utf8_casefold (original, -1); */ string = g_string_new (NULL); normalized = g_utf8_normalize(original, -1, G_NORMALIZE_DEFAULT); unicode = g_utf8_to_ucs4_fast (normalized, -1, NULL); for (cur = unicode; *cur != 0; cur++) { switch (g_unichar_type (*cur)) { case G_UNICODE_COMBINING_MARK: case G_UNICODE_ENCLOSING_MARK: case G_UNICODE_NON_SPACING_MARK: case G_UNICODE_CONNECT_PUNCTUATION: case G_UNICODE_DASH_PUNCTUATION: case G_UNICODE_CLOSE_PUNCTUATION: case G_UNICODE_FINAL_PUNCTUATION: case G_UNICODE_INITIAL_PUNCTUATION: case G_UNICODE_OTHER_PUNCTUATION: case G_UNICODE_OPEN_PUNCTUATION: /* remove these */ break; case G_UNICODE_LOWERCASE_LETTER: case G_UNICODE_MODIFIER_LETTER: case G_UNICODE_OTHER_LETTER: case G_UNICODE_TITLECASE_LETTER: case G_UNICODE_UPPERCASE_LETTER: /* convert to lower case */ *cur = g_unichar_tolower (*cur); /* ... and fall through */\ case G_UNICODE_DECIMAL_NUMBER: case G_UNICODE_LETTER_NUMBER: case G_UNICODE_OTHER_NUMBER: /* should be keep symbols? */ case G_UNICODE_CURRENCY_SYMBOL: case G_UNICODE_MODIFIER_SYMBOL: case G_UNICODE_MATH_SYMBOL: case G_UNICODE_OTHER_SYMBOL: g_string_append_unichar (string, *cur); break; case G_UNICODE_UNASSIGNED: rb_debug ("unassigned unicode character type found"); /* fall through */ default: /* leave these in */ g_string_append_unichar (string, *cur); } } g_free (unicode); g_free (normalized); return g_string_free (string, FALSE); }
static void impl_show_properties (RBMediaPlayerSource *source, GtkWidget *info_box, GtkWidget *notebook) { RBMtpSourcePrivate *priv = MTP_SOURCE_GET_PRIVATE (source); GtkBuilder *builder; GtkWidget *widget; GHashTableIter iter; gpointer key, value; int num_podcasts; char *device_name; char *builder_file; RBPlugin *plugin; char *text; GList *output_formats; GList *t; GString *str; g_object_get (source, "plugin", &plugin, NULL); builder_file = rb_plugin_find_file (plugin, "mtp-info.ui"); g_object_unref (plugin); if (builder_file == NULL) { g_warning ("Couldn't find mtp-info.ui"); return; } builder = rb_builder_load (builder_file, NULL); g_free (builder_file); if (builder == NULL) { rb_debug ("Couldn't load mtp-info.ui"); return; } /* 'basic' tab stuff */ widget = GTK_WIDGET (gtk_builder_get_object (builder, "mtp-basic-info")); gtk_box_pack_start (GTK_BOX (info_box), widget, TRUE, TRUE, 0); widget = GTK_WIDGET (gtk_builder_get_object (builder, "entry-mtp-name")); g_object_get (source, "name", &device_name, NULL); gtk_entry_set_text (GTK_ENTRY (widget), device_name); g_free (device_name); g_signal_connect (widget, "focus-out-event", (GCallback)rb_mtp_source_name_changed_cb, source); num_podcasts = 0; g_hash_table_iter_init (&iter, priv->entry_map); while (g_hash_table_iter_next (&iter, &key, &value)) { LIBMTP_track_t *track = value; if (g_strcmp0 (track->genre, "Podcast") == 0) { num_podcasts++; } } widget = GTK_WIDGET (gtk_builder_get_object (builder, "mtp-num-tracks")); text = g_strdup_printf ("%d", g_hash_table_size (priv->entry_map) - num_podcasts); gtk_label_set_text (GTK_LABEL (widget), text); g_free (text); widget = GTK_WIDGET (gtk_builder_get_object (builder, "mtp-num-podcasts")); text = g_strdup_printf ("%d", num_podcasts); gtk_label_set_text (GTK_LABEL (widget), text); g_free (text); widget = GTK_WIDGET (gtk_builder_get_object (builder, "mtp-num-playlists")); text = g_strdup_printf ("%d", 0); /* correct, but wrong */ gtk_label_set_text (GTK_LABEL (widget), text); g_free (text); /* 'advanced' tab stuff */ widget = GTK_WIDGET (gtk_builder_get_object (builder, "mtp-advanced-tab")); gtk_notebook_append_page (GTK_NOTEBOOK (notebook), widget, gtk_label_new (_("Advanced"))); widget = GTK_WIDGET (gtk_builder_get_object (builder, "label-mtp-model-value")); gtk_label_set_text (GTK_LABEL (widget), priv->model_name); widget = GTK_WIDGET (gtk_builder_get_object (builder, "label-serial-number-value")); gtk_label_set_text (GTK_LABEL (widget), priv->serial); widget = GTK_WIDGET (gtk_builder_get_object (builder, "label-firmware-version-value")); gtk_label_set_text (GTK_LABEL (widget), priv->device_version); widget = GTK_WIDGET (gtk_builder_get_object (builder, "label-manufacturer-value")); gtk_label_set_text (GTK_LABEL (widget), priv->manufacturer); str = g_string_new (""); output_formats = rb_removable_media_source_get_format_descriptions (RB_REMOVABLE_MEDIA_SOURCE (source)); for (t = output_formats; t != NULL; t = t->next) { if (t != output_formats) { g_string_append (str, "\n"); } g_string_append (str, t->data); } rb_list_deep_free (output_formats); widget = GTK_WIDGET (gtk_builder_get_object (builder, "label-audio-formats-value")); gtk_label_set_text (GTK_LABEL (widget), str->str); g_string_free (str, TRUE); g_object_unref (builder); }
static void rb_mtp_sink_handle_message (GstBin *bin, GstMessage *message) { /* when we get an EOS message from the fdsink, close the fd and upload the * file to the device. */ if (GST_MESSAGE_TYPE (message) == GST_MESSAGE_EOS) { int fd; struct stat stat_buf; RBMTPSink *sink = RB_MTP_SINK (bin); /* fill in the file size and close the fd */ g_object_get (sink->fdsink, "fd", &fd, NULL); fstat (fd, &stat_buf); sink->track->filesize = stat_buf.st_size; close (fd); rb_debug ("handling EOS from fdsink; file size is %" G_GUINT64_FORMAT, sink->track->filesize); /* we can just block waiting for mtp thread operations to finish here * as we're on a streaming thread. */ g_mutex_lock (sink->upload_mutex); if (sink->folder_path != NULL) { /* find or create the target folder. * if this fails, we just upload to the default music folder * rather than giving up entirely. */ sink->got_folder = FALSE; rb_mtp_thread_create_folder (sink->device_thread, (const char **)sink->folder_path, (RBMtpCreateFolderCallback) folder_callback, g_object_ref (sink), g_object_unref); while (sink->got_folder == FALSE) { g_cond_wait (sink->upload_cond, sink->upload_mutex); } } /* and upload the file */ sink->upload_done = FALSE; rb_mtp_thread_upload_track (sink->device_thread, sink->track, sink->tempfile, (RBMtpUploadCallback) upload_callback, g_object_ref (sink), g_object_unref); while (sink->upload_done == FALSE) { g_cond_wait (sink->upload_cond, sink->upload_mutex); } g_mutex_unlock (sink->upload_mutex); /* post error message if the upload failed - this should get there before * this EOS message does, so it should work OK. */ if (sink->upload_error != NULL) { int code; switch (sink->upload_error->code) { case RB_MTP_THREAD_ERROR_NO_SPACE: code = GST_RESOURCE_ERROR_NO_SPACE_LEFT; break; default: case RB_MTP_THREAD_ERROR_SEND_TRACK: code = GST_RESOURCE_ERROR_WRITE; break; } GST_WARNING_OBJECT (sink, "error: %s", sink->upload_error->message); gst_element_message_full (GST_ELEMENT (sink), GST_MESSAGE_ERROR, GST_RESOURCE_ERROR, code, g_strdup (sink->upload_error->message), NULL, __FILE__, GST_FUNCTION, __LINE__); } } GST_BIN_CLASS (parent_class)->handle_message (bin, message); }
static RhythmDBEntry * add_mtp_track_to_db (RBMtpSource *source, RhythmDB *db, LIBMTP_track_t *track) { RhythmDBEntry *entry = NULL; RhythmDBEntryType entry_type; RBMtpSourcePrivate *priv = MTP_SOURCE_GET_PRIVATE (source); char *name = NULL; /* ignore everything except audio (allow audio/video types too, since they're probably pretty common) */ if (!(LIBMTP_FILETYPE_IS_AUDIO (track->filetype) || LIBMTP_FILETYPE_IS_AUDIOVIDEO (track->filetype))) { rb_debug ("ignoring non-audio item %d (filetype %s)", track->item_id, LIBMTP_Get_Filetype_Description (track->filetype)); return NULL; } /* Set URI */ g_object_get (G_OBJECT (source), "entry-type", &entry_type, NULL); name = g_strdup_printf ("xrbmtp://%i/%s", track->item_id, track->filename); entry = rhythmdb_entry_new (RHYTHMDB (db), entry_type, name); g_free (name); g_boxed_free (RHYTHMDB_TYPE_ENTRY_TYPE, entry_type); if (entry == NULL) { rb_debug ("cannot create entry %i", track->item_id); g_object_unref (G_OBJECT (db)); return NULL; } /* Set track number */ if (track->tracknumber != 0) { GValue value = {0, }; g_value_init (&value, G_TYPE_ULONG); g_value_set_ulong (&value, track->tracknumber); rhythmdb_entry_set (RHYTHMDB (db), entry, RHYTHMDB_PROP_TRACK_NUMBER, &value); g_value_unset (&value); } /* Set length */ if (track->duration != 0) { GValue value = {0, }; g_value_init (&value, G_TYPE_ULONG); g_value_set_ulong (&value, track->duration/1000); rhythmdb_entry_set (RHYTHMDB (db), entry, RHYTHMDB_PROP_DURATION, &value); g_value_unset (&value); } /* Set file size */ if (track->filesize != 0) { GValue value = {0, }; g_value_init (&value, G_TYPE_UINT64); g_value_set_uint64 (&value, track->filesize); rhythmdb_entry_set (RHYTHMDB (db), entry, RHYTHMDB_PROP_FILE_SIZE, &value); g_value_unset (&value); } /* Set playcount */ if (track->usecount != 0) { GValue value = {0, }; g_value_init (&value, G_TYPE_ULONG); g_value_set_ulong (&value, track->usecount); rhythmdb_entry_set (RHYTHMDB (db), entry, RHYTHMDB_PROP_PLAY_COUNT, &value); g_value_unset (&value); } /* Set rating */ if (track->rating != 0) { GValue value = {0, }; g_value_init (&value, G_TYPE_DOUBLE); g_value_set_double (&value, track->rating/20); rhythmdb_entry_set (RHYTHMDB (db), entry, RHYTHMDB_PROP_RATING, &value); g_value_unset (&value); } /* Set title */ entry_set_string_prop (RHYTHMDB (db), entry, RHYTHMDB_PROP_TITLE, track->title); /* Set album, artist and genre from MTP */ entry_set_string_prop (RHYTHMDB (db), entry, RHYTHMDB_PROP_ARTIST, track->artist); entry_set_string_prop (RHYTHMDB (db), entry, RHYTHMDB_PROP_ALBUM, track->album); entry_set_string_prop (RHYTHMDB (db), entry, RHYTHMDB_PROP_GENRE, track->genre); g_hash_table_insert (priv->entry_map, entry, track); rhythmdb_commit (RHYTHMDB (db)); return entry; }
static void got_session_key_cb (SoupSession *session, SoupMessage *msg, gpointer user_data) { /* parses the session details from the response. * if successful then authentication is complete. * if the error is that the token has not been authenticated * then keep trying. * on other errors stop trying and go to logged out state. */ RBAudioscrobblerAccount *account; JsonParser *parser; g_assert (RB_IS_AUDIOSCROBBLER_ACCOUNT (user_data)); account = RB_AUDIOSCROBBLER_ACCOUNT (user_data); parser = json_parser_new (); if (msg->response_body->data != NULL && json_parser_load_from_data (parser, msg->response_body->data, msg->response_body->length, NULL)) { JsonObject *root_object; root_object = json_node_get_object (json_parser_get_root (parser)); if (json_object_has_member (root_object, "session")) { JsonObject *session_object; /* cancel the old session (and remove timeout) */ cancel_session (account); session_object = json_object_get_object_member (root_object, "session"); account->priv->username = g_strdup (json_object_get_string_member (session_object, "name")); account->priv->session_key = g_strdup (json_object_get_string_member (session_object, "key")); rb_debug ("granted session key \"%s\" for user \"%s\"", account->priv->session_key, account->priv->username); /* save our session for future use */ save_session_settings (account); /* update status */ account->priv->login_status = RB_AUDIOSCROBBLER_ACCOUNT_LOGIN_STATUS_LOGGED_IN; g_signal_emit (account, rb_audioscrobbler_account_signals[LOGIN_STATUS_CHANGED], 0, account->priv->login_status); } else { int code; const char *message; code = json_object_get_int_member (root_object, "error"); message = json_object_get_string_member (root_object, "message"); switch (code) { case 14: rb_debug ("auth token has not been authorised yet. will try again"); break; default: /* some other error. most likely 4 (invalid token) or 15 (token has expired) * whatever it is, we wont be retrieving a session key from it */ rb_debug ("error retrieving session key: %s", message); /* go back to being logged out */ rb_audioscrobbler_account_logout (account); break; } } } else { /* treat as connection error */ rb_debug ("empty or invalid response retrieving session key. treating as connection error"); cancel_session (account); account->priv->login_status = RB_AUDIOSCROBBLER_ACCOUNT_LOGIN_STATUS_CONNECTION_ERROR; g_signal_emit (account, rb_audioscrobbler_account_signals[LOGIN_STATUS_CHANGED], 0, account->priv->login_status); } g_object_unref (parser); }
static void default_reset_filters (RBSource *source) { rb_debug ("no implementation of reset_filters for this source"); }
static gboolean start_next (RBTrackTransferBatch *batch) { char *media_type = NULL; char *extension = NULL; if (batch->priv->cancelled == TRUE) { return FALSE; } if (batch->priv->entries == NULL) { /* guess we must be done.. */ g_signal_emit (batch, signals[COMPLETE], 0); return FALSE; } batch->priv->current_fraction = 0.0; batch->priv->current_encoder = rb_encoder_new (); g_signal_connect_object (batch->priv->current_encoder, "progress", G_CALLBACK (encoder_progress_cb), batch, 0); g_signal_connect_object (batch->priv->current_encoder, "overwrite", G_CALLBACK (encoder_overwrite_cb), batch, 0); g_signal_connect_object (batch->priv->current_encoder, "completed", G_CALLBACK (encoder_completed_cb), batch, 0); rb_debug ("%d entries remain in the batch", g_list_length (batch->priv->entries)); while ((batch->priv->entries != NULL) && (batch->priv->cancelled == FALSE)) { RhythmDBEntry *entry; guint64 filesize; gulong duration; double fraction; GList *n; n = batch->priv->entries; batch->priv->entries = g_list_remove_link (batch->priv->entries, n); entry = (RhythmDBEntry *)n->data; g_list_free_1 (n); rb_debug ("attempting to transfer %s", rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION)); /* calculate the fraction of the transfer that this entry represents */ filesize = rhythmdb_entry_get_uint64 (entry, RHYTHMDB_PROP_FILE_SIZE); duration = rhythmdb_entry_get_ulong (entry, RHYTHMDB_PROP_DURATION); if (batch->priv->total_duration > 0) { g_assert (duration > 0); /* otherwise total_duration would be 0 */ fraction = ((double)duration) / (double) batch->priv->total_duration; } else if (batch->priv->total_size > 0) { g_assert (filesize > 0); /* otherwise total_size would be 0 */ fraction = ((double)filesize) / (double) batch->priv->total_size; } else { int count = g_list_length (batch->priv->entries) + g_list_length (batch->priv->done_entries) + 1; fraction = 1.0 / ((double)count); } g_free (media_type); g_free (extension); media_type = NULL; extension = NULL; if (rb_encoder_get_media_type (batch->priv->current_encoder, entry, batch->priv->media_types, &media_type, &extension) == FALSE) { rb_debug ("skipping entry %s, can't find a destination format", rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION)); rhythmdb_entry_unref (entry); batch->priv->total_fraction += fraction; continue; } g_free (batch->priv->current_dest_uri); batch->priv->current_dest_uri = NULL; g_signal_emit (batch, signals[GET_DEST_URI], 0, entry, media_type, extension, &batch->priv->current_dest_uri); if (batch->priv->current_dest_uri == NULL) { rb_debug ("unable to build destination URI for %s, skipping", rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION)); rhythmdb_entry_unref (entry); batch->priv->total_fraction += fraction; continue; } batch->priv->current = entry; batch->priv->current_entry_fraction = fraction; break; } if (batch->priv->current == NULL) { g_object_unref (batch->priv->current_encoder); batch->priv->current_encoder = NULL; } else { g_signal_emit (batch, signals[TRACK_STARTED], 0, batch->priv->current, batch->priv->current_dest_uri); rb_encoder_encode (batch->priv->current_encoder, batch->priv->current, batch->priv->current_dest_uri, media_type); } g_free (media_type); g_free (extension); return TRUE; }