static char * default_uri_to_playlist_uri (RBGenericPlayerSource *source, const char *uri, TotemPlParserType playlist_type) { char *mount_uri; char *playlist_uri; switch (playlist_type) { case TOTEM_PL_PARSER_IRIVER_PLA: /* we need absolute paths within the device filesystem for this format */ mount_uri = rb_generic_player_source_get_mount_path (source); if (g_str_has_prefix (uri, mount_uri) == FALSE) { rb_debug ("uri %s is not under device mount uri %s", uri, mount_uri); return NULL; } playlist_uri = g_strdup_printf ("file://%s", uri + strlen (mount_uri)); return playlist_uri; case TOTEM_PL_PARSER_M3U_DOS: case TOTEM_PL_PARSER_M3U: case TOTEM_PL_PARSER_PLS: default: /* leave the URI as-is, so we end up with relative paths in the playlist file */ return g_strdup (uri); } }
static void load_playlist_file (RBGenericPlayerSource *source, const char *playlist_path, const char *rel_path) { RhythmDBEntryType entry_type; RBGenericPlayerPlaylistSource *playlist; RBShell *shell; char *mount_path; g_object_get (source, "shell", &shell, "entry-type", &entry_type, NULL); mount_path = rb_generic_player_source_get_mount_path (source); rb_debug ("loading playlist %s", playlist_path); playlist = RB_GENERIC_PLAYER_PLAYLIST_SOURCE ( rb_generic_player_playlist_source_new (shell, source, playlist_path, mount_path, entry_type)); if (playlist != NULL) { rb_generic_player_source_add_playlist (source, shell, RB_SOURCE (playlist)); } g_boxed_free (RHYTHMDB_TYPE_ENTRY_TYPE, entry_type); g_object_unref (shell); g_free (mount_path); }
static void load_songs (RBGenericPlayerSource *source) { RBGenericPlayerSourcePrivate *priv = GET_PRIVATE (source); RhythmDBEntryType *entry_type; char **audio_folders; char *mount_path; RBShell *shell; RBTaskList *tasklist; char *name; char *label; mount_path = rb_generic_player_source_get_mount_path (source); g_object_get (source, "entry-type", &entry_type, NULL); /* if we have a set of folders on the device containing audio files, * load only those folders, otherwise add the whole volume. */ priv->import_job = rhythmdb_import_job_new (priv->db, entry_type, priv->ignore_type, priv->error_type); g_object_get (source, "name", &name, NULL); label = g_strdup_printf (_("Scanning %s"), name); g_object_set (priv->import_job, "task-label", label, NULL); g_free (label); g_free (name); g_signal_connect_object (priv->import_job, "complete", G_CALLBACK (import_complete_cb), source, 0); g_object_get (priv->device_info, "audio-folders", &audio_folders, NULL); if (audio_folders != NULL && g_strv_length (audio_folders) > 0) { int af; for (af=0; audio_folders[af] != NULL; af++) { char *path; path = rb_uri_append_path (mount_path, audio_folders[af]); rb_debug ("loading songs from device audio folder %s", path); rhythmdb_import_job_add_uri (priv->import_job, path); g_free (path); } } else { rb_debug ("loading songs from device mount path %s", mount_path); rhythmdb_import_job_add_uri (priv->import_job, mount_path); } g_strfreev (audio_folders); rhythmdb_import_job_start (priv->import_job); g_object_get (source, "shell", &shell, NULL); g_object_get (shell, "task-list", &tasklist, NULL); rb_task_list_add_task (tasklist, RB_TASK_PROGRESS (priv->import_job)); g_object_unref (tasklist); g_object_unref (shell); g_object_unref (entry_type); g_free (mount_path); }
static void default_load_playlists (RBGenericPlayerSource *source) { RBGenericPlayerSourcePrivate *priv = GENERIC_PLAYER_SOURCE_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); g_object_get (priv->device_info, "playlist-path", &playlist_path, NULL); 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 */ if (g_str_has_suffix (playlist_path, "/%File")) { playlist_path[strlen (playlist_path) - strlen("/%File")] = '\0'; } full_playlist_path = rb_uri_append_path (mount_path, playlist_path); rb_debug ("constructed playlist search path %s", full_playlist_path); } else { full_playlist_path = g_strdup (mount_path); } /* 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); }
static char * default_uri_to_playlist_uri (RBGenericPlayerSource *source, const char *uri) { char *mount_uri; char *playlist_uri; mount_uri = rb_generic_player_source_get_mount_path (source); if (g_str_has_prefix (uri, mount_uri) == FALSE) { rb_debug ("uri %s is not under device mount uri %s", uri, mount_uri); return NULL; } playlist_uri = g_strdup_printf ("file://%s", uri + strlen (mount_uri)); return playlist_uri; }
static char * default_uri_from_playlist_uri (RBGenericPlayerSource *source, const char *uri) { char *mount_uri; char *full_uri; mount_uri = rb_generic_player_source_get_mount_path (source); if (g_str_has_prefix (uri, mount_uri)) { return g_strdup (uri); } full_uri = rb_uri_append_uri (mount_uri, uri); g_free (mount_uri); rb_debug ("%s => %s", uri, full_uri); return full_uri; }
static char * impl_uri_from_playlist_uri (RBGenericPlayerSource *source, const char *uri) { const char *path; char *local_uri; char *mount_uri; if (!g_str_has_prefix (uri, NOKIA_INTERNAL_MOUNTPOINT)) { rb_debug ("found playlist uri with unexpected mountpoint"); return NULL; } path = uri + strlen (NOKIA_INTERNAL_MOUNTPOINT); mount_uri = rb_generic_player_source_get_mount_path (source); local_uri = rb_uri_append_uri (mount_uri, path); g_free (mount_uri); return local_uri; }
static void load_songs (RBGenericPlayerSource *source) { RBGenericPlayerSourcePrivate *priv = GENERIC_PLAYER_SOURCE_GET_PRIVATE (source); RhythmDBEntryType entry_type; char **audio_folders; char *mount_path; mount_path = rb_generic_player_source_get_mount_path (source); g_object_get (source, "entry-type", &entry_type, NULL); /* if we have a set of folders on the device containing audio files, * load only those folders, otherwise add the whole volume. */ priv->import_job = rhythmdb_import_job_new (priv->db, entry_type, priv->ignore_type, priv->error_type); g_signal_connect_object (priv->import_job, "complete", G_CALLBACK (import_complete_cb), source, 0); g_signal_connect_object (priv->import_job, "status-changed", G_CALLBACK (import_status_changed_cb), source, 0); g_object_get (priv->device_info, "audio-folders", &audio_folders, NULL); if (audio_folders != NULL && g_strv_length (audio_folders) > 0) { int af; for (af=0; audio_folders[af] != NULL; af++) { char *path; path = rb_uri_append_path (mount_path, audio_folders[af]); rb_debug ("loading songs from device audio folder %s", path); rhythmdb_import_job_add_uri (priv->import_job, path); g_free (path); } } else { rb_debug ("loading songs from device mount path %s", mount_path); rhythmdb_import_job_add_uri (priv->import_job, mount_path); } g_strfreev (audio_folders); rhythmdb_import_job_start (priv->import_job); g_boxed_free (RHYTHMDB_TYPE_ENTRY_TYPE, entry_type); g_free (mount_path); }
static guint64 get_fs_property (RBGenericPlayerSource *source, const char *attr) { char *mountpoint; GFile *root; GFileInfo *info; guint64 value = 0; mountpoint = rb_generic_player_source_get_mount_path (source); root = g_file_new_for_uri (mountpoint); g_free (mountpoint); info = g_file_query_filesystem_info (root, attr, NULL, NULL); g_object_unref (root); if (info != NULL) { if (g_file_info_has_attribute (info, attr)) { value = g_file_info_get_attribute_uint64 (info, attr); } g_object_unref (info); } return value; }
static void default_load_playlists (RBGenericPlayerSource *source) { RBGenericPlayerSourcePrivate *priv = GENERIC_PLAYER_SOURCE_GET_PRIVATE (source); char *mount_path; char *playlist_path = NULL; mount_path = rb_generic_player_source_get_mount_path (source); if (priv->playlist_path) { /* If the device only supports a single playlist, just load that */ if (g_str_has_suffix (priv->playlist_path, ".m3u") || g_str_has_suffix (priv->playlist_path, ".pls")) { char *playlist_path = rb_uri_append_path (mount_path, priv->playlist_path); if (rb_uri_exists (playlist_path)) { load_playlist_file (source, playlist_path, priv->playlist_path); } return; } /* Otherwise, limit the search to the device's playlist folder. * The optional trailing '/%File' is stripped in set_playlist_path */ playlist_path = rb_uri_append_path (mount_path, priv->playlist_path); rb_debug ("constructed playlist search path %s", playlist_path); } rb_uri_handle_recursively (playlist_path ? playlist_path : mount_path, NULL, (RBUriRecurseFunc) visit_playlist_dirs, source); g_free (playlist_path); g_free (mount_path); }
static gboolean save_playlist (RBGenericPlayerPlaylistSource *source) { TotemPlParser *parser; TotemPlParserType playlist_type; RhythmDBQueryModel *query_model; char *name; char *temp_path; GError *error = NULL; RBGenericPlayerPlaylistSourcePrivate *priv = GET_PRIVATE (source); GFile *file; gboolean result; SavePlaylistData data; priv->save_playlist_id = 0; playlist_type = rb_generic_player_source_get_playlist_format (priv->player_source); g_object_get (source, "name", &name, "base-query-model", &query_model, NULL); /* if we don't already have a name for this playlist, make one now */ if (priv->playlist_path == NULL) { char *playlist_dir; char *mount_uri; char *filename; const char *ext; GFile *dir; GFile *playlist; ext = playlist_format_extension (playlist_type); if (name == NULL || name[0] == '\0') { /* now what? */ filename = g_strdup_printf ("unnamed%s", ext); } else { filename = g_strdup_printf ("%s%s", name, ext); } playlist_dir = rb_generic_player_source_get_playlist_path (priv->player_source); mount_uri = rb_generic_player_source_get_mount_path (priv->player_source); dir = g_file_new_for_uri (mount_uri); if (playlist_dir != NULL) { GFile *pdir; pdir = g_file_resolve_relative_path (dir, playlist_dir); g_object_unref (dir); dir = pdir; } playlist = g_file_resolve_relative_path (dir, filename); priv->playlist_path = g_file_get_path (playlist); g_free (mount_uri); g_free (playlist_dir); g_object_unref (dir); } temp_path = g_strdup_printf ("%s%06X", priv->playlist_path, g_random_int_range (0, 0xFFFFFF)); file = g_file_new_for_path (temp_path); parser = totem_pl_parser_new (); data.source = source; data.playlist_type = playlist_type; #if TOTEM_PL_PARSER_CHECK_VERSION(2,29,1) data.playlist = totem_pl_playlist_new (); gtk_tree_model_foreach (GTK_TREE_MODEL (query_model), (GtkTreeModelForeachFunc) save_playlist_foreach, &data); if (rb_debug_matches ("totem_pl_parser_save", "totem-pl-parser.c")) { g_object_set (parser, "debug", TRUE, NULL); } result = totem_pl_parser_save (parser, data.playlist, file, name, playlist_type, &error); g_object_unref (data.playlist); data.playlist = NULL; #else if (rb_debug_matches ("totem_pl_parser_write_with_title", "totem-pl-parser.c")) { g_object_set (parser, "debug", TRUE, NULL); } result = totem_pl_parser_write_with_title (parser, GTK_TREE_MODEL (query_model), (TotemPlParserIterFunc) save_playlist_entry, temp_path, name, playlist_type, &data, &error); #endif if (result == FALSE) { /* XXX report this more usefully */ g_warning ("Playlist save failed: %s", error ? error->message : "<no error>"); } else { GFile *dest; dest = g_file_new_for_path (priv->playlist_path); g_file_move (file, dest, G_FILE_COPY_OVERWRITE | G_FILE_COPY_NO_FALLBACK_FOR_MOVE, NULL, NULL, NULL, &error); if (error != NULL) { /* XXX report this more usefully */ g_warning ("moving %s => %s failed: %s", temp_path, priv->playlist_path, error->message); } g_object_unref (dest); } g_clear_error (&error); g_free (name); g_free (temp_path); g_object_unref (query_model); g_object_unref (parser); g_object_unref (file); return FALSE; }
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 gboolean save_playlist (RBGenericPlayerPlaylistSource *source) { TotemPlParser *parser; TotemPlParserType playlist_type; RhythmDBQueryModel *query_model; char *name; char *temp_uri; GError *error = NULL; RBGenericPlayerPlaylistSourcePrivate *priv = GET_PRIVATE (source); priv->save_playlist_id = 0; playlist_type = rb_generic_player_source_get_playlist_format (priv->player_source); g_object_get (source, "name", &name, "base-query-model", &query_model, NULL); /* if we don't already have a name for this playlist, make one now */ if (priv->playlist_path == NULL) { char *playlist_dir; char *mount_uri; char *filename; const char *ext; GFile *dir; GFile *playlist; ext = playlist_format_extension (playlist_type); if (name == NULL || name[0] == '\0') { /* now what? */ filename = g_strdup_printf ("unnamed%s", ext); } else { filename = g_strdup_printf ("%s%s", name, ext); } playlist_dir = rb_generic_player_source_get_playlist_path (priv->player_source); mount_uri = rb_generic_player_source_get_mount_path (priv->player_source); dir = g_file_new_for_uri (mount_uri); if (playlist_dir != NULL) { GFile *pdir; pdir = g_file_resolve_relative_path (dir, playlist_dir); g_object_unref (dir); dir = pdir; } playlist = g_file_resolve_relative_path (dir, filename); priv->playlist_path = g_file_get_path (playlist); g_free (mount_uri); g_free (playlist_dir); g_object_unref (dir); } temp_uri = g_strdup_printf ("%s%06X", priv->playlist_path, g_random_int_range (0, 0xFFFFFF)); parser = totem_pl_parser_new (); if (rb_debug_matches ("totem_pl_parser_write_with_title", "totem-pl-parser.c")) { g_object_set (parser, "debug", TRUE, NULL); } if (totem_pl_parser_write_with_title (parser, GTK_TREE_MODEL (query_model), (TotemPlParserIterFunc) save_playlist_entry, temp_uri, name, playlist_type, source, &error) == FALSE) { /* XXX report this more usefully */ g_warning ("Playlist save failed: %s", error->message); } else { GFile *dest; GFile *src; dest = g_file_new_for_path (priv->playlist_path); src = g_file_new_for_path (temp_uri); g_file_move (src, dest, G_FILE_COPY_OVERWRITE | G_FILE_COPY_NO_FALLBACK_FOR_MOVE, NULL, NULL, NULL, &error); if (error != NULL) { /* XXX report this more usefully */ g_warning ("Replacing playlist failed: %s", error->message); } g_object_unref (dest); g_object_unref (src); } g_clear_error (&error); g_free (name); g_free (temp_uri); g_object_unref (query_model); return FALSE; }