From: Andre Noll Date: Tue, 2 Oct 2007 09:56:35 +0000 (+0200) Subject: Implement com_cpsi(). X-Git-Tag: v0.3.0~316 X-Git-Url: http://git.tue.mpg.de/?a=commitdiff_plain;h=e60387b0557fbeb97895bc3d6d4423be12436c52;p=paraslash.git Implement com_cpsi(). --- diff --git a/afs.cmd b/afs.cmd index 2ec7bd26..14ee5891 100644 --- a/afs.cmd +++ b/afs.cmd @@ -196,6 +196,28 @@ H: in pattern and not by an asterisk (*) or a question mark H: (?) metacharacter, nor by a bracket expression ([]) containing H: a slash (see fnmatch(3)). --- +N: cpsi +P: AFS_READ | AFS_WRITE +D: Copy audio file selector info. +U: cpsi [-a] [-y] [-i] [-l] [-n] [-v] source pattern... +H: If no option, or only the -v option is given, all fields of the audio file +H: selector info are copied to all files matching pattern. Otherwise, only the +H: given options are taken into account. +H: +H: Options: +H: +H: -a Copy attributes. +H: +H: -y Copy the lyrics id. +H: +H: -i Copy the image id. +H: +H: -l Copy the lastplayed time. +H: +H: -n Copy the numplayed count. +H: +H: -v Verbose mode. +--- T: add N: add@member@ O: int com_add@member@(int fd, int argc, char * const * const argv); diff --git a/afs.h b/afs.h index 546a19ec..7167da49 100644 --- a/afs.h +++ b/afs.h @@ -99,12 +99,13 @@ int get_attribute_text(uint64_t *atts, const char *delim, char **text); /* aft */ int aft_init(struct table_info *ti, const char *db); void aft_shutdown(enum osl_close_flags flags); -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); int open_and_update_audio_file(struct osl_row *aft_row, struct audio_file_data *afd); int load_afsi(struct afs_info *afsi, struct osl_object *obj); void save_afsi(struct afs_info *afsi, struct osl_object *obj); int get_afsi_of_row(const struct osl_row *row, struct afs_info *afsi); int get_afhi_of_row(const struct osl_row *row, struct audio_format_info *afhi); +int get_afsi_of_path(const char *path, struct afs_info *afsi); int get_audio_file_path_of_row(const struct osl_row *row, char **path); int get_afsi_object_of_row(const struct osl_row *row, struct osl_object *obj); int audio_file_loop(void *private_data, osl_rbtree_loop_func *func); diff --git a/aft.c b/aft.c index cbea5eb1..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. * @@ -1800,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 = { @@ -1974,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) { @@ -2022,6 +2178,8 @@ int aft_check_callback(__a_unused const struct osl_object *query, struct osl_obj } + + /** * Close the audio file table. *