static struct song * apply_song_metadata(struct song *dest, const struct song *src) { struct song *tmp; assert(dest != NULL); assert(src != NULL); if (src->tag == NULL && src->start_ms == 0 && src->end_ms == 0) return dest; if (song_in_database(dest)) { char *path_fs = map_song_fs(dest); if (path_fs == NULL) return dest; tmp = song_file_new(path_fs, NULL); g_free(path_fs); merge_song_metadata(tmp, dest, src); } else { tmp = song_file_new(dest->uri, NULL); merge_song_metadata(tmp, dest, src); song_free(dest); } return tmp; }
struct song * song_file_load(const char *path, struct directory *parent) { struct song *song; bool ret; assert((parent == NULL) == g_path_is_absolute(path)); assert(!uri_has_scheme(path)); assert(strchr(path, '\n') == NULL); song = song_file_new(path, parent); //in archive ? if (parent != NULL && parent->device == DEVICE_INARCHIVE) { ret = song_file_update_inarchive(song); } else { ret = song_file_update(song); } if (!ret) { song_free(song); return NULL; } return song; }
bool update_container_file(struct directory *directory, const char *name, const struct stat *st, const struct decoder_plugin *plugin) { if (plugin->container_scan == NULL) return false; db_lock(); struct directory *contdir = make_directory_if_modified(directory, name, st); if (contdir == NULL) { /* not modified */ db_unlock(); return true; } contdir->device = DEVICE_CONTAINER; db_unlock(); char *const pathname = map_directory_child_fs(directory, name); char *vtrack; unsigned int tnum = 0; while ((vtrack = plugin->container_scan(pathname, ++tnum)) != NULL) { struct song *song = song_file_new(vtrack, contdir); // shouldn't be necessary but it's there.. song->mtime = st->st_mtime; char *child_path_fs = map_directory_child_fs(contdir, vtrack); song->tag = tag_new(); decoder_plugin_scan_file(plugin, child_path_fs, &add_tag_handler, song->tag); g_free(child_path_fs); db_lock(); directory_add_song(contdir, song); db_unlock(); modified = true; g_message("added %s/%s", directory_get_path(directory), vtrack); g_free(vtrack); } g_free(pathname); if (tnum == 1) { db_lock(); delete_directory(contdir); db_unlock(); return false; } else return true; }
static struct song * apply_song_metadata(struct song *dest, const struct song *src) { struct song *tmp; assert(dest != NULL); assert(src != NULL); if (src->tag == NULL && src->start_ms == 0 && src->end_ms == 0) return dest; if (song_in_database(dest)) { char *path_fs = map_song_fs(dest); if (path_fs == NULL) return dest; char *path_utf8 = fs_charset_to_utf8(path_fs); if (path_utf8 != NULL) g_free(path_fs); else path_utf8 = path_fs; tmp = song_file_new(path_utf8, NULL); g_free(path_utf8); merge_song_metadata(tmp, dest, src); } else { tmp = song_file_new(dest->uri, NULL); merge_song_metadata(tmp, dest, src); } if (dest->tag != NULL && dest->tag->time > 0 && src->start_ms > 0 && src->end_ms == 0 && src->start_ms / 1000 < (unsigned)dest->tag->time) /* the range is open-ended, and the playlist plugin did not know the total length of the song file (e.g. last track on a CUE file); fix it up here */ tmp->tag->time = dest->tag->time - src->start_ms / 1000; song_free(dest); return tmp; }
static bool update_container_file( struct directory* directory, const char* name, const struct stat* st, const struct decoder_plugin* plugin) { char* vtrack = NULL; unsigned int tnum = 0; char* pathname = map_directory_child_fs(directory, name); struct directory* contdir = dirvec_find(&directory->children, name); // directory exists already if (contdir != NULL) { // modification time not eq. file mod. time if (contdir->mtime != st->st_mtime || walk_discard) { g_message("removing container file: %s", pathname); delete_directory(contdir); contdir = NULL; modified = true; } else { g_free(pathname); return true; } } contdir = make_subdir(directory, name); contdir->mtime = st->st_mtime; contdir->device = DEVICE_CONTAINER; while ((vtrack = plugin->container_scan(pathname, ++tnum)) != NULL) { struct song* song = song_file_new(vtrack, contdir); char *child_path_fs; // shouldn't be necessary but it's there.. song->mtime = st->st_mtime; child_path_fs = map_directory_child_fs(contdir, vtrack); song->tag = plugin->tag_dup(child_path_fs); g_free(child_path_fs); songvec_add(&contdir->songs, song); modified = true; g_message("added %s/%s", directory_get_path(directory), vtrack); g_free(vtrack); } g_free(pathname); if (tnum == 1) { delete_directory(contdir); return false; } else return true; }
struct song * song_load(FILE *fp, struct directory *parent, const char *uri, GString *buffer, GError **error_r) { struct song *song = parent != NULL ? song_file_new(uri, parent) : song_remote_new(uri); char *line, *colon; enum tag_type type; const char *value; while ((line = read_text_line(fp, buffer)) != NULL && strcmp(line, SONG_END) != 0) { colon = strchr(line, ':'); if (colon == NULL || colon == line) { if (song->tag != NULL) tag_end_add(song->tag); song_free(song); g_set_error(error_r, song_save_quark(), 0, "unknown line in db: %s", line); return NULL; } *colon++ = 0; value = g_strchug(colon); if ((type = tag_name_parse(line)) != TAG_NUM_OF_ITEM_TYPES) { if (!song->tag) { song->tag = tag_new(); tag_begin_add(song->tag); } tag_add_item(song->tag, type, value); } else if (strcmp(line, "Time") == 0) { if (!song->tag) { song->tag = tag_new(); tag_begin_add(song->tag); } song->tag->time = atoi(value); } else if (strcmp(line, SONG_MTIME) == 0) { song->mtime = atoi(value); } else if (strcmp(line, "Range") == 0) { char *endptr; song->start_ms = strtoul(value, &endptr, 10); if (*endptr == '-') song->end_ms = strtoul(endptr + 1, NULL, 10); } else { if (song->tag != NULL) tag_end_add(song->tag); song_free(song); g_set_error(error_r, song_save_quark(), 0, "unknown line in db: %s", line); return NULL; } } if (song->tag != NULL) tag_end_add(song->tag); return song; }