1 /**********************************************************
2 *
3 * libmp3splt -- library based on mp3splt,
4 * for mp3/ogg splitting without decoding
5 *
6 * Copyright (c) 2002-2005 M. Trotta - <mtrotta@users.sourceforge.net>
7 * Copyright (c) 2005-2014 Alexandru Munteanu - m@ioalex.net
8 *
9 * http://mp3splt.sourceforge.net
10 *
11 *********************************************************/
12
13 /**********************************************************
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
28 * USA.
29 *
30 *********************************************************/
31
32 /*! \file
33
34 Automatic generation of filenams for split files from tags.
35 */
36 #include <string.h>
37 #include <ctype.h>
38 #include <math.h>
39
40 #include "splt.h"
41
42 static void splt_of_trim_on_separator_characters(char *filename);
43 static const char *splt_of_goto_last_non_separator_character(const char *format);
44
duplicate_and_clean(splt_state * state,const char * str,int * error)45 static char *duplicate_and_clean(splt_state *state, const char *str, int *error)
46 {
47 char *dup = strdup(str);
48 if (!dup)
49 {
50 *error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
51 return NULL;
52 }
53
54 splt_su_clean_string(state, dup, error);
55 if (error < 0)
56 {
57 free(dup);
58 return NULL;
59 }
60
61 return dup;
62 }
63
64 /*! \brief Is a placeholder char valid in a filename format string?
65
66 \param v The character that is to be tested
67 \param amb True, if the character is valid
68 \return The value that is returned in amb, as well.
69
70 \todo Why do we need amb?
71 */
splt_of_output_variable_is_valid(char v,int * amb)72 static short splt_of_output_variable_is_valid(char v, int *amb)
73 {
74 switch (v)
75 {
76 case 's':
77 case 'S':
78 case 'm':
79 case 'M':
80 case 'h':
81 case 'H':
82 case 'a':
83 case 'A':
84 case 'b':
85 case 'f':
86 case 'd':
87 case 'g':
88 case 'p':
89 break;
90 case 't':
91 case 'l':
92 case 'L':
93 case 'u':
94 case 'U':
95 case 'n':
96 case 'N':
97 *amb = SPLT_OUTPUT_FORMAT_OK;
98 break;
99 default:
100 return SPLT_FALSE;
101 }
102
103 return SPLT_TRUE;
104 }
105
splt_of_parse_outformat(char * s,splt_state * state)106 int splt_of_parse_outformat(char *s, splt_state *state)
107 {
108 char *ptrs = NULL, *ptre = NULL;
109 int i=0, amb = SPLT_OUTPUT_FORMAT_AMBIGUOUS, len=0;
110
111 size_t size = strlen(s);
112 for (i = 0; i < size; i++)
113 {
114 if (s[i]=='+')
115 {
116 s[i]=' ';
117 }
118 else
119 {
120 if (s[i] == SPLT_VARCHAR)
121 {
122 s[i]='%';
123 }
124 }
125 }
126
127 ptrs = s;
128 i = 0;
129 ptre = strchr(ptrs+1, '%');
130 if (s[0] != '%')
131 {
132 if (ptre==NULL)
133 {
134 len = strlen(ptrs);
135 }
136 else
137 {
138 len = ptre-ptrs;
139 }
140 if (len > SPLT_MAXOLEN)
141 {
142 len = SPLT_MAXOLEN;
143 }
144 strncpy(state->oformat.format[i++], ptrs, len);
145 }
146 else
147 {
148 ptre = s;
149 }
150
151 //if stdout, NOT ambiguous
152 if (splt_io_input_is_stdout(state))
153 {
154 return SPLT_OUTPUT_FORMAT_OK;
155 }
156
157 char err[2] = { '\0' };
158
159 if (ptre == NULL)
160 {
161 splt_e_set_error_data(state, err);
162 return SPLT_OUTPUT_FORMAT_AMBIGUOUS;
163 }
164 ptrs = ptre;
165
166 char *last_ptre = NULL;
167 while (((ptre = strchr(ptrs+1, '%')) != NULL) && (i < SPLT_OUTNUM))
168 {
169 char cf = *(ptrs+1);
170
171 len = ptre-ptrs;
172 if (len > SPLT_MAXOLEN)
173 {
174 len = SPLT_MAXOLEN;
175 }
176
177 if (!splt_of_output_variable_is_valid(cf, &amb))
178 {
179 err[0] = cf;
180 splt_e_set_error_data(state, err);
181 return SPLT_OUTPUT_FORMAT_ERROR;
182 }
183
184 strncpy(state->oformat.format[i++], ptrs, len);
185 ptrs = ptre;
186 last_ptre = ptre;
187 }
188
189 if (last_ptre && *last_ptre != '\0')
190 {
191 char v = *(last_ptre+1);
192 if (!splt_of_output_variable_is_valid(v, &amb))
193 {
194 err[0] = v;
195 splt_e_set_error_data(state, err);
196 return SPLT_OUTPUT_FORMAT_ERROR;
197 }
198 }
199
200 strncpy(state->oformat.format[i], ptrs, strlen(ptrs));
201
202 if (ptrs[1]=='t')
203 {
204 amb = SPLT_OUTPUT_FORMAT_OK;
205 }
206
207 if (ptrs[1]=='n')
208 {
209 amb = SPLT_OUTPUT_FORMAT_OK;
210 }
211
212 return amb;
213 }
214
splt_u_get_format_ptr(const char * format,char * temp,int * number_of_digits_to_output)215 static const char *splt_u_get_format_ptr(const char *format, char *temp,
216 int *number_of_digits_to_output)
217 {
218 int format_length = strlen(format);
219 const char *format_ptr = format;
220
221 if ((format_length > 2) && isdigit(format[2]))
222 {
223 if (number_of_digits_to_output)
224 {
225 sscanf(&format[2], "%d", number_of_digits_to_output);
226 }
227
228 temp[2] = format[2];
229 format_ptr = format + 1;
230 }
231 else
232 {
233 if (number_of_digits_to_output)
234 {
235 *number_of_digits_to_output = -1;
236 }
237 }
238
239 return format_ptr;
240 }
241
splt_u_get_requested_num_of_digits(splt_state * state,const char * format,int * requested_num_of_digits,int is_alpha)242 static int splt_u_get_requested_num_of_digits(splt_state *state, const char *format,
243 int *requested_num_of_digits, int is_alpha)
244 {
245 int format_length = strlen(format);
246 int number_of_digits = 0;
247 if (is_alpha)
248 {
249 number_of_digits = state->oformat.output_alpha_format_digits;
250 }
251 else
252 {
253 number_of_digits = splt_of_get_oformat_number_of_digits_as_int(state);
254 }
255 int max_number_of_digits = number_of_digits;
256 *requested_num_of_digits = number_of_digits;
257
258 if ((format_length > 2) && isdigit(format[2]))
259 {
260 *requested_num_of_digits = format[2] - '0';
261 }
262
263 if (*requested_num_of_digits > number_of_digits)
264 {
265 max_number_of_digits = *requested_num_of_digits;
266 }
267
268 return max_number_of_digits;
269 }
270
271 /*! Encode track number as 'A', 'B', ... 'Z', 'AA, 'AB', ...
272 *
273 * This is not simply "base 26"; note that the lowest 'digit' is from 'A' to
274 * 'Z' (base 26), but all higher digits are 'A' to 'Z' plus 'nothing', i.e.,
275 * base 27. In other words, since after 'Z' comes 'AA', we cannot use 'AA'
276 * as the padded version of track number 1 ('A').
277 *
278 * This means that there are two distinct work modes:
279 * - The normal encoding is as described above.
280 * - When the user has specified the number of digits (padding), we encode
281 * the track number as simple base-26: 'AAA', 'AAB', ... 'AAZ', 'ABA',
282 * 'ABB', ...
283 */
splt_u_alpha_track(splt_state * state,int nfield,char * fm,int fm_length,int number_of_digits,int tracknumber)284 static void splt_u_alpha_track(splt_state *state, int nfield,
285 char *fm, int fm_length, int number_of_digits, int tracknumber)
286 {
287 char *format = state->oformat.format[nfield];
288 int lowercase = (toupper(format[1]) == 'L');
289 char a = lowercase ? 'a' : 'A';
290 int zerobased = tracknumber - 1;
291 int i = 1, min_digits = state->oformat.output_alpha_format_digits;
292
293 if (number_of_digits > 1)
294 {
295 /* Padding required => simple base-26 encoding */
296 if (number_of_digits < min_digits)
297 number_of_digits = min_digits;
298 for (i = 1; i <= number_of_digits; ++ i, zerobased /= 26)
299 {
300 int digit = (zerobased % 26);
301 fm[number_of_digits - i] = a + digit;
302 }
303 }
304 else
305 {
306 /* No padding: First letter base-26, others base-27 */
307 number_of_digits = min_digits;
308
309 /* Start with the first, base-26 'digit' */
310 fm[number_of_digits - 1] = a + (zerobased % 26);
311
312 /* Now handle all other digits */
313 zerobased /= 26;
314 for (i = 2; i <= number_of_digits; ++ i, zerobased /= 27)
315 {
316 int digit = (zerobased % 27);
317 fm[number_of_digits - i] = a + digit - 1;
318 }
319 }
320
321 int offset = 0;
322 if ((strlen(format) > 2) && isdigit(format[2]))
323 {
324 offset = 1;
325 }
326 snprintf(fm + number_of_digits, fm_length - number_of_digits,
327 "%s", format + 2 + offset);
328 }
329
splt_of_get_number_of_digits_from_total_time(splt_state * state)330 char splt_of_get_number_of_digits_from_total_time(splt_state *state)
331 {
332 long total_time = splt_t_get_total_time(state);
333 if (total_time <= 0)
334 {
335 return '2';
336 }
337
338 long minutes = total_time / 100 / 60;
339 int i = (int) (log10(minutes));
340 char number_of_digits = (char) (i + '1');
341 if (number_of_digits == '1')
342 {
343 return '2';
344 }
345
346 return number_of_digits;
347 }
348
349 /*! \brief Automagically set the filename for a split point
350
351 The filename is generated from the tags and the output format
352 string.
353
354 \param state The central structure libmp3splt keeps all its data in
355 \param current_splt The number of the split point to determine the
356 filename for.
357 */
splt_of_put_output_format_filename(splt_state * state,int current_split)358 int splt_of_put_output_format_filename(splt_state *state, int current_split)
359 {
360 int error = SPLT_OK;
361
362 int output_filenames = splt_o_get_int_option(state, SPLT_OPT_OUTPUT_FILENAMES);
363 if (output_filenames == SPLT_OUTPUT_CUSTOM)
364 {
365 return error;
366 }
367
368 char *temp = NULL;
369 char *fm = NULL;
370 int i = 0;
371 char *output_filename = NULL;
372 int output_filename_size = 0;
373
374 const char *title = NULL;
375 const char *artist = NULL;
376 const char *album = NULL;
377 const char *genre = NULL;
378 const char *performer = NULL;
379 const char *artist_or_performer = NULL;
380 char *original_filename = NULL;
381
382 int split_file_number = splt_t_get_current_split_file_number(state);
383 int tags_index = split_file_number - 1;
384
385 if (current_split == -1)
386 {
387 current_split = splt_t_get_current_split_file_number(state) - 1;
388 }
389
390 long mins = -1; long secs = -1; long hundr = -1;
391 long point_value = splt_sp_get_splitpoint_value(state, current_split, &error);
392 splt_co_get_mins_secs_hundr(point_value, &mins, &secs, &hundr);
393 long next_mins = -1; long next_secs = -1; long next_hundr = -1;
394 long next_point_value = -1;
395 if (splt_sp_splitpoint_exists(state, current_split + 1))
396 {
397 next_point_value = splt_sp_get_splitpoint_value(state, current_split + 1, &error);
398 long total_time = splt_t_get_total_time(state);
399 if (total_time > 0 && next_point_value > total_time)
400 {
401 next_point_value = total_time;
402 }
403 splt_co_get_mins_secs_hundr(next_point_value, &next_mins, &next_secs, &next_hundr);
404 }
405
406 int fm_length = 0;
407
408 //if we get the tags from the first file
409 int remaining_tags_like_x = splt_o_get_int_option(state,SPLT_OPT_ALL_REMAINING_TAGS_LIKE_X);
410 int real_tags_number = 0;
411 if (state->split.tags_group)
412 {
413 real_tags_number = state->split.tags_group->real_tagsnumber;
414 }
415
416 if ((tags_index >= real_tags_number) &&
417 (remaining_tags_like_x != -1))
418 {
419 tags_index = remaining_tags_like_x;
420 }
421
422 const char *output_format = splt_of_get_oformat(state);
423 short write_eof = SPLT_FALSE;
424 if ((next_point_value == LONG_MAX) &&
425 (strcmp(output_format, SPLT_DEFAULT_OUTPUT) == 0))
426 {
427 write_eof = SPLT_TRUE;
428 }
429
430 splt_d_print_debug(state,"The output format is _%s_\n", output_format);
431
432 long mMsShH_value = -1;
433 short eof_written = SPLT_FALSE;
434
435 for (i = 0; i < SPLT_OUTNUM; i++)
436 {
437 if (strlen(state->oformat.format[i]) == 0)
438 {
439 break;
440 }
441
442 //if we have some % in the format (@ has been converted to %)
443 if (state->oformat.format[i][0] == '%')
444 {
445 //we allocate memory for the temp variable
446 if (temp)
447 {
448 free(temp);
449 temp = NULL;
450 }
451
452 int temp_len = strlen(state->oformat.format[i])+10;
453 if ((temp = malloc(temp_len * sizeof(char))) == NULL)
454 {
455 error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
456 goto end;
457 }
458 memset(temp, 0x0, temp_len);
459
460 temp[0] = '%';
461 temp[1] = 's';
462 char char_variable = state->oformat.format[i][1];
463 switch (char_variable)
464 {
465 case 's':
466 mMsShH_value = secs;
467 goto put_value;
468 case 'S':
469 mMsShH_value = next_secs;
470 goto put_value;
471 case 'm':
472 mMsShH_value = mins;
473 goto put_value;
474 case 'M':
475 mMsShH_value = next_mins;
476 goto put_value;
477 case 'h':
478 mMsShH_value = hundr;
479 goto put_value;
480 case 'H':
481 mMsShH_value = next_hundr;
482 put_value:
483 if (!eof_written)
484 {
485 if (write_eof &&
486 (char_variable == 'S' ||
487 char_variable == 'M' ||
488 char_variable == 'H'))
489 {
490 write_eof = SPLT_FALSE;
491 eof_written = SPLT_TRUE;
492
493 fm_length = strlen(temp) + 4;
494 if ((fm = malloc(fm_length * sizeof(char))) == NULL)
495 {
496 error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
497 goto end;
498 }
499 snprintf(fm, fm_length, temp, "EOF");
500 }
501 else if (mMsShH_value != -1)
502 {
503 temp[1] = '0';
504 char number_of_digits = '2';
505 if (char_variable == 'M' || char_variable == 'm')
506 {
507 number_of_digits = splt_of_get_number_of_digits_from_total_time(state);
508 }
509 temp[2] = number_of_digits;
510 temp[3] = 'l';
511 temp[4] = 'd';
512
513 const char *format = NULL;
514 int offset = 5;
515
516 int number_of_digits_to_output = 0;
517 const char *new_format =
518 splt_u_get_format_ptr(state->oformat.format[i], temp, &number_of_digits_to_output);
519
520 if (number_of_digits_to_output == 0 && mMsShH_value == 0)
521 {
522 const char *start_format = state->oformat.format[i] + 3;
523 format = splt_of_goto_last_non_separator_character(start_format);
524 offset = 0;
525
526 splt_of_trim_on_separator_characters(output_filename);
527 }
528 else
529 {
530 format = new_format + 2;
531 }
532
533 int requested_num_of_digits = 0;
534 int max_number_of_digits = splt_u_get_requested_num_of_digits(state,
535 state->oformat.format[i], &requested_num_of_digits, SPLT_FALSE);
536
537 snprintf(temp + offset, temp_len, "%s", format);
538
539 fm_length = strlen(temp) + 1 + max_number_of_digits;
540 if ((fm = malloc(fm_length * sizeof(char))) == NULL)
541 {
542 error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
543 goto end;
544 }
545
546 snprintf(fm, fm_length, temp, mMsShH_value);
547 }
548 }
549 break;
550 case 'A':
551 if (splt_tu_tags_exists(state, tags_index))
552 {
553 artist_or_performer = splt_tu_get_tags_field(state,tags_index, SPLT_TAGS_PERFORMER);
554 if (artist_or_performer == NULL || artist_or_performer[0] == '\0')
555 {
556 artist_or_performer = splt_tu_get_tags_field(state, tags_index, SPLT_TAGS_ARTIST);
557 }
558 }
559 else
560 {
561 artist_or_performer = NULL;
562 }
563
564 //
565 if (artist_or_performer != NULL)
566 {
567 snprintf(temp+2,temp_len, "%s", state->oformat.format[i]+2);
568
569 int artist_length = 0;
570 artist_length = strlen(artist_or_performer);
571 fm_length = strlen(temp) + artist_length + 1;
572 }
573 else
574 {
575 snprintf(temp,temp_len, "%s", state->oformat.format[i]+2);
576 fm_length = strlen(temp) + 1;
577 }
578
579 if ((fm = malloc(fm_length * sizeof(char))) == NULL)
580 {
581 error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
582 goto end;
583 }
584
585 //
586 if (artist_or_performer != NULL)
587 {
588 char *dup = duplicate_and_clean(state, artist_or_performer, &error);
589 if (!dup) { goto end; }
590 snprintf(fm, fm_length, temp, dup);
591 free(dup);
592 }
593 else
594 {
595 snprintf(fm, fm_length, "%s", temp);
596 }
597
598 break;
599 case 'a':
600 if (splt_tu_tags_exists(state, tags_index))
601 {
602 artist = splt_tu_get_tags_field(state, tags_index, SPLT_TAGS_ARTIST);
603 }
604 else
605 {
606 artist = NULL;
607 }
608
609 //
610 if (artist != NULL)
611 {
612 snprintf(temp+2,temp_len, "%s", state->oformat.format[i]+2);
613
614 int artist_length = 0;
615 artist_length = strlen(artist);
616 fm_length = strlen(temp) + artist_length + 1;
617 }
618 else
619 {
620 snprintf(temp,temp_len, "%s", state->oformat.format[i]+2);
621 fm_length = strlen(temp) + 1;
622 }
623
624 if ((fm = malloc(fm_length * sizeof(char))) == NULL)
625 {
626 error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
627 goto end;
628 }
629
630 //
631 if (artist != NULL)
632 {
633 char *dup = duplicate_and_clean(state, artist, &error);
634 if (!dup) { goto end; }
635 snprintf(fm, fm_length, temp, dup);
636 free(dup);
637 }
638 else
639 {
640 snprintf(fm, fm_length, "%s", temp);
641 }
642 break;
643 case 'b':
644 if (splt_tu_tags_exists(state,tags_index))
645 {
646 album = splt_tu_get_tags_field(state, tags_index, SPLT_TAGS_ALBUM);
647 }
648 else
649 {
650 album = NULL;
651 }
652
653 //
654 if (album != NULL)
655 {
656 int album_length = 0;
657 album_length = strlen(album);
658 snprintf(temp+2, temp_len, "%s", state->oformat.format[i]+2);
659
660 fm_length = strlen(temp) + album_length + 1;
661 }
662 else
663 {
664 snprintf(temp,temp_len, "%s", state->oformat.format[i]+2);
665 fm_length = strlen(temp) + 1;
666 }
667
668 if ((fm = malloc(fm_length * sizeof(char))) == NULL)
669 {
670 error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
671 goto end;
672 }
673
674 //
675 if (album != NULL)
676 {
677 char *dup = duplicate_and_clean(state, album, &error);
678 if (!dup) { goto end; }
679 snprintf(fm, fm_length, temp, dup);
680 free(dup);
681 }
682 else
683 {
684 snprintf(fm, fm_length, "%s", temp);
685 }
686 break;
687 case 'g':
688 if (splt_tu_tags_exists(state,tags_index))
689 {
690 genre = splt_tu_get_tags_field(state, tags_index, SPLT_TAGS_GENRE);
691 }
692 else
693 {
694 genre = NULL;
695 }
696
697 //
698 if (genre != NULL)
699 {
700 int genre_length = 0;
701 genre_length = strlen(genre);
702 snprintf(temp+2, temp_len, "%s", state->oformat.format[i]+2);
703
704 fm_length = strlen(temp) + genre_length + 1;
705 }
706 else
707 {
708 snprintf(temp,temp_len, "%s", state->oformat.format[i]+2);
709 fm_length = strlen(temp) + 1;
710 }
711
712 if ((fm = malloc(fm_length * sizeof(char))) == NULL)
713 {
714 error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
715 goto end;
716 }
717
718 //
719 if (genre != NULL)
720 {
721 char *dup = duplicate_and_clean(state, genre, &error);
722 if (!dup) { goto end; }
723 snprintf(fm, fm_length, temp, dup);
724 free(dup);
725 }
726 else
727 {
728 snprintf(fm, fm_length, "%s", temp);
729 }
730 break;
731 case 't':
732 if (splt_tu_tags_exists(state,tags_index))
733 {
734 title = splt_tu_get_tags_field(state, tags_index, SPLT_TAGS_TITLE);
735 }
736 else
737 {
738 title = NULL;
739 }
740
741 //
742 if (title != NULL)
743 {
744 int title_length = 0;
745 title_length = strlen(title);
746 snprintf(temp+2, temp_len, "%s", state->oformat.format[i]+2);
747
748 fm_length = strlen(temp) + title_length + 1;
749 }
750 else
751 {
752 snprintf(temp,temp_len, "%s", state->oformat.format[i]+2);
753 fm_length = strlen(temp) + 1;
754 }
755
756 if ((fm = malloc(fm_length * sizeof(char))) == NULL)
757 {
758 error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
759 goto end;
760 }
761
762 //
763 if (title != NULL)
764 {
765 char *dup = duplicate_and_clean(state, title, &error);
766 if (!dup) { goto end; }
767 snprintf(fm, fm_length, temp, dup);
768 free(dup);
769 }
770 else
771 {
772 snprintf(fm, fm_length, "%s", temp);
773 }
774 break;
775 case 'p':
776 if (splt_tu_tags_exists(state,tags_index))
777 {
778 performer = splt_tu_get_tags_field(state, tags_index, SPLT_TAGS_PERFORMER);
779 }
780 else
781 {
782 performer = NULL;
783 }
784
785 //
786 if (performer != NULL)
787 {
788 int performer_length = 0;
789 performer_length = strlen(performer);
790 snprintf(temp+2, temp_len, "%s", state->oformat.format[i]+2);
791
792 fm_length = strlen(temp) + performer_length + 1;
793 }
794 else
795 {
796 snprintf(temp,temp_len, "%s", state->oformat.format[i]+2);
797 fm_length = strlen(temp) + 1;
798 }
799
800 if ((fm = malloc(fm_length * sizeof(char))) == NULL)
801 {
802 error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
803 goto end;
804 }
805
806 if (performer != NULL)
807 {
808 char *dup = duplicate_and_clean(state, performer, &error);
809 if (!dup) { goto end; }
810 snprintf(fm, fm_length, temp, dup);
811 free(dup);
812 }
813 else
814 {
815 snprintf(fm, fm_length, "%s", temp);
816 }
817 break;
818 case 'l':
819 case 'L':
820 case 'u':
821 case 'U':
822 case 'n':
823 case 'N':
824 temp[1] = '0';
825 temp[2] = splt_of_get_oformat_number_of_digits_as_char(state);
826 temp[3] = 'd';
827
828 int tracknumber = split_file_number;
829
830 //if not time split, or normal split, or silence split or error,
831 //we put the track number from the tags
832 int split_mode = splt_o_get_int_option(state,SPLT_OPT_SPLIT_MODE);
833 if ((isupper(state->oformat.format[i][1])) ||
834 ((split_mode != SPLT_OPTION_TIME_MODE) &&
835 (split_mode != SPLT_OPTION_NORMAL_MODE) &&
836 (split_mode != SPLT_OPTION_SILENCE_MODE) &&
837 (split_mode != SPLT_OPTION_TRIM_SILENCE_MODE) &&
838 (split_mode != SPLT_OPTION_ERROR_MODE) &&
839 (split_mode != SPLT_OPTION_LENGTH_MODE)))
840 {
841 if (splt_tu_tags_exists(state, tags_index))
842 {
843 const int *tags_track = splt_tu_get_tags_field(state, tags_index, SPLT_TAGS_TRACK);
844 if (tags_track && *tags_track != -1)
845 {
846 tracknumber = *tags_track;
847 }
848 }
849 }
850
851 int requested_num_of_digits = 0;
852 int max_num_of_digits = splt_u_get_requested_num_of_digits(state,
853 state->oformat.format[i], &requested_num_of_digits, SPLT_FALSE);
854
855 int alpha_requested_num_of_digits = 0;
856 int alpha_max_num_of_digits = splt_u_get_requested_num_of_digits(state,
857 state->oformat.format[i], &alpha_requested_num_of_digits, SPLT_TRUE);
858
859 int is_numeric = toupper(state->oformat.format[i][1]) == 'N';
860 if (is_numeric)
861 {
862 const char *format =
863 splt_u_get_format_ptr(state->oformat.format[i], temp, NULL);
864
865 snprintf(temp + 4, temp_len, "%s", format + 2);
866 fm_length = strlen(temp) + 1 + max_num_of_digits;
867 }
868 else
869 {
870 fm_length = strlen(state->oformat.format[i]) + 1 + alpha_max_num_of_digits;
871 }
872
873 if ((fm = malloc(fm_length * sizeof(char))) == NULL)
874 {
875 error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
876 goto end;
877 }
878 memset(fm, '\0', fm_length);
879
880 if (tracknumber == -2)
881 {
882 temp[1] = 's';
883 temp[2] = '%';
884 temp[3] = 's';
885 snprintf(fm, fm_length, temp, "", "");
886 }
887 else
888 {
889 if (is_numeric)
890 {
891 snprintf(fm, fm_length, temp, tracknumber);
892 }
893 else
894 {
895 splt_u_alpha_track(state, i, fm, fm_length,
896 alpha_requested_num_of_digits, tracknumber);
897 }
898 }
899 break;
900 case 'f':
901 if (splt_t_get_filename_to_split(state) != NULL)
902 {
903 original_filename = strdup(splt_su_get_fname_without_path(splt_t_get_filename_to_split(state)));
904 if (original_filename)
905 {
906 snprintf(temp+2,temp_len, "%s", state->oformat.format[i]+2);
907
908 splt_su_cut_extension(original_filename);
909
910 int filename_length = strlen(original_filename);
911
912 fm_length = strlen(temp) + filename_length;
913 if ((fm = malloc(fm_length * sizeof(char))) == NULL)
914 {
915 error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
916 goto end;
917 }
918
919 snprintf(fm, fm_length, temp, original_filename);
920 free(original_filename);
921 original_filename = NULL;
922 }
923 else
924 {
925 error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
926 goto end;
927 }
928 }
929 break;
930 case 'd':
931 {
932 char *last_dir = splt_su_get_last_dir_of_fname(splt_t_get_filename_to_split(state), &error);
933 if (error < 0) { goto end; }
934
935 if (last_dir)
936 {
937 snprintf(temp+2, temp_len, "%s", state->oformat.format[i]+2);
938
939 int last_dir_length = strlen(last_dir);
940
941 fm_length = strlen(temp) + last_dir_length;
942 if ((fm = malloc(fm_length * sizeof(char))) == NULL)
943 {
944 error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
945 goto end;
946 }
947
948 snprintf(fm, fm_length, temp, last_dir);
949 free(last_dir);
950 last_dir = NULL;
951 }
952 }
953 break;
954 }
955 }
956 else
957 {
958 fm_length = SPLT_MAXOLEN;
959 if ((fm = malloc(fm_length * sizeof(char))) == NULL)
960 {
961 error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
962 goto end;
963 }
964
965 strncpy(fm, state->oformat.format[i], SPLT_MAXOLEN);
966 }
967
968 int fm_size = 7;
969 if (fm != NULL)
970 {
971 fm_size = strlen(fm);
972 }
973
974 //allocate memory for the output filename
975 if (!output_filename)
976 {
977 if ((output_filename = malloc((1+fm_size)*sizeof(char))) == NULL)
978 {
979 error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
980 goto end;
981 }
982 output_filename_size = fm_size;
983 output_filename[0] = '\0';
984 }
985 else
986 {
987 output_filename_size += fm_size+1;
988 if ((output_filename = realloc(output_filename, output_filename_size * sizeof(char))) == NULL)
989 {
990 error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
991 goto end;
992 }
993 }
994
995 if (fm != NULL)
996 {
997 strcat(output_filename, fm);
998 }
999
1000 //we free fm
1001 if (fm)
1002 {
1003 free(fm);
1004 fm = NULL;
1005 }
1006 }
1007
1008 splt_d_print_debug(state,"The new output filename is _%s_\n", output_filename);
1009 int cur_splt = splt_t_get_current_split(state);
1010 int name_error = splt_sp_set_splitpoint_name(state, cur_splt, output_filename);
1011 if (name_error != SPLT_OK) { error = name_error; }
1012
1013 end:
1014 if (output_filename)
1015 {
1016 free(output_filename);
1017 output_filename = NULL;
1018 }
1019 if (fm)
1020 {
1021 free(fm);
1022 fm = NULL;
1023 }
1024 if (temp)
1025 {
1026 free(temp);
1027 temp = NULL;
1028 }
1029
1030 return error;
1031 }
1032
splt_of_trim_on_separator_characters(char * filename)1033 static void splt_of_trim_on_separator_characters(char *filename)
1034 {
1035 if (!filename)
1036 {
1037 return;
1038 }
1039
1040 int last_index = strlen(filename)-1;
1041 if (last_index < 0)
1042 {
1043 return;
1044 }
1045
1046 while (last_index >= 0)
1047 {
1048 char last_char = filename[last_index];
1049 if (last_char == ':' || last_char == '_' ||
1050 last_char == '-' || last_char == '.')
1051 {
1052 filename[last_index] = '\0';
1053 }
1054 else
1055 {
1056 return;
1057 }
1058
1059 last_index--;
1060 }
1061 }
1062
splt_of_goto_last_non_separator_character(const char * format)1063 static const char *splt_of_goto_last_non_separator_character(const char *format)
1064 {
1065 if (!format)
1066 {
1067 return format;
1068 }
1069
1070 int counter = 0;
1071 int max_length = strlen(format);
1072 while (counter < max_length)
1073 {
1074 if (format[counter] == ':' || format[counter] == '_' ||
1075 format[counter] == '-' || format[counter] == '.')
1076 {
1077 break;
1078 }
1079
1080 counter++;
1081 }
1082
1083 return format + counter;
1084 }
1085
1086