static void rb_generic_player_plugin_new_playlist (GtkAction *action, RBSource *source) { RBShell *shell; RBSourceList *sourcelist; RBSource *playlist; RhythmDBEntryType *entry_type; g_return_if_fail (RB_IS_GENERIC_PLAYER_SOURCE (source)); g_object_get (source, "shell", &shell, "entry-type", &entry_type, NULL); playlist = rb_generic_player_playlist_source_new (shell, RB_GENERIC_PLAYER_SOURCE (source), NULL, NULL, entry_type); g_object_unref (entry_type); rb_generic_player_source_add_playlist (RB_GENERIC_PLAYER_SOURCE (source), shell, playlist); g_object_get (shell, "sourcelist", &sourcelist, NULL); rb_sourcelist_edit_source_name (sourcelist, playlist); g_object_unref (sourcelist); g_object_unref (shell); }
static void impl_add_playlist (RBMediaPlayerSource *source, char *name, GList *entries) { RBSource *playlist; RhythmDBEntryType *entry_type; RBShell *shell; GList *i; g_object_get (source, "shell", &shell, "entry-type", &entry_type, NULL); playlist = rb_generic_player_playlist_source_new (shell, RB_GENERIC_PLAYER_SOURCE (source), NULL, NULL, entry_type); g_object_unref (entry_type); rb_generic_player_source_add_playlist (RB_GENERIC_PLAYER_SOURCE (source), shell, playlist); g_object_set (playlist, "name", name, NULL); for (i = entries; i != NULL; i = i->next) { rb_static_playlist_source_add_entry (RB_STATIC_PLAYLIST_SOURCE (playlist), i->data, -1); } g_object_unref (shell); }
static void new_playlist_action_cb (GSimpleAction *action, GVariant *parameters, gpointer data) { RBGenericPlayerSource *source = RB_GENERIC_PLAYER_SOURCE (data); RBShell *shell; RBSource *playlist; RBDisplayPageTree *page_tree; RhythmDBEntryType *entry_type; GMenuModel *playlist_menu; g_object_get (source, "shell", &shell, "entry-type", &entry_type, "playlist-menu", &playlist_menu, NULL); playlist = rb_generic_player_playlist_source_new (shell, source, NULL, NULL, entry_type, playlist_menu); g_object_unref (entry_type); rb_generic_player_source_add_playlist (source, shell, playlist); g_object_get (shell, "display-page-tree", &page_tree, NULL); rb_display_page_tree_edit_source_name (page_tree, playlist); g_object_unref (page_tree); g_object_unref (playlist_menu); g_object_unref (shell); }
static RBTrackTransferBatch * impl_paste (RBSource *source, GList *entries) { gboolean defer; defer = (ensure_loaded (RB_GENERIC_PLAYER_SOURCE (source)) == FALSE); return rb_transfer_target_transfer (RB_TRANSFER_TARGET (source), entries, defer); }
static GObject * impl_constructor (GType type, guint n_construct_properties, GObjectConstructParam *construct_properties) { RBGenericPlayerSource *source; RBGenericPlayerSourcePrivate *priv; GMount *mount; char *mount_name; RBShell *shell; GFile *root; GFileInfo *info; GError *error = NULL; source = RB_GENERIC_PLAYER_SOURCE (G_OBJECT_CLASS (rb_generic_player_source_parent_class)-> constructor (type, n_construct_properties, construct_properties)); priv = GENERIC_PLAYER_SOURCE_GET_PRIVATE (source); g_object_get (source, "shell", &shell, NULL); g_object_get (shell, "db", &priv->db, NULL); priv->import_errors = rb_import_errors_source_new (shell, priv->error_type); g_object_unref (shell); g_object_get (source, "mount", &mount, NULL); root = g_mount_get_root (mount); mount_name = g_mount_get_name (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_unref (mount); priv->folder_depth = -1; /* 0 is a possible value, I guess */ priv->playlist_format_unknown = TRUE; get_device_info (source); load_songs (source); return G_OBJECT (source); }
static void impl_delete (RBSource *source) { RBEntryView *view; GList *sel; view = rb_source_get_entry_view (source); sel = rb_entry_view_get_selected_entries (view); rb_generic_player_source_delete_entries (RB_GENERIC_PLAYER_SOURCE (source), sel); g_list_foreach (sel, (GFunc)rhythmdb_entry_unref, NULL); g_list_free (sel); }
static RBTrackTransferBatch * impl_paste (RBSource *source, GList *entries) { gboolean defer; GSettings *settings; RBTrackTransferBatch *batch; defer = (ensure_loaded (RB_GENERIC_PLAYER_SOURCE (source)) == FALSE); g_object_get (source, "encoding-settings", &settings, NULL); batch = rb_transfer_target_transfer (RB_TRANSFER_TARGET (source), settings, entries, defer); g_object_unref (settings); return batch; }
static void default_load_playlists (RBGenericPlayerSource *source) { RBGenericPlayerSourcePrivate *priv = GET_PRIVATE (source); char *mount_path; char *playlist_path; char *full_playlist_path; char **playlist_formats; mount_path = rb_generic_player_source_get_mount_path (source); playlist_path = rb_generic_player_source_get_playlist_path (RB_GENERIC_PLAYER_SOURCE (source)); if (playlist_path) { /* If the device only supports a single playlist, just load that */ if (g_str_has_suffix (playlist_path, ".m3u") || g_str_has_suffix (playlist_path, ".pls")) { full_playlist_path = rb_uri_append_path (mount_path, playlist_path); if (rb_uri_exists (full_playlist_path)) { load_playlist_file (source, full_playlist_path, playlist_path); } g_free (full_playlist_path); g_free (playlist_path); return; } /* Otherwise, limit the search to the device's playlist folder */ full_playlist_path = rb_uri_append_path (mount_path, playlist_path); rb_debug ("constructed playlist search path %s", full_playlist_path); } else { g_free (playlist_path); return; } /* only try to load playlists if the device has at least one playlist format */ g_object_get (priv->device_info, "playlist-formats", &playlist_formats, NULL); if (playlist_formats != NULL && g_strv_length (playlist_formats) > 0) { rb_debug ("searching for playlists in %s", playlist_path); rb_uri_handle_recursively (full_playlist_path, NULL, (RBUriRecurseFunc) visit_playlist_dirs, source); } g_strfreev (playlist_formats); g_free (playlist_path); g_free (full_playlist_path); g_free (mount_path); }
RBRemovableMediaSource * rb_generic_player_source_new (RBShell *shell, GMount *mount) { RBGenericPlayerSource *source; RhythmDBEntryType entry_type; RhythmDBEntryType error_type; RhythmDBEntryType ignore_type; RhythmDB *db; GVolume *volume; char *name; char *path; g_assert (rb_generic_player_is_mount_player (mount)); volume = g_mount_get_volume (mount); g_object_get (G_OBJECT (shell), "db", &db, NULL); path = g_volume_get_identifier (volume, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE); name = g_strdup_printf ("generic audio player: %s", path); entry_type = rhythmdb_entry_register_type (db, name); g_free (name); name = g_strdup_printf ("generic audio player (ignore): %s", path); ignore_type = rhythmdb_entry_register_type (db, name); g_free (name); name = g_strdup_printf ("generic audio player (errors): %s", path); error_type = rhythmdb_entry_register_type (db, name); g_free (name); g_object_unref (db); g_object_unref (volume); g_free (path); source = RB_GENERIC_PLAYER_SOURCE (g_object_new (RB_TYPE_GENERIC_PLAYER_SOURCE, "entry-type", entry_type, "ignore-entry-type", ignore_type, "error-entry-type", error_type, "mount", mount, "shell", shell, "source-group", RB_SOURCE_GROUP_DEVICES, NULL)); rb_shell_register_entry_type_for_source (shell, RB_SOURCE (source), entry_type); return RB_REMOVABLE_MEDIA_SOURCE (source); }
static void impl_delete_entries (RBMediaPlayerSource *source, GList *entries, RBMediaPlayerSourceDeleteCallback callback, gpointer callback_data, GDestroyNotify destroy_data) { rb_generic_player_source_delete_entries (RB_GENERIC_PLAYER_SOURCE (source), entries); if (callback) { callback (source, callback_data); } if (destroy_data) { destroy_data (callback_data); } }
static void visit_playlist_dirs (RBPspSource *source, GFile *file) { RBShell *shell; RhythmDB *db; RhythmDBEntryType *entry_type; char *playlist_path; char *playlist_name; RBSource *playlist; GPtrArray *query; playlist_path = g_file_get_uri (file); /* or _get_path? */ g_object_get (source, "shell", &shell, "entry-type", &entry_type, NULL); g_object_get (shell, "db", &db, NULL); /* FIXME this isn't good enough, we only need the files directly under the playlist directory, * not sub-dirs */ query = rhythmdb_query_parse (db, RHYTHMDB_QUERY_PROP_EQUALS, RHYTHMDB_PROP_TYPE, entry_type, RHYTHMDB_QUERY_PROP_PREFIX, RHYTHMDB_PROP_LOCATION, playlist_path, RHYTHMDB_QUERY_END); g_free (playlist_path); g_object_unref (entry_type); playlist_name = g_file_get_basename (file); playlist = rb_auto_playlist_source_new (shell, playlist_name, FALSE); g_free (playlist_name); rb_auto_playlist_source_set_query (RB_AUTO_PLAYLIST_SOURCE (playlist), query, RHYTHMDB_QUERY_MODEL_LIMIT_NONE, NULL, NULL, 0); rb_generic_player_source_add_playlist (RB_GENERIC_PLAYER_SOURCE (source), shell, RB_SOURCE (playlist)); rhythmdb_query_free (query); g_object_unref (shell); g_object_unref (db); }
static gboolean impl_can_move_to_trash (RBSource *source) { RBEntryView *view; GList *sel; gboolean ret; view = rb_source_get_entry_view (source); sel = rb_entry_view_get_selected_entries (view); ret = rb_generic_player_source_can_trash_entries (RB_GENERIC_PLAYER_SOURCE (source), sel); g_list_foreach (sel, (GFunc)rhythmdb_entry_unref, NULL); g_list_free (sel); return ret; }
static void impl_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { RBGenericPlayerPlaylistSourcePrivate *priv = GET_PRIVATE (object); switch (prop_id) { case PROP_PLAYER_SOURCE: priv->player_source = RB_GENERIC_PLAYER_SOURCE (g_value_dup_object (value)); break; case PROP_PLAYLIST_PATH: priv->playlist_path = g_value_dup_string (value); break; case PROP_DEVICE_ROOT: priv->device_root = g_value_dup_string (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } }
static guint64 impl_get_free_space (RBMediaPlayerSource *source) { return get_fs_property (RB_GENERIC_PLAYER_SOURCE (source), G_FILE_ATTRIBUTE_FILESYSTEM_FREE); }
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 GObject * impl_constructor (GType type, guint n_construct_properties, GObjectConstructParam *construct_properties) { RBGenericPlayerSource *source; RBGenericPlayerSourcePrivate *priv; GMount *mount; char **playlist_formats; char *mount_name; RBShell *shell; GFile *root; GFileInfo *info; GError *error = NULL; source = RB_GENERIC_PLAYER_SOURCE (G_OBJECT_CLASS (rb_generic_player_source_parent_class)-> constructor (type, n_construct_properties, construct_properties)); priv = GENERIC_PLAYER_SOURCE_GET_PRIVATE (source); g_object_get (source, "shell", &shell, NULL); g_object_get (shell, "db", &priv->db, NULL); priv->import_errors = rb_import_errors_source_new (shell, priv->error_type); g_object_unref (shell); g_object_get (source, "mount", &mount, NULL); root = g_mount_get_root (mount); mount_name = g_mount_get_name (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_unref (mount); g_object_get (priv->device_info, "playlist-formats", &playlist_formats, NULL); if (playlist_formats != NULL && g_strv_length (playlist_formats) > 0) { RhythmDBEntryType entry_type; g_object_get (source, "entry-type", &entry_type, NULL); entry_type->has_playlists = TRUE; g_boxed_free (RHYTHMDB_TYPE_ENTRY_TYPE, entry_type); } g_strfreev (playlist_formats); load_songs (source); return G_OBJECT (source); }
static char * impl_build_dest_uri (RBRemovableMediaSource *source, RhythmDBEntry *entry, const char *mimetype, const char *extension) { RBGenericPlayerSourcePrivate *priv = GENERIC_PLAYER_SOURCE_GET_PRIVATE (source); 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 (""); } artist = sanitize_path (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_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 (source)); 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 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; char *label; char *fullname; char *name; 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, "name", &name, 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); priv->new_playlist_action_name = g_strdup_printf ("generic-player-%p-playlist-new", source); fullname = g_strdup_printf ("app.%s", priv->new_playlist_action_name); label = g_strdup_printf (_("New Playlist on %s"), name); rb_application_add_plugin_menu_item (RB_APPLICATION (g_application_get_default ()), "display-page-add-playlist", priv->new_playlist_action_name, g_menu_item_new (label, fullname)); g_free (fullname); g_free (label); g_free (name); 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 ((priv->read_only == FALSE) && playlist_formats != NULL && g_strv_length (playlist_formats) > 0) { RBDisplayPageModel *model; GMenu *playlist_menu; GMenuModel *playlists; priv->new_playlist_action = g_simple_action_new (priv->new_playlist_action_name, NULL); g_signal_connect (priv->new_playlist_action, "activate", G_CALLBACK (new_playlist_action_cb), source); g_action_map_add_action (G_ACTION_MAP (g_application_get_default ()), G_ACTION (priv->new_playlist_action)); g_object_get (shell, "display-page-model", &model, NULL); playlists = rb_display_page_menu_new (model, RB_DISPLAY_PAGE (source), RB_TYPE_GENERIC_PLAYER_PLAYLIST_SOURCE, "app.playlist-add-to"); g_object_unref (model); playlist_menu = g_menu_new (); g_menu_append (playlist_menu, _("Add to New Playlist"), priv->new_playlist_action_name); g_menu_append_section (playlist_menu, NULL, playlists); g_object_set (source, "playlist-menu", playlist_menu, 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); g_object_unref (shell); }
RBSource * rb_generic_player_source_new (GObject *plugin, RBShell *shell, GMount *mount, MPIDDevice *device_info) { RBGenericPlayerSource *source; RhythmDBEntryType *entry_type; RhythmDBEntryType *error_type; RhythmDBEntryType *ignore_type; RhythmDB *db; GVolume *volume; GSettings *settings; char *name; char *path; volume = g_mount_get_volume (mount); g_object_get (shell, "db", &db, NULL); path = g_volume_get_identifier (volume, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE); name = g_strdup_printf ("generic audio player: %s", path); entry_type = g_object_new (RHYTHMDB_TYPE_ENTRY_TYPE, "db", db, "name", name, "save-to-disk", FALSE, "category", RHYTHMDB_ENTRY_NORMAL, NULL); rhythmdb_register_entry_type (db, entry_type); g_free (name); name = g_strdup_printf ("generic audio player (ignore): %s", path); ignore_type = g_object_new (RHYTHMDB_TYPE_ENTRY_TYPE, "db", db, "name", name, "save-to-disk", FALSE, "category", RHYTHMDB_ENTRY_VIRTUAL, NULL); rhythmdb_register_entry_type (db, ignore_type); g_free (name); name = g_strdup_printf ("generic audio player (errors): %s", path); error_type = g_object_new (RHYTHMDB_TYPE_ENTRY_TYPE, "db", db, "name", name, "save-to-disk", FALSE, "category", RHYTHMDB_ENTRY_VIRTUAL, NULL); rhythmdb_register_entry_type (db, error_type); g_free (name); g_object_unref (db); g_object_unref (volume); g_free (path); settings = g_settings_new ("org.gnome.rhythmbox.plugins.generic-player"); source = RB_GENERIC_PLAYER_SOURCE (g_object_new (RB_TYPE_GENERIC_PLAYER_SOURCE, "plugin", plugin, "entry-type", entry_type, "ignore-entry-type", ignore_type, "error-entry-type", error_type, "mount", mount, "shell", shell, "device-info", device_info, "load-status", RB_SOURCE_LOAD_STATUS_LOADING, "settings", g_settings_get_child (settings, "source"), "toolbar-path", "/GenericPlayerSourceToolBar", NULL)); g_object_unref (settings); rb_shell_register_entry_type_for_source (shell, RB_SOURCE (source), entry_type); return RB_SOURCE (source); }
static void impl_selected (RBDisplayPage *page) { ensure_loaded (RB_GENERIC_PLAYER_SOURCE (page)); }