X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=aft.c;h=8c7dd21a0f86ac25e39b1bfdae33ccc5f6032b71;hp=99b132dd9d249a9991805068161fc1faf729ada5;hb=e60387b0557fbeb97895bc3d6d4423be12436c52;hpb=55030e0d1a28ded2076d62fb9aac3539ff337275 diff --git a/aft.c b/aft.c index 99b132dd..8c7dd21a 100644 --- a/aft.c +++ b/aft.c @@ -457,9 +457,9 @@ static int load_chunk_info(struct osl_object *obj, struct audio_format_info *afh * * \return The return value of the underlying call to osl_get_row(). */ -int aft_get_row_of_path(char *path, struct osl_row **row) +int aft_get_row_of_path(const char *path, struct osl_row **row) { - struct osl_object obj = {.data = path, .size = strlen(path) + 1}; + struct osl_object obj = {.data = (char *)path, .size = strlen(path) + 1}; return osl_get_row(audio_file_table, AFTCOL_PATH, &obj, row); } @@ -500,7 +500,7 @@ int get_afsi_object_of_row(const struct osl_row *row, struct osl_object *obj) * * \return Positive on success, negative on errors. */ -int get_afsi_object_of_path(char *path, struct osl_object *obj) +int get_afsi_object_of_path(const char *path, struct osl_object *obj) { struct osl_row *row; int ret = aft_get_row_of_path(path, &row); @@ -526,6 +526,23 @@ int get_afsi_of_row(const struct osl_row *row, struct afs_info *afsi) return load_afsi(afsi, &obj); } +/** + * Get the audio file selector info, given the path of an audio table. + * + * \param path The full path of the audio file. + * \param afsi Result pointer. + * + * \return Positive on success, negative on errors. + */ +int get_afsi_of_path(const char *path, struct afs_info *afsi) +{ + struct osl_object obj; + int ret = get_afsi_object_of_path(path, &obj); + if (ret < 0) + return ret; + return load_afsi(afsi, &obj); +} + /** * Get the path of an audio file, given a row of the audio file table. * @@ -1566,8 +1583,13 @@ static int add_one_audio_file(const char *arg, const void *private_data) if (ret < 0) goto out_free; ret = guess_audio_format(path); - if (ret < 0 && !(pad->flags & ADD_FLAG_ALL)) + if (ret < 0 && !(pad->flags & ADD_FLAG_ALL)) { + if (pad->flags & ADD_FLAG_VERBOSE) + ret = send_va_buffer(pad->fd, "%s: %s\n", + PARA_STRERROR(-ret), path); + ret = 1; goto out_free; + } query.data = path; query.size = strlen(path) + 1; ret = send_callback_request(path_brother_callback, &query, &result); @@ -1618,8 +1640,11 @@ static int add_one_audio_file(const char *arg, const void *private_data) format_num = ret; afhi_ptr = &afhi; } - if (pad->flags & ADD_FLAG_VERBOSE) - send_va_buffer(pad->fd, "adding %s\n", path); + if (pad->flags & ADD_FLAG_VERBOSE) { + ret = send_va_buffer(pad->fd, "adding %s\n", path); + if (ret < 0) + goto out_unmap; + } munmap(map.data, map.size); save_audio_file_info(hash, path, afhi_ptr, pad->flags, format_num, &obj); /* Ask afs to consider this entry for adding. */ @@ -1629,14 +1654,15 @@ static int add_one_audio_file(const char *arg, const void *private_data) out_unmap: munmap(map.data, map.size); out_free: - if (ret < 0) + if (ret < 0 && ret != -E_SEND) send_va_buffer(pad->fd, "failed to add %s (%s)\n", path? path : arg, PARA_STRERROR(-ret)); free(obj.data); free(path); if (afhi_ptr) free(afhi_ptr->chunk_table); - return 1; /* it's not an error if not all files could be added */ + /* it's not an error if not all files could be added */ + return ret == -E_SEND? ret : 1; } int com_add(int fd, int argc, char * const * const argv) @@ -1681,12 +1707,18 @@ int com_add(int fd, int argc, char * const * const argv) if (ret < 0) PARA_NOTICE_LOG("failed to stat %s (%s)", path, strerror(errno)); - else + else { if (S_ISDIR(statbuf.st_mode)) - for_each_file_in_dir(path, add_one_audio_file, + ret = for_each_file_in_dir(path, add_one_audio_file, &pad); else - add_one_audio_file(path, &pad); + ret = add_one_audio_file(path, &pad); + if (ret < 0) { + send_va_buffer(fd, "%s: %s\n", path, PARA_STRERROR(-ret)); + free(path); + return ret; + } + } free(path); } ret = 1; @@ -1785,7 +1817,6 @@ static int com_touch_callback(const struct osl_object *query, return ret < 0? ret : 0; } - int com_touch(int fd, int argc, char * const * const argv) { struct com_touch_options cto = { @@ -1959,6 +1990,146 @@ int com_afs_rm(int fd, int argc, char * const * const argv) return ret; } +enum cpsi_flags { + CPSI_FLAG_COPY_LYRICS_ID = 1, + CPSI_FLAG_COPY_IMAGE_ID = 2, + CPSI_FLAG_COPY_LASTPLAYED = 4, + CPSI_FLAG_COPY_NUMPLAYED = 8, + CPSI_FLAG_COPY_ATTRIBUTES = 16, + CPSI_FLAG_VERBOSE = 32, +}; + +struct cpsi_action_data { + unsigned flags; + unsigned num_copied; + struct para_buffer pb; + struct afs_info source_afsi; +}; + +static int copy_selector_info(__a_unused struct osl_table *table, + struct osl_row *row, const char *name, void *data) +{ + struct cpsi_action_data *cad = data; + struct osl_object target_afsi_obj; + int ret; + struct afs_info target_afsi; + + ret = get_afsi_object_of_row(row, &target_afsi_obj); + if (ret < 0) + return ret; + load_afsi(&target_afsi, &target_afsi_obj); + if (cad->flags & CPSI_FLAG_COPY_LYRICS_ID) + target_afsi.lyrics_id = cad->source_afsi.lyrics_id; + if (cad->flags & CPSI_FLAG_COPY_IMAGE_ID) + target_afsi.image_id = cad->source_afsi.image_id; + if (cad->flags & CPSI_FLAG_COPY_LASTPLAYED) + target_afsi.last_played = cad->source_afsi.last_played; + if (cad->flags & CPSI_FLAG_COPY_NUMPLAYED) + target_afsi.num_played = cad->source_afsi.num_played; + if (cad->flags & CPSI_FLAG_COPY_ATTRIBUTES) + target_afsi.attributes = cad->source_afsi.attributes; + save_afsi(&target_afsi, &target_afsi_obj); /* in-place update */ + cad->num_copied++; + if (cad->flags & CPSI_FLAG_VERBOSE) + para_printf(&cad->pb, "copied afsi to %s\n", name); + return 1; +} + +static int com_cpsi_callback(const struct osl_object *query, + struct osl_object *result) +{ + struct cpsi_action_data cad = {.flags = *(unsigned *)query->data}; + int ret; + char *source_path = (char *)query->data + sizeof(cad.flags); + + ret = get_afsi_of_path(source_path, &cad.source_afsi); + if (ret < 0) + goto out; + struct pattern_match_data pmd = { + .table = audio_file_table, + .loop_col_num = AFTCOL_HASH, + .match_col_num = AFTCOL_PATH, + .patterns = {.data = source_path + strlen(source_path) + 1, + .size = query->size - sizeof(cad.flags) + - strlen(source_path) - 1}, + .data = &cad, + .action = copy_selector_info + }; + ret = for_each_matching_row(&pmd); +out: + if (ret < 0) + para_printf(&cad.pb, "%s\n", PARA_STRERROR(-ret)); + if (cad.flags & CPSI_FLAG_VERBOSE) { + if (cad.num_copied) + para_printf(&cad.pb, "copied requested afsi from %s " + "to %u files\n", + source_path, cad.num_copied); + else + para_printf(&cad.pb, "nothing copied\n"); + } + if (cad.pb.buf) { + result->data = cad.pb.buf; + result->size = cad.pb.size; + return 1; + } + return ret < 0? ret : 0; +} + +int com_cpsi(int fd, int argc, char * const * const argv) +{ + unsigned flags = 0; + int i, ret; + struct osl_object options = {.data = &flags, .size = sizeof(flags)}, + result; + + for (i = 1; i < argc; i++) { + const char *arg = argv[i]; + if (arg[0] != '-') + break; + if (!strcmp(arg, "--")) { + i++; + break; + } + if (!strcmp(arg, "-y")) { + flags |= CPSI_FLAG_COPY_LYRICS_ID; + continue; + } + if (!strcmp(arg, "-i")) { + flags |= CPSI_FLAG_COPY_IMAGE_ID; + continue; + } + if (!strcmp(arg, "-l")) { + flags |= CPSI_FLAG_COPY_LASTPLAYED; + continue; + } + if (!strcmp(arg, "-n")) { + flags |= CPSI_FLAG_COPY_NUMPLAYED; + continue; + } + if (!strcmp(arg, "-a")) { + flags |= CPSI_FLAG_COPY_ATTRIBUTES; + continue; + } + if (!strcmp(arg, "-v")) { + flags |= CPSI_FLAG_VERBOSE; + continue; + } + break; + } + if (i + 1 >= argc) /* need at least souce file and pattern */ + return -E_AFT_SYNTAX; + if (!(flags & ~CPSI_FLAG_VERBOSE)) /* no copy flags given */ + flags = ~(unsigned)CPSI_FLAG_VERBOSE | flags; + ret = send_option_arg_callback_request(&options, argc - i, argv + i, + com_cpsi_callback, &result); + if (ret > 0) { + send_buffer(fd, (char *)result.data); + free(result.data); + } else + send_va_buffer(fd, "%s\n", PARA_STRERROR(-ret)); + return ret; +} + /* TODO: optionally fix problems by removing offending rows */ static int check_audio_file(struct osl_row *row, void *data) { @@ -2007,6 +2178,8 @@ int aft_check_callback(__a_unused const struct osl_object *query, struct osl_obj } + + /** * Close the audio file table. *