00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00037 #include <string.h>
00038 #include <ctype.h>
00039
00040 #include "splt.h"
00041
00042 static void splt_tp_process_tags(const char *tags,
00043 tags_parser_utils *tpu, splt_state *state, int *error);
00044 static void splt_tp_process_tag_variable(const char *tag_variable_start, const char *end_paranthesis,
00045 tags_parser_utils *tpu, splt_state *state, int *error);
00046 static void splt_tp_process_str_tags_variable(const char *tag_variable_start,
00047 const char *end_paranthesis, int tags_field,
00048 tags_parser_utils *tpu, splt_state *state, int *error);
00049 static void splt_tp_process_tracknumber_variable(const char *tag_variable_start,
00050 const char *end_paranthesis, tags_parser_utils *tpu, splt_state *state,
00051 int *error);
00052 static void splt_tp_process_auto_increment_tracknumber_variable(
00053 const char *tag_variable_start, const char *end_paranthesis,
00054 tags_parser_utils *tpu, splt_state *state, int *error);
00055
00056 static void splt_tp_check_ambigous_next_position(const char *tag_variable_start,
00057 tags_parser_utils *tpu);
00058 static void splt_tp_process_original_tags_variable(tags_parser_utils *tpu,
00059 splt_state *state, int *error);
00060 static void splt_tp_get_original_tags(splt_state *state, int *error);
00061 static int splt_tp_tpu_has_one_current_tag_set(tags_parser_utils *tpu);
00062 static char *splt_tp_look_for_end_paranthesis(tags_parser_utils *tpu);
00063 static void splt_tp_look_for_all_tags_char(const char *tags,
00064 tags_parser_utils *tpu, splt_state *state);
00065 static void splt_tp_tpu_increment_tags_field_counter(tags_parser_utils *tpu,
00066 int tags_field);
00067
00068 static tags_parser_utils *splt_tp_tpu_new(splt_state *state, int *error);
00069 static void splt_tp_tpu_reset_for_new_tags(splt_state *state, tags_parser_utils *tpu, int *error);
00070 static void splt_tp_tpu_free(tags_parser_utils **tpu);
00071 static void splt_tp_tpu_set_tracknumber(tags_parser_utils *tpu,
00072 const char *tracknumber, int *error);
00073 static const char *splt_tp_tpu_get_tracknumber(tags_parser_utils *tpu);
00074 static void splt_tp_tpu_set_tags_value(tags_parser_utils *tpu,
00075 int tags_field, const void *tag_value);
00076 static void splt_tp_set_track_from_parsed_tracknumber(tags_parser_utils *tpu,
00077 splt_state *state, int *error);
00078
00079 void splt_tp_put_tags_from_filename(splt_state *state, int *error)
00080 {
00081 #ifndef NO_PCRE
00082 splt_tags *tags = splt_fr_parse_from_state(state, error);
00083 if (*error < 0) { return; }
00084
00085 char *tags_format = splt_su_get_formatted_message(state,
00086 "%%[@o,@a=%s,@b=%s,@t=%s,@y=%s,@c=%s,@n=%d,@g=%s]",
00087 tags->artist,
00088 tags->album,
00089 tags->title,
00090 tags->year,
00091 tags->comment,
00092 tags->track,
00093 tags->genre);
00094
00095 if (tags_format == NULL)
00096 {
00097 *error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
00098 splt_tu_free_one_tags(&tags);
00099 return;
00100 }
00101
00102 splt_tp_put_tags_from_string(state, tags_format, error);
00103 free(tags_format);
00104
00105 splt_tu_free_one_tags(&tags);
00106 #else
00107 splt_c_put_info_message_to_client(state,
00108 _(" warning: cannot set tags from filename regular expression - compiled without pcre support\n"));
00109 #endif
00110 }
00111
00112 static char *splt_tp_parse_tag_word(const char *cur_pos,
00113 const char *end_paranthesis, int *ambiguous, int *error)
00114 {
00115 char *word = NULL;
00116 char *word_end = NULL;
00117 char *word_end2 = NULL;
00118 const char *equal_sign = NULL;
00119
00120 if ((word_end = strchr(cur_pos,',')))
00121 {
00122 if ((word_end2 = strchr(cur_pos,']')) < word_end)
00123 {
00124 word_end = word_end2;
00125 if ((strchr(word_end+1,']') && !strchr(word_end+1,'['))
00126 || (strchr(word_end+1,']') < strchr(word_end+1,'[')))
00127 {
00128 *ambiguous = SPLT_TRUE;
00129 }
00130 }
00131
00132 if (*word_end == ',')
00133 {
00134 if (*(word_end+1) != '@')
00135 {
00136 *ambiguous = SPLT_TRUE;
00137 }
00138 }
00139 }
00140 else
00141 {
00142 word_end = strchr(cur_pos,']');
00143 }
00144
00145 if (word_end <= end_paranthesis)
00146 {
00147 if (*(cur_pos+1) == '=')
00148 {
00149 equal_sign = cur_pos+1;
00150 int string_length = word_end-(equal_sign+1);
00151 if (string_length > 0)
00152 {
00153 word = malloc((string_length+1)*sizeof(char));
00154 memset(word,'\0',(string_length+1)*sizeof(char));
00155 if (word)
00156 {
00157 memcpy(word,equal_sign+1,string_length);
00158 word[string_length] = '\0';
00159 }
00160 else
00161 {
00162 *error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
00163 return NULL;
00164 }
00165 }
00166 else
00167 {
00168 *ambiguous = SPLT_TRUE;
00169 }
00170 }
00171 else
00172 {
00173 *ambiguous = SPLT_TRUE;
00174 }
00175 }
00176
00177 return word;
00178 }
00179
00180 int splt_tp_put_tags_from_string(splt_state *state, const char *tags, int *error)
00181 {
00182 if (tags == NULL)
00183 {
00184 return SPLT_FALSE;
00185 }
00186
00187 tags_parser_utils *tpu = splt_tp_tpu_new(state, error);
00188 if (*error < 0) { goto end; }
00189
00190 tpu->position = tags;
00191 while ((tpu->position = strchr(tpu->position, '[')))
00192 {
00193 splt_tp_process_tags(tags, tpu, state, error);
00194 if (*error < 0) { goto end; }
00195
00196 splt_tu_append_tags_to_state(state, tpu->current_tags,
00197 !tpu->original_tags_found, error);
00198 if (*error < 0) { goto end; }
00199
00200 if (tpu->set_all_tags)
00201 {
00202 tpu->we_had_all_tags = SPLT_TRUE;
00203 tpu->set_all_tags = SPLT_FALSE;
00204 splt_tu_copy_tags(tpu->all_tags, splt_tu_get_tags_like_x(state), error);
00205 if (*error < 0) { goto end; }
00206 }
00207 else if (tpu->we_had_all_tags && !tpu->original_tags_found)
00208 {
00209 int index = state->split.real_tagsnumber - 1;
00210 splt_tu_set_new_tags_where_current_tags_are_null(state,
00211 tpu->current_tags, tpu->all_tags, index, error);
00212 if (*error < 0) { goto end; }
00213 }
00214
00215 tpu->tags_counter++;
00216 }
00217
00218 end:
00219 ;
00220 int ambigous = tpu->ambigous;
00221 splt_tp_tpu_free(&tpu);
00222
00223 return ambigous;
00224 }
00225
00226 static void splt_tp_tpu_set_ambigous_if_more_than_one_variable(tags_parser_utils *tpu)
00227 {
00228 if ((tpu->title_counter > 1) ||
00229 (tpu->artist_counter > 1) ||
00230 (tpu->album_counter > 1) ||
00231 (tpu->performer_counter > 1) ||
00232 (tpu->year_counter > 1) ||
00233 (tpu->comment_counter > 1) ||
00234 (tpu->tracknumber_counter > 1) ||
00235 (tpu->genre_counter > 1))
00236 {
00237 tpu->ambigous = SPLT_TRUE;
00238 }
00239 }
00240
00241 static char *splt_tp_find_tag_start(const char *position, const char *end_paranthesis)
00242 {
00243 const char *ptr = position;
00244
00245 int comma_or_open_bracket_found = SPLT_FALSE;
00246
00247 while (ptr <= end_paranthesis)
00248 {
00249 if (*ptr == ',' || *ptr == '[')
00250 {
00251 comma_or_open_bracket_found = SPLT_TRUE;
00252 break;
00253 }
00254 ptr++;
00255 }
00256
00257 if (!comma_or_open_bracket_found)
00258 {
00259 return NULL;
00260 }
00261
00262 return strchr(ptr, '@');
00263 }
00264
00265 static void splt_tp_process_tags(const char *tags, tags_parser_utils *tpu,
00266 splt_state *state, int *error)
00267 {
00268 splt_tp_look_for_all_tags_char(tags, tpu, state);
00269
00270 splt_tp_tpu_reset_for_new_tags(state, tpu, error);
00271 if (*error < 0) { return; }
00272
00273 const char *end_paranthesis = splt_tp_look_for_end_paranthesis(tpu);
00274 if (!end_paranthesis) { return; }
00275
00276 tpu->position++;
00277
00278 char *tag_start = NULL;
00279 while ((tag_start = splt_tp_find_tag_start(tpu->position-1, end_paranthesis)))
00280 {
00281 if (tag_start >= end_paranthesis)
00282 {
00283 break;
00284 }
00285
00286 tpu->position = tag_start + 1;
00287
00288 splt_tp_process_tag_variable(tpu->position, end_paranthesis, tpu, state, error);
00289 if (*error < 0)
00290 {
00291 return;
00292 }
00293
00294 if (tpu->position == tag_start + 1)
00295 {
00296 tpu->position++;
00297 }
00298 }
00299
00300 splt_tp_set_track_from_parsed_tracknumber(tpu, state, error);
00301
00302 splt_tp_tpu_set_ambigous_if_more_than_one_variable(tpu);
00303 }
00304
00305 static void splt_tp_set_track_from_parsed_tracknumber(tags_parser_utils *tpu,
00306 splt_state *state, int *error)
00307 {
00308 const char *tracknumber = splt_tp_tpu_get_tracknumber(tpu);
00309
00310 if (tracknumber)
00311 {
00312 int is_number = SPLT_TRUE;
00313 int i = 0;
00314 for (i = 0;i < strlen(tracknumber);i++)
00315 {
00316 if (!isdigit(tracknumber[i]))
00317 {
00318 is_number = SPLT_FALSE;
00319 tpu->ambigous = SPLT_TRUE;
00320 }
00321 }
00322
00323 int track = 1;
00324 if (is_number)
00325 {
00326 track = atoi(tracknumber);
00327 }
00328
00329 splt_tp_tpu_set_tags_value(tpu, SPLT_TAGS_TRACK, &track);
00330 }
00331 else if (tpu->auto_increment_tracknumber)
00332 {
00333 splt_tags last_tags = splt_tu_get_last_tags(state);
00334 int track = last_tags.track + 1;
00335 splt_tp_tpu_set_tags_value(tpu, SPLT_TAGS_TRACK, &track);
00336 }
00337 }
00338
00339 static void splt_tp_process_tag_variable(const char *tag_variable_start,
00340 const char *end_paranthesis, tags_parser_utils *tpu, splt_state *state,
00341 int *error)
00342 {
00343 char tag_variable = *tag_variable_start;
00344 switch (tag_variable)
00345 {
00346 case 'o':
00347 splt_tp_process_original_tags_variable(tpu, state, error);
00348 if (*error < 0) { return; }
00349 break;
00350 case 'a':
00351 splt_tp_process_str_tags_variable(tag_variable_start, end_paranthesis,
00352 SPLT_TAGS_ARTIST, tpu, state, error);
00353 break;
00354 case 'p':
00355 splt_tp_process_str_tags_variable(tag_variable_start, end_paranthesis,
00356 SPLT_TAGS_PERFORMER, tpu, state, error);
00357 break;
00358 case 'b':
00359 splt_tp_process_str_tags_variable(tag_variable_start, end_paranthesis,
00360 SPLT_TAGS_ALBUM, tpu, state, error);
00361 break;
00362 case 't':
00363 splt_tp_process_str_tags_variable(tag_variable_start, end_paranthesis,
00364 SPLT_TAGS_TITLE, tpu, state, error);
00365 break;
00366 case 'c':
00367 splt_tp_process_str_tags_variable(tag_variable_start, end_paranthesis,
00368 SPLT_TAGS_COMMENT, tpu, state, error);
00369 break;
00370 case 'g':
00371 splt_tp_process_str_tags_variable(tag_variable_start, end_paranthesis,
00372 SPLT_TAGS_GENRE, tpu, state, error);
00373 break;
00374 case 'y':
00375 splt_tp_process_str_tags_variable(tag_variable_start, end_paranthesis,
00376 SPLT_TAGS_YEAR, tpu, state, error);
00377 break;
00378 case 'n':
00379 splt_tp_process_tracknumber_variable(tag_variable_start,
00380 end_paranthesis, tpu, state, error);
00381 break;
00382 case 'N':
00383 splt_tp_process_auto_increment_tracknumber_variable(tag_variable_start,
00384 end_paranthesis, tpu, state, error);
00385 break;
00386 default:
00387 tpu->ambigous = SPLT_TRUE;
00388 break;
00389 }
00390
00391 splt_tp_check_ambigous_next_position(tag_variable_start, tpu);
00392 }
00393
00394 static void splt_tp_process_tracknumber_variable(const char *tag_variable_start,
00395 const char *end_paranthesis, tags_parser_utils *tpu, splt_state *state,
00396 int *error)
00397 {
00398 char *tag_value = splt_tp_parse_tag_word(tag_variable_start, end_paranthesis,
00399 &tpu->ambigous, error);
00400 if (*error < 0) { return; }
00401
00402 if (tag_value)
00403 {
00404 tpu->position += strlen(tag_value) + 1;
00405 splt_tp_tpu_increment_tags_field_counter(tpu, SPLT_TAGS_TRACK);
00406 splt_tp_tpu_set_tracknumber(tpu, tag_value, error);
00407 if (*error < 0) { return; }
00408
00409 free(tag_value);
00410 tag_value = NULL;
00411 }
00412 }
00413
00414 static void splt_tp_process_auto_increment_tracknumber_variable(
00415 const char *tag_variable_start, const char *end_paranthesis,
00416 tags_parser_utils *tpu, splt_state *state, int *error)
00417 {
00418 char *tag_value = splt_tp_parse_tag_word(tag_variable_start, end_paranthesis,
00419 &tpu->ambigous, error);
00420 if (*error < 0) { return; }
00421
00422 splt_o_set_int_option(state, SPLT_OPT_AUTO_INCREMENT_TRACKNUMBER_TAGS, SPLT_TRUE);
00423
00424 if (tag_value)
00425 {
00426 tpu->position += strlen(tag_value) + 1;
00427 splt_tp_tpu_set_tracknumber(tpu, tag_value, error);
00428 if (*error < 0) { return; }
00429
00430 free(tag_value);
00431 tag_value = NULL;
00432 }
00433
00434 if (tpu->set_all_tags)
00435 {
00436 tpu->auto_increment_tracknumber = SPLT_TRUE;
00437 }
00438 }
00439
00440 static const char *splt_tp_tpu_get_tracknumber(tags_parser_utils *tpu)
00441 {
00442 return tpu->current_tracknumber;
00443 }
00444
00445 static void splt_tp_tpu_set_tracknumber(tags_parser_utils *tpu,
00446 const char *tracknumber, int *error)
00447 {
00448 int err = splt_su_copy(tracknumber, &tpu->current_tracknumber);
00449 if (err < 0) { *error = err; return; }
00450 }
00451
00452 static void splt_tp_process_str_tags_variable(const char *tag_variable_start,
00453 const char *end_paranthesis, int tags_field,
00454 tags_parser_utils *tpu, splt_state *state, int *error)
00455 {
00456 char *tag_value = splt_tp_parse_tag_word(tag_variable_start, end_paranthesis,
00457 &tpu->ambigous, error);
00458 if (*error < 0) { return; }
00459
00460 if (tag_value)
00461 {
00462 splt_tp_tpu_set_tags_value(tpu, tags_field, tag_value);
00463
00464 tpu->position += strlen(tag_value) + 1;
00465 splt_tp_tpu_increment_tags_field_counter(tpu, tags_field);
00466
00467 free(tag_value);
00468 tag_value = NULL;
00469 }
00470 }
00471
00472 static void splt_tp_check_ambigous_next_position(const char *tag_variable_start,
00473 tags_parser_utils *tpu)
00474 {
00475 char next_position = *(tpu->position+1);
00476 if ((next_position != ',') &&
00477 (next_position != ']'))
00478 {
00479 tpu->ambigous = SPLT_TRUE;
00480 }
00481 }
00482
00483 static void splt_tp_process_original_tags_variable(tags_parser_utils *tpu,
00484 splt_state *state, int *error)
00485 {
00486 if (tpu->original_tags_found)
00487 {
00488 tpu->ambigous = SPLT_TRUE;
00489 }
00490
00491 if (splt_io_input_is_stdin(state))
00492 {
00493 return;
00494 }
00495
00496 splt_o_lock_messages(state);
00497
00498 splt_tp_get_original_tags(state, error);
00499 if (*error < 0) { goto end; }
00500
00501 int err = splt_tu_append_original_tags(state);
00502 if (err < 0) { *error = err; goto end; }
00503
00504 if (tpu->set_all_tags)
00505 {
00506 splt_tags last_tags = splt_tu_get_last_tags(state);
00507 splt_tu_copy_tags(&last_tags, tpu->all_tags, error);
00508 tpu->all_tags->set_original_tags = SPLT_TRUE;
00509 if (*error < 0) { goto end; }
00510 }
00511
00512 tpu->original_tags_found = SPLT_TRUE;
00513
00514 if (splt_tp_tpu_has_one_current_tag_set(tpu))
00515 {
00516 tpu->ambigous = SPLT_TRUE;
00517 }
00518
00519 end:
00520 splt_o_unlock_messages(state);
00521 }
00522
00523 static void splt_tp_get_original_tags(splt_state *state, int *error)
00524 {
00525 splt_check_file_type(state, error);
00526 if (*error < 0) { return; }
00527
00528 splt_o_lock_messages(state);
00529
00530 splt_p_init(state, error);
00531 if (*error < 0) { return; }
00532
00533 splt_tu_get_original_tags(state, error);
00534
00535 splt_p_end(state, error);
00536
00537 return;
00538 }
00539
00540 static char *splt_tp_look_for_end_paranthesis(tags_parser_utils *tpu)
00541 {
00542 char *end_paranthesis = strchr(tpu->position,']');
00543 if (!end_paranthesis)
00544 {
00545 tpu->ambigous = SPLT_TRUE;
00546 }
00547 else
00548 {
00549 char after_end_paranthesis = *(end_paranthesis+1);
00550 if ((after_end_paranthesis != '[') &&
00551 (after_end_paranthesis != '%') &&
00552 (after_end_paranthesis != '\0'))
00553 {
00554 tpu->ambigous = SPLT_TRUE;
00555 }
00556 }
00557
00558 return end_paranthesis;
00559 }
00560
00561 static void splt_tp_look_for_all_tags_char(const char *tags,
00562 tags_parser_utils *tpu, splt_state *state)
00563 {
00564 if ((tpu->position != tags) && (*(tpu->position-1) == '%'))
00565 {
00566 splt_o_set_int_option(state,
00567 SPLT_OPT_ALL_REMAINING_TAGS_LIKE_X, tpu->tags_counter);
00568 tpu->set_all_tags = SPLT_TRUE;
00569
00570 splt_tu_free_one_tags_content(tpu->all_tags);
00571 }
00572 }
00573
00574 static tags_parser_utils *splt_tp_tpu_new(splt_state *state, int *error)
00575 {
00576 tags_parser_utils *tpu = NULL;
00577
00578 tpu = malloc(sizeof(tags_parser_utils));
00579 if (tpu == NULL)
00580 {
00581 goto mem_error;
00582 }
00583
00584 tpu->ambigous = SPLT_FALSE;
00585 tpu->tags_counter = 0;
00586 tpu->set_all_tags = SPLT_FALSE;
00587 tpu->we_had_all_tags = SPLT_FALSE;
00588
00589 tpu->all_tags = splt_tu_new_tags(state, error);
00590 if (*error < 0) { goto mem_error; }
00591
00592 tpu->current_tags = splt_tu_new_tags(state, error);
00593 if (*error < 0) { goto mem_error; }
00594
00595 tpu->current_tracknumber = NULL;
00596
00597 splt_tp_tpu_reset_for_new_tags(state, tpu, error);
00598 if (*error < 0) { goto mem_error; }
00599
00600 tpu->auto_increment_tracknumber = SPLT_FALSE;
00601
00602 tpu->position = NULL;
00603
00604 return tpu;
00605
00606 mem_error:
00607 splt_tp_tpu_free(&tpu);
00608 return NULL;
00609 }
00610
00611 static void splt_tp_tpu_reset_for_new_tags(splt_state *state, tags_parser_utils *tpu, int *error)
00612 {
00613 tpu->title_counter = 0;
00614 tpu->artist_counter = 0;
00615 tpu->album_counter = 0;
00616 tpu->performer_counter = 0;
00617 tpu->year_counter = 0;
00618 tpu->comment_counter = 0;
00619 tpu->tracknumber_counter = 0;
00620 tpu->genre_counter = 0;
00621
00622 splt_tu_free_one_tags_content(tpu->current_tags);
00623
00624 tpu->original_tags_found = SPLT_FALSE;
00625
00626 if (tpu->current_tracknumber)
00627 {
00628 free(tpu->current_tracknumber);
00629 tpu->current_tracknumber = NULL;
00630 }
00631 }
00632
00633 static void splt_tp_tpu_increment_tags_field_counter(tags_parser_utils *tpu,
00634 int tags_field)
00635 {
00636 switch(tags_field)
00637 {
00638 case SPLT_TAGS_TITLE:
00639 tpu->title_counter++;
00640 break;
00641 case SPLT_TAGS_ARTIST:
00642 tpu->artist_counter++;
00643 break;
00644 case SPLT_TAGS_ALBUM:
00645 tpu->album_counter++;
00646 break;
00647 case SPLT_TAGS_YEAR:
00648 tpu->year_counter++;
00649 break;
00650 case SPLT_TAGS_COMMENT:
00651 tpu->comment_counter++;
00652 break;
00653 case SPLT_TAGS_PERFORMER:
00654 tpu->performer_counter++;
00655 break;
00656 case SPLT_TAGS_TRACK:
00657 tpu->tracknumber_counter++;
00658 break;
00659 case SPLT_TAGS_VERSION:
00660 ;
00661 break;
00662 case SPLT_TAGS_GENRE:
00663 tpu->genre_counter++;
00664 ;
00665 break;
00666 }
00667 }
00668
00669 static void splt_tp_tpu_set_all_tags_field(tags_parser_utils *tpu,
00670 int tags_field, const void *tag_value)
00671 {
00672 if (tpu->set_all_tags)
00673 {
00674 splt_tu_set_field_on_tags(tpu->all_tags, tags_field, tag_value);
00675 }
00676 }
00677
00678 static void splt_tp_tpu_set_current_tags_field(tags_parser_utils *tpu,
00679 int tags_field, const void *tag_value)
00680 {
00681 splt_tu_set_field_on_tags(tpu->current_tags, tags_field, tag_value);
00682 }
00683
00684 static void splt_tp_tpu_set_tags_value(tags_parser_utils *tpu,
00685 int tags_field, const void *tag_value)
00686 {
00687 splt_tp_tpu_set_all_tags_field(tpu, tags_field, tag_value);
00688 splt_tp_tpu_set_current_tags_field(tpu, tags_field, tag_value);
00689 }
00690
00691 static void splt_tp_tpu_free(tags_parser_utils **tpu)
00692 {
00693 if (!tpu || !*tpu)
00694 {
00695 return;
00696 }
00697
00698 splt_tu_free_one_tags(&(*tpu)->current_tags);
00699 splt_tu_free_one_tags(&(*tpu)->all_tags);
00700
00701 if ((*tpu)->current_tracknumber)
00702 {
00703 free((*tpu)->current_tracknumber);
00704 (*tpu)->current_tracknumber = NULL;
00705 }
00706
00707 free(*tpu);
00708 *tpu = NULL;
00709 }
00710
00711 static int splt_tp_tpu_has_one_current_tag_set(tags_parser_utils *tpu)
00712 {
00713 return splt_tu_has_one_tag_set(tpu->current_tags);
00714 }
00715