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 All user-accessible functions
35
36 The functions that are actually meant to be called by the user. If
37 this was C++ it would be the "public" section of our object.
38
39 Actually this whole library seems to be written with object orientied
40 programming in mind: All functions expect the address of the object as
41 the first parameter etc. Actually changing the library to be c++
42 should therefore not be too hard a task...
43 */
44
45 #include <sys/stat.h>
46 #include <string.h>
47
48 #include <ltdl.h>
49
50 #include "splt.h"
51
52 const char splt_id3v1_genres[SPLT_ID3V1_NUMBER_OF_GENRES][25] = {
53 {"Blues"},
54 {"Classic Rock"}, {"Country"}, {"Dance"},
55 {"Disco"},{"Funk"},{"Grunge"},{"Hip-Hop"},{"Jazz"},
56 {"Metal"},{"New Age"},{"Oldies"}, {"Other"}, {"Pop"},
57 {"R&B"}, {"Rap"}, {"Reggae"}, {"Rock"}, {"Techno"},
58 {"Industrial"}, {"Alternative"}, {"Ska"}, {"Death metal"},
59 {"Pranks"}, {"Soundtrack"}, {"Euro-Techno"},
60 {"Ambient"}, {"Trip-hop"}, {"Vocal"}, {"Jazz+Funk"},
61 {"Fusion"}, {"Trance"}, {"Classical"}, {"Instrumental"},
62 {"Acid"}, {"House"}, {"Game"}, {"Sound clip"}, {"Gospel"},
63 {"Noise"}, {"Alt. Rock"}, {"Bass"}, {"Soul"}, {"Punk"},
64 {"Space"}, {"Meditative"}, {"Instrumental pop"},
65 {"Instrumental rock"}, {"Ethnic"}, {"Gothic"},{"Darkwave"},
66 {"Techno-Industrial"},{"Electronic"},{"Pop-Folk"},{"Eurodance"},
67 {"Dream"},{"Southern Rock"},{"Comedy"}, {"Cult"},{"Gangsta"},
68 {"Top 40"},{"Christian Rap"},{"Pop/Funk"}, {"Jungle"},
69 {"Native American"},{"Cabaret"},{"New Wave"}, {"Psychedelic"},
70 {"Rave"},{"Showtunes"},{"Trailer"}, {"Lo-Fi"},{"Tribal"},
71 {"Acid Punk"},{"Acid Jazz"}, {"Polka"}, {"Retro"},
72 {"Musical"},{"Rock & Roll"},{"Hard Rock"},
73
74 {"Folk"}, {"Folk-Rock"}, {"National Folk"}, {"Swing"},
75 {"Fast Fusion"}, {"Bebob"}, {"Latin"}, {"Revival"},
76 {"Celtic"}, {"Bluegrass"}, {"Avantgarde"}, {"Gothic Rock"},
77 {"Progressive Rock"}, {"Psychedelic Rock"}, {"Symphonic Rock"},
78 {"Slow Rock"}, {"Big Band"}, {"Chorus"}, {"Easy Listening"},
79 {"Acoustic"}, {"Humour"}, {"Speech"}, {"Chanson"}, {"Opera"},
80 {"Chamber Music"}, {"Sonata"}, {"Symphony"}, {"Booty Bass"},
81 {"Primus"}, {"Porn Groove"}, {"Satire"}, {"Slow Jam"},
82 {"Club"}, {"Tango"}, {"Samba"}, {"Folklore"}, {"Ballad"},
83 {"Power Ballad"}, {"Rhythmic Soul"}, {"Freestyle"}, {"Duet"},
84 {"Punk Rock"}, {"Drum Solo"}, {"A capella"}, {"Euro-House"},
85 {"Dance Hall"},
86
87 {"misc"},
88 };
89
90 int global_debug = SPLT_FALSE;
91
92 /*!
93 \defgroup API The API of libmp3splt
94
95 This group contains all functions of libmp3splt that are meant to be
96 accessed by the user
97
98 @{
99 */
100
101 /*! Initialisation
102
103 creates and returns the new central splt_state structure this
104 library keeps all its data in.
105
106 The next step after initialization is to do a
107 mp3splt_find_plugins() to find any plugins;
108
109 At the end of the program all data we allocate here is freed by
110 calling mp3splt_free_state()
111
112 \param error Contains the error code if an error occours.
113 */
mp3splt_new_state(splt_code * error)114 splt_state *mp3splt_new_state(splt_code *error)
115 {
116 splt_state *state = NULL;
117
118 int erro = SPLT_OK;
119 int *err = &erro;
120 if (error != NULL) { err = error; }
121
122 if (lt_dlinit() != 0)
123 {
124 *err = SPLT_ERROR_CANNOT_INIT_LIBLTDL;
125 }
126 else
127 {
128
129 #ifdef ENABLE_NLS
130 #ifndef __WIN32__
131 bindtextdomain(MP3SPLT_LIB_GETTEXT_DOMAIN, LOCALEDIR);
132 bind_textdomain_codeset(MP3SPLT_LIB_GETTEXT_DOMAIN, nl_langinfo(CODESET));
133 #else
134 bind_textdomain_codeset(MP3SPLT_LIB_GETTEXT_DOMAIN, "UTF-8");
135 #endif
136 #endif
137
138 state = splt_t_new_state(state, err);
139 }
140
141 return state;
142 }
143
144 /*! find plugins and initialise them
145
146 \return The error code if necessary
147 */
mp3splt_find_plugins(splt_state * state)148 splt_code mp3splt_find_plugins(splt_state *state)
149 {
150 return splt_p_find_get_plugins_data(state);
151 }
152
153 /*! this function frees all variables malloc'ed by the library
154
155 call this function ONLY at the end of the program
156 and don't forget to call it.
157
158 \param error The code of any error that might have occoured
159 \param state the splt_state structure that keeps all data for
160 our library
161 */
mp3splt_free_state(splt_state * state)162 splt_code mp3splt_free_state(splt_state *state)
163 {
164 if (!state)
165 {
166 return SPLT_ERROR_STATE_NULL;
167 }
168
169 if (!splt_o_library_locked(state))
170 {
171 splt_o_lock_library(state);
172 splt_t_free_state(state);
173 }
174 else
175 {
176 return SPLT_ERROR_LIBRARY_LOCKED;
177 }
178
179 return SPLT_OK;
180 }
181
182 //! Set the output path
mp3splt_set_path_of_split(splt_state * state,const char * path)183 splt_code mp3splt_set_path_of_split(splt_state *state, const char *path)
184 {
185 int error = SPLT_OK;
186
187 if (state != NULL)
188 {
189 if (!splt_o_library_locked(state))
190 {
191 splt_o_lock_library(state);
192
193 error = splt_t_set_path_of_split(state, path);
194
195 splt_o_unlock_library(state);
196 }
197 else
198 {
199 error = SPLT_ERROR_LIBRARY_LOCKED;
200 }
201 }
202 else
203 {
204 error = SPLT_ERROR_STATE_NULL;
205 }
206
207 return error;
208 }
209
210 /*! Set the m3u filename
211
212 \param state the splt_state structure that keeps all our data
213 \param filename Constains the file name that is to be set
214 */
mp3splt_set_m3u_filename(splt_state * state,const char * filename)215 splt_code mp3splt_set_m3u_filename(splt_state *state, const char *filename)
216 {
217 int error = SPLT_OK;
218
219 if (state != NULL)
220 {
221 if (!splt_o_library_locked(state))
222 {
223 splt_o_lock_library(state);
224
225 error = splt_t_set_m3u_filename(state, filename);
226
227 splt_o_unlock_library(state);
228 }
229 else
230 {
231 error = SPLT_ERROR_LIBRARY_LOCKED;
232 }
233 }
234 else
235 {
236 error = SPLT_ERROR_STATE_NULL;
237 }
238
239 return error;
240 }
241
mp3splt_set_silence_log_filename(splt_state * state,const char * filename)242 splt_code mp3splt_set_silence_log_filename(splt_state *state, const char *filename)
243 {
244 if (state == NULL)
245 {
246 return SPLT_ERROR_STATE_NULL;
247 }
248
249 if (splt_o_library_locked(state))
250 {
251 return SPLT_ERROR_LIBRARY_LOCKED;
252 }
253
254 splt_o_lock_library(state);
255
256 int error = splt_t_set_silence_log_fname(state, filename);
257
258 splt_o_unlock_library(state);
259
260 return error;
261 }
262
mp3splt_set_silence_full_log_filename(splt_state * state,const char * filename)263 splt_code mp3splt_set_silence_full_log_filename(splt_state *state, const char *filename)
264 {
265 if (state == NULL)
266 {
267 return SPLT_ERROR_STATE_NULL;
268 }
269
270 if (splt_o_library_locked(state))
271 {
272 return SPLT_ERROR_LIBRARY_LOCKED;
273 }
274
275 splt_o_lock_library(state);
276
277 int error = splt_t_set_silence_full_log_fname(state, filename);
278
279 splt_o_unlock_library(state);
280
281 return error;
282 }
283
284 /*! \brief Reads out the name of the file that is about to be split
285
286
287 */
mp3splt_get_filename_to_split(splt_state * state)288 const char *mp3splt_get_filename_to_split(splt_state *state)
289 {
290 return splt_t_get_filename_to_split(state);
291 }
292
293 /*! \brief Sets the name of the file that is about to be split
294
295 \param state The central data structure this library keeps its data in
296 \param filename The filename we want to save in state
297 */
mp3splt_set_filename_to_split(splt_state * state,const char * filename)298 splt_code mp3splt_set_filename_to_split(splt_state *state, const char *filename)
299 {
300 int error = SPLT_OK;
301
302 if (state != NULL)
303 {
304 if (!splt_o_library_locked(state))
305 {
306 splt_o_lock_library(state);
307
308 error = splt_t_set_filename_to_split(state, filename);
309
310 splt_o_unlock_library(state);
311 }
312 else
313 {
314 error = SPLT_ERROR_LIBRARY_LOCKED;
315 }
316 }
317 else
318 {
319 error = SPLT_ERROR_STATE_NULL;
320 }
321
322 return error;
323 }
324
mp3splt_set_input_filename_regex(splt_state * state,const char * regex)325 splt_code mp3splt_set_input_filename_regex(splt_state *state, const char *regex)
326 {
327 int error = SPLT_OK;
328
329 if (state != NULL)
330 {
331 if (!splt_o_library_locked(state))
332 {
333 splt_o_lock_library(state);
334
335 error = splt_t_set_input_filename_regex(state, regex);
336
337 splt_o_unlock_library(state);
338 }
339 else
340 {
341 error = SPLT_ERROR_LIBRARY_LOCKED;
342 }
343 }
344 else
345 {
346 error = SPLT_ERROR_STATE_NULL;
347 }
348
349 return error;
350 }
351
mp3splt_set_default_comment_tag(splt_state * state,const char * default_comment)352 splt_code mp3splt_set_default_comment_tag(splt_state *state, const char *default_comment)
353 {
354 int error = SPLT_OK;
355
356 if (state != NULL)
357 {
358 if (!splt_o_library_locked(state))
359 {
360 splt_o_lock_library(state);
361
362 error = splt_t_set_default_comment_tag(state, default_comment);
363
364 splt_o_unlock_library(state);
365 }
366 else
367 {
368 error = SPLT_ERROR_LIBRARY_LOCKED;
369 }
370 }
371 else
372 {
373 error = SPLT_ERROR_STATE_NULL;
374 }
375
376 return error;
377 }
378
mp3splt_set_default_genre_tag(splt_state * state,const char * default_genre_tag)379 splt_code mp3splt_set_default_genre_tag(splt_state *state, const char *default_genre_tag)
380 {
381 int error = SPLT_OK;
382
383 if (state != NULL)
384 {
385 if (!splt_o_library_locked(state))
386 {
387 splt_o_lock_library(state);
388
389 error = splt_t_set_default_genre_tag(state, default_genre_tag);
390
391 splt_o_unlock_library(state);
392 }
393 else
394 {
395 error = SPLT_ERROR_LIBRARY_LOCKED;
396 }
397 }
398 else
399 {
400 error = SPLT_ERROR_STATE_NULL;
401 }
402
403 return error;
404 }
405
406
407 /************************************/
408 /* Set callback functions */
409
410 /*! Register the callback that is called for messages to the client
411
412 \param state The central structure this library keeps all its data in
413 \param message_cb The callback function
414 \return The error code if any error occours
415 */
mp3splt_set_message_function(splt_state * state,void (* message_cb)(const char *,splt_message_type,void *),void * cb_data)416 splt_code mp3splt_set_message_function(splt_state *state,
417 void (*message_cb)(const char *, splt_message_type, void *),
418 void *cb_data)
419 {
420 int error = SPLT_OK;
421
422 if (state != NULL)
423 {
424 state->split.put_message = message_cb;
425 state->split.put_message_cb_data = cb_data;
426 }
427 else
428 {
429 error = SPLT_ERROR_STATE_NULL;
430 }
431
432 return error;
433 }
434
435 /*! Register the callback called with the split filename after split
436
437 \param state The central structure this library keeps all its data in
438 \param file_cb The callback function
439 \return The error code if any error occours
440 */
mp3splt_set_split_filename_function(splt_state * state,void (* file_cb)(const char *,void *),void * cb_data)441 splt_code mp3splt_set_split_filename_function(splt_state *state,
442 void (*file_cb)(const char *, void *), void *cb_data)
443 {
444 int error = SPLT_OK;
445
446 if (state != NULL)
447 {
448 state->split.file_split = file_cb;
449 state->split.file_split_cb_data = cb_data;
450 }
451 else
452 {
453 error = SPLT_ERROR_STATE_NULL;
454 }
455
456 return error;
457 }
458
mp3splt_set_pretend_to_split_write_function(splt_state * state,void (* write_cb)(const void * ptr,size_t size,size_t nmemb,void * cb_data),void * cb_data)459 splt_code mp3splt_set_pretend_to_split_write_function(splt_state *state,
460 void (*write_cb)(const void *ptr, size_t size, size_t nmemb, void *cb_data),
461 void *cb_data)
462 {
463 if (state == NULL)
464 {
465 return SPLT_ERROR_STATE_NULL;
466 }
467
468 state->split.write_cb = write_cb;
469 state->split.write_cb_data = cb_data;
470
471 return SPLT_OK;
472 }
473
474 /*! Register the callback called with progress messages
475
476 \param state The central structure this library keeps all its data in
477 \param progress_cb The callback function
478 \return The error code if any error occours
479 */
mp3splt_set_progress_function(splt_state * state,void (* progress_cb)(splt_progress * p_bar,void *),void * cb_data)480 splt_code mp3splt_set_progress_function(splt_state *state,
481 void (*progress_cb)(splt_progress *p_bar, void *), void *cb_data)
482 {
483 int error = SPLT_OK;
484
485 if (state != NULL)
486 {
487 state->split.p_bar->progress = progress_cb;
488 state->split.p_bar->progress_cb_data = cb_data;
489 }
490 else
491 {
492 error = SPLT_ERROR_STATE_NULL;
493 }
494
495 return error;
496 }
497
mp3splt_progress_get_type(const splt_progress * p_bar)498 int mp3splt_progress_get_type(const splt_progress *p_bar)
499 {
500 return p_bar->progress_type;
501 }
502
mp3splt_progress_get_filename_shorted(const splt_progress * p_bar)503 char *mp3splt_progress_get_filename_shorted(const splt_progress *p_bar)
504 {
505 if (p_bar->filename_shorted)
506 {
507 return strdup(p_bar->filename_shorted);
508 }
509
510 return NULL;
511 }
512
mp3splt_progress_get_current_split(const splt_progress * p_bar)513 int mp3splt_progress_get_current_split(const splt_progress *p_bar)
514 {
515 return p_bar->current_split;
516 }
517
mp3splt_progress_get_max_splits(const splt_progress * p_bar)518 int mp3splt_progress_get_max_splits(const splt_progress *p_bar)
519 {
520 return p_bar->max_splits;
521 }
522
mp3splt_progress_get_silence_found_tracks(const splt_progress * p_bar)523 int mp3splt_progress_get_silence_found_tracks(const splt_progress *p_bar)
524 {
525 return p_bar->silence_found_tracks;
526 }
527
mp3splt_progress_get_silence_db_level(const splt_progress * p_bar)528 float mp3splt_progress_get_silence_db_level(const splt_progress *p_bar)
529 {
530 return p_bar->silence_db_level;
531 }
532
mp3splt_progress_get_percent_progress(const splt_progress * p_bar)533 float mp3splt_progress_get_percent_progress(const splt_progress *p_bar)
534 {
535 return p_bar->percent_progress;
536 }
537
538 /*! Register the callback for the function that calculates silence
539 levels
540
541 \param state The central structure this library keeps all its data in
542 \param get_silence_cb The callback function
543 \return The error code if any error occours
544 */
mp3splt_set_silence_level_function(splt_state * state,void (* get_silence_cb)(long time,float level,void * user_data),void * data)545 splt_code mp3splt_set_silence_level_function(splt_state *state,
546 void (*get_silence_cb)(long time, float level, void *user_data),
547 void *data)
548 {
549 int error = SPLT_OK;
550
551 if (state != NULL)
552 {
553 state->split.get_silence_level = get_silence_cb;
554 state->split.silence_level_client_data = data;
555 }
556 else
557 {
558 error = SPLT_ERROR_STATE_NULL;
559 }
560
561 return error;
562 }
563
564 /************************************/
565 /* Splitpoints */
566
mp3splt_point_new(long splitpoint_value,splt_code * error)567 splt_point *mp3splt_point_new(long splitpoint_value, splt_code *error)
568 {
569 int erro = SPLT_OK;
570 int *err = &erro;
571 if (error != NULL) { err = error; }
572
573 splt_point *point = malloc(sizeof(splt_point));
574 if (point == NULL)
575 {
576 *err = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
577 return NULL;
578 }
579
580 point->value = splitpoint_value;
581 point->name = NULL;
582 point->type = SPLT_SPLITPOINT;
583
584 return point;
585 }
586
mp3splt_point_set_name(splt_point * splitpoint,const char * name)587 splt_code mp3splt_point_set_name(splt_point *splitpoint, const char *name)
588 {
589 if (splitpoint == NULL || name == NULL)
590 {
591 return SPLT_OK;
592 }
593
594 if (splitpoint->name)
595 {
596 free(splitpoint->name);
597 }
598
599 splitpoint->name = strdup(name);
600 if (splitpoint->name == NULL)
601 {
602 return SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
603 }
604
605 return SPLT_OK;
606 }
607
mp3splt_point_set_type(splt_point * splitpoint,splt_type_of_splitpoint type)608 splt_code mp3splt_point_set_type(splt_point *splitpoint, splt_type_of_splitpoint type)
609 {
610 if (splitpoint == NULL)
611 {
612 return SPLT_OK;
613 }
614
615 splitpoint->type = type;
616
617 return SPLT_OK;
618 }
619
620 /*! puts a splitpoint in the state
621
622 \param state The central data structure this library keeps all its
623 data in
624 \param name The file name if we want to set it, else NULL
625 \param split_value The time of this splitpoint in hundreths of
626 seconds. If this walue is LONG_MAX we put the splitpoint to the end of
627 the song (EOF)
628 */
mp3splt_append_splitpoint(splt_state * state,splt_point * splitpoint)629 splt_code mp3splt_append_splitpoint(splt_state *state, splt_point *splitpoint)
630 {
631 int error = SPLT_OK;
632
633 if (state != NULL)
634 {
635 if (!splt_o_library_locked(state))
636 {
637 splt_o_lock_library(state);
638
639 error = splt_sp_append_splitpoint(state,
640 splitpoint->value, splitpoint->name, splitpoint->type);
641
642 splt_sp_free_one_splitpoint(splitpoint);
643
644 splt_o_unlock_library(state);
645 }
646 else
647 {
648 error = SPLT_ERROR_LIBRARY_LOCKED;
649 }
650 }
651 else
652 {
653 error = SPLT_ERROR_STATE_NULL;
654 }
655
656 return error;
657 }
658
659 /*!returns a list containing all the splitpoints
660
661 \param state The structure this library keeps all its data in
662 \param splitpoints_number Will be set to the number of splitpoints by
663 this function
664 \param error Is set to the error code if any error occours
665 */
mp3splt_get_splitpoints(splt_state * state,splt_code * error)666 splt_points *mp3splt_get_splitpoints(splt_state *state, splt_code *error)
667 {
668 int erro = SPLT_OK;
669 int *err = &erro;
670 if (error != NULL) { err = error; }
671
672 if (state == NULL)
673 {
674 *err = SPLT_ERROR_STATE_NULL;
675 return NULL;
676 }
677
678 return splt_sp_get_splitpoints(state);
679 }
680
mp3splt_points_init_iterator(splt_points * splitpoints)681 void mp3splt_points_init_iterator(splt_points *splitpoints)
682 {
683 if (splitpoints == NULL)
684 {
685 return;
686 }
687
688 splitpoints->iterator_counter = 0;
689 }
690
mp3splt_points_next(splt_points * splitpoints)691 const splt_point *mp3splt_points_next(splt_points *splitpoints)
692 {
693 if (splitpoints == NULL)
694 {
695 return NULL;
696 }
697
698 if (splitpoints->iterator_counter < 0 ||
699 splitpoints->iterator_counter >= splitpoints->real_splitnumber)
700 {
701 splitpoints->iterator_counter++;
702 return NULL;
703 }
704
705 splt_point *point = &splitpoints->points[splitpoints->iterator_counter];
706
707 splitpoints->iterator_counter++;
708
709 return point;
710 }
711
mp3splt_point_get_value(const splt_point * point)712 long mp3splt_point_get_value(const splt_point *point)
713 {
714 return point->value;
715 }
716
mp3splt_point_get_type(const splt_point * point)717 splt_type_of_splitpoint mp3splt_point_get_type(const splt_point *point)
718 {
719 return point->type;
720 }
721
mp3splt_point_get_name(const splt_point * point)722 char *mp3splt_point_get_name(const splt_point *point)
723 {
724 if (point->name)
725 {
726 return strdup(point->name);
727 }
728
729 return NULL;
730 }
731
732 /*! erase all the splitpoints
733
734 \param state The structure this library keeps all its data in
735 \param error Is set to the error code if any error occours
736 */
mp3splt_erase_all_splitpoints(splt_state * state)737 splt_code mp3splt_erase_all_splitpoints(splt_state *state)
738 {
739 if (state == NULL)
740 {
741 return SPLT_ERROR_STATE_NULL;
742 }
743
744 if (splt_o_library_locked(state))
745 {
746 return SPLT_ERROR_LIBRARY_LOCKED;
747 }
748
749 splt_o_lock_library(state);
750 splt_sp_free_splitpoints(state);
751 splt_o_unlock_library(state);
752
753 return SPLT_OK;
754 }
755
756 /************************************/
757 /* Tags */
758
mp3splt_tags_new(splt_code * error)759 splt_tags *mp3splt_tags_new(splt_code *error)
760 {
761 int erro = SPLT_OK;
762 int *err = &erro;
763 if (error != NULL) { err = error; }
764
765 return splt_tu_new_tags(err);
766 }
767
mp3splt_tags_set(splt_tags * tags,...)768 splt_code mp3splt_tags_set(splt_tags *tags, ...)
769 {
770 if (tags == NULL)
771 {
772 return SPLT_OK;
773 }
774
775 int error = SPLT_OK;
776
777 va_list ap;
778 va_start(ap, tags);
779
780 splt_tag_key current_key = 0;
781 while ((current_key = va_arg(ap, splt_tag_key)))
782 {
783 const char *current_value = va_arg(ap, const char *);
784 error = splt_tu_set_char_field_on_tag(tags, current_key, current_value);
785 if (error < 0) { break; }
786 }
787
788 va_end(ap);
789
790 return error;
791 }
792
mp3splt_tags_get(splt_tags * tags,splt_tag_key key)793 char *mp3splt_tags_get(splt_tags *tags, splt_tag_key key)
794 {
795 if (key == SPLT_TAGS_TRACK)
796 {
797 const int *track = splt_tu_get_tags_value(tags, SPLT_TAGS_TRACK);
798 char *track_str = malloc(sizeof(char) * 24);
799 if (!track_str) { return NULL; }
800 snprintf(track_str, 24, "%d", *track);
801 return track_str;
802 }
803
804 const char *value = splt_tu_get_tags_value(tags, key);
805 if (value == NULL)
806 {
807 return NULL;
808 }
809
810 return strdup(value);
811 }
812
mp3splt_append_tags(splt_state * state,splt_tags * tags)813 splt_code mp3splt_append_tags(splt_state *state, splt_tags *tags)
814 {
815 int error = SPLT_OK;
816
817 if (state == NULL)
818 {
819 return SPLT_ERROR_STATE_NULL;
820 }
821
822 if (splt_o_library_locked(state))
823 {
824 return SPLT_ERROR_LIBRARY_LOCKED;
825 }
826
827 splt_o_lock_library(state);
828
829 splt_tu_append_tags_to_state(state, tags, SPLT_TRUE, SPLT_FALSE, SPLT_TRUE, &error);
830 mp3splt_free_one_tag(tags);
831
832 splt_o_unlock_library(state);
833
834 return error;
835 }
836
837 //!returns a list containing all the tags
mp3splt_get_tags_group(splt_state * state,splt_code * error)838 splt_tags_group *mp3splt_get_tags_group(splt_state *state, splt_code *error)
839 {
840 int erro = SPLT_OK;
841 int *err = &erro;
842 if (error != NULL) { err = error; }
843
844 if (state != NULL)
845 {
846 return splt_tu_get_tags_group(state);
847 }
848 else
849 {
850 *err = SPLT_ERROR_STATE_NULL;
851 return NULL;
852 }
853 }
854
mp3splt_remove_tags_of_skippoints(splt_state * state)855 splt_code mp3splt_remove_tags_of_skippoints(splt_state *state)
856 {
857 return splt_tu_remove_tags_of_skippoints(state);
858 }
859
mp3splt_tags_group_init_iterator(splt_tags_group * tags_group)860 void mp3splt_tags_group_init_iterator(splt_tags_group *tags_group)
861 {
862 if (tags_group == NULL)
863 {
864 return;
865 }
866
867 tags_group->iterator_counter = 0;
868 }
869
mp3splt_tags_group_next(splt_tags_group * tags_group)870 splt_tags *mp3splt_tags_group_next(splt_tags_group *tags_group)
871 {
872 if (tags_group == NULL)
873 {
874 return NULL;
875 }
876
877 if (tags_group->iterator_counter < 0 ||
878 tags_group->iterator_counter >= tags_group->real_tagsnumber)
879 {
880 tags_group->iterator_counter++;
881 return NULL;
882 }
883
884 return &tags_group->tags[tags_group->iterator_counter++];
885 }
886
mp3splt_read_original_tags(splt_state * state)887 splt_code mp3splt_read_original_tags(splt_state *state)
888 {
889 int error = SPLT_OK;
890
891 if (state == NULL)
892 {
893 return SPLT_ERROR_STATE_NULL;
894 }
895
896 if (splt_o_library_locked(state))
897 {
898 return SPLT_ERROR_LIBRARY_LOCKED;
899 }
900
901 splt_o_lock_library(state);
902
903 splt_check_file_type_and_set_plugin(state, SPLT_FALSE, SPLT_FALSE, &error);
904 if (error < 0) { goto end; }
905
906 splt_o_lock_messages(state);
907
908 splt_p_init(state, &error);
909 if (error < 0) { goto end; }
910
911 splt_tu_get_original_tags(state, &error);
912 if (error < 0) { goto end; }
913
914 splt_p_end(state, &error);
915 if (error < 0) { goto end; }
916
917 end:
918 splt_o_unlock_messages(state);
919 splt_o_unlock_library(state);
920
921 return error;
922 }
923
924 //!puts tags from a string
mp3splt_put_tags_from_string(splt_state * state,const char * tags,splt_code * error)925 int mp3splt_put_tags_from_string(splt_state *state, const char *tags, splt_code *error)
926 {
927 int ambigous = SPLT_FALSE;
928 int erro = SPLT_OK;
929 int *err = &erro;
930 if (error != NULL) { err = error; }
931
932 if (state != NULL)
933 {
934 if (!splt_o_library_locked(state))
935 {
936 splt_o_lock_library(state);
937
938 ambigous = splt_tp_put_tags_from_string(state, tags, err);
939
940 splt_o_unlock_library(state);
941 }
942 else
943 {
944 *err = SPLT_ERROR_LIBRARY_LOCKED;
945 }
946 }
947 else
948 {
949 *err = SPLT_ERROR_STATE_NULL;
950 }
951
952 return ambigous;
953 }
954
955 //!erase all the tags
mp3splt_erase_all_tags(splt_state * state)956 splt_code mp3splt_erase_all_tags(splt_state *state)
957 {
958 if (state == NULL)
959 {
960 return SPLT_ERROR_STATE_NULL;
961 }
962
963 if (splt_o_library_locked(state))
964 {
965 return SPLT_ERROR_LIBRARY_LOCKED;
966 }
967
968 splt_o_lock_library(state);
969 splt_tu_free_tags(state);
970 splt_o_unlock_library(state);
971
972 return SPLT_OK;
973 }
974
975 /************************************/
976 /* Options */
977
mp3splt_set_option(splt_state * state,splt_options option_name,void * value)978 static int mp3splt_set_option(splt_state *state, splt_options option_name, void *value)
979 {
980 int error = SPLT_OK;
981
982 if (state != NULL)
983 {
984 if (!splt_o_library_locked(state))
985 {
986 splt_o_lock_library(state);
987
988 splt_o_set_option(state, option_name, value);
989
990 splt_o_unlock_library(state);
991 }
992 else
993 {
994 error = SPLT_ERROR_LIBRARY_LOCKED;
995 }
996 }
997 else
998 {
999 error = SPLT_ERROR_STATE_NULL;
1000 }
1001
1002 return error;
1003 }
1004
mp3splt_set_int_option(splt_state * state,splt_options option_name,int value)1005 splt_code mp3splt_set_int_option(splt_state *state, splt_options option_name, int value)
1006 {
1007 return mp3splt_set_option(state, option_name, &value);
1008 }
1009
mp3splt_set_long_option(splt_state * state,splt_options option_name,long value)1010 splt_code mp3splt_set_long_option(splt_state *state, splt_options option_name, long value)
1011 {
1012 return mp3splt_set_option(state, option_name, &value);
1013 }
1014
mp3splt_set_float_option(splt_state * state,splt_options option_name,float value)1015 splt_code mp3splt_set_float_option(splt_state *state, splt_options option_name, float value)
1016 {
1017 return mp3splt_set_option(state, option_name, &value);
1018 }
1019
mp3splt_get_int_option(splt_state * state,splt_options option_name,splt_code * error)1020 int mp3splt_get_int_option(splt_state *state, splt_options option_name, splt_code *error)
1021 {
1022 int erro = SPLT_OK;
1023 int *err = &erro;
1024 if (error != NULL) { err = error; }
1025
1026 if (state != NULL)
1027 {
1028 return splt_o_get_int_option(state, option_name);
1029 }
1030 else
1031 {
1032 *err = SPLT_ERROR_STATE_NULL;
1033 return 0;
1034 }
1035 }
1036
mp3splt_get_long_option(splt_state * state,splt_options option_name,splt_code * error)1037 long mp3splt_get_long_option(splt_state *state, splt_options option_name, splt_code *error)
1038 {
1039 int erro = SPLT_OK;
1040 int *err = &erro;
1041 if (error != NULL) { err = error; }
1042
1043 if (state != NULL)
1044 {
1045 return splt_o_get_long_option(state, option_name);
1046 }
1047 else
1048 {
1049 *err = SPLT_ERROR_STATE_NULL;
1050 return 0;
1051 }
1052 }
1053
mp3splt_get_float_option(splt_state * state,splt_options option_name,splt_code * error)1054 float mp3splt_get_float_option(splt_state *state, splt_options option_name, splt_code *error)
1055 {
1056 int erro = SPLT_OK;
1057 int *err = &erro;
1058 if (error != NULL) { err = error; }
1059
1060 if (state != NULL)
1061 {
1062 return splt_o_get_float_option(state, option_name);
1063 }
1064 else
1065 {
1066 *err = SPLT_ERROR_STATE_NULL;
1067 return 0;
1068 }
1069 }
1070
1071 /************************************/
1072 /* Split functions */
1073
1074 /*! main function: Call it and it splits the file for you
1075
1076 state-> splitnumber tells how many splits to do
1077 \return the error code if any error has occoured
1078 */
mp3splt_split(splt_state * state)1079 splt_code mp3splt_split(splt_state *state)
1080 {
1081 int error = SPLT_OK;
1082
1083 if (state != NULL)
1084 {
1085 if (!splt_o_library_locked(state))
1086 {
1087 splt_o_lock_library(state);
1088
1089 splt_d_print_debug(state,"Starting to split file ...\n");
1090
1091 if (splt_o_get_int_option(state, SPLT_OPT_HANDLE_BIT_RESERVOIR))
1092 {
1093 splt_c_put_warning_message_to_client(state,
1094 _(" warning: bit reservoir handling for gapless playback is still experimental\n"));
1095
1096 if (splt_o_get_long_option(state, SPLT_OPT_OVERLAP_TIME) > 0)
1097 {
1098 splt_c_put_warning_message_to_client(state,
1099 _(" warning: bit reservoir is not compatible with overlap option\n"));
1100 }
1101
1102 if (splt_o_get_int_option(state, SPLT_OPT_AUTO_ADJUST))
1103 {
1104 splt_c_put_warning_message_to_client(state,
1105 _(" warning: bit reservoir is not compatible with auto adjust option\n"));
1106 }
1107
1108 if (splt_o_get_int_option(state, SPLT_OPT_INPUT_NOT_SEEKABLE))
1109 {
1110 splt_c_put_warning_message_to_client(state,
1111 _(" warning: bit reservoir is not compatible with input not seekable\n"));
1112 }
1113
1114 int supported_split_mode = SPLT_TRUE;
1115 int split_mode = splt_o_get_int_option(state, SPLT_OPT_SPLIT_MODE);
1116 if ((split_mode == SPLT_OPTION_SILENCE_MODE) || (split_mode == SPLT_OPTION_TRIM_SILENCE_MODE))
1117 {
1118 supported_split_mode = SPLT_FALSE;
1119 }
1120
1121 if (!supported_split_mode)
1122 {
1123 splt_c_put_warning_message_to_client(state,
1124 _(" warning: bit reservoir is not compatible with silence detection or trimming\n"));
1125 }
1126
1127 int with_xing = splt_o_get_int_option(state, SPLT_OPT_XING);
1128 if (!with_xing)
1129 {
1130 splt_c_put_warning_message_to_client(state,
1131 _(" warning: bit reservoir is not compatible with 'no xing'\n"));
1132 }
1133
1134 int with_frame_mode = splt_o_get_int_option(state, SPLT_OPT_FRAME_MODE);
1135 if (!with_frame_mode)
1136 {
1137 splt_c_put_warning_message_to_client(state,
1138 _(" warning: please enable frame mode to make bit reservoir work\n"));
1139 }
1140 }
1141
1142 char *new_filename_path = NULL;
1143 char *fname_to_split = splt_t_get_filename_to_split(state);
1144
1145 splt_d_print_debug(state,"Original filename/path to split is _%s_\n", fname_to_split);
1146
1147 if (splt_io_input_is_stdin(state))
1148 {
1149 splt_o_set_int_option(state, SPLT_OPT_INPUT_NOT_SEEKABLE, SPLT_TRUE);
1150 }
1151
1152 splt_t_set_stop_split(state, SPLT_FALSE);
1153
1154 splt_o_set_default_iopts(state);
1155
1156 //we put the real splitnumber in the splitnumber variable
1157 //that could be changed (see splitnumber in mp3splt.h)
1158 if (!state->split.points)
1159 {
1160 state->split.splitnumber = 0;
1161 }
1162 else
1163 {
1164 state->split.splitnumber = state->split.points->real_splitnumber;
1165 }
1166
1167 splt_t_set_current_split(state,0);
1168
1169 if (!splt_io_check_if_file(state, fname_to_split))
1170 {
1171 error = SPLT_ERROR_INEXISTENT_FILE;
1172 splt_o_unlock_library(state);
1173 return error;
1174 }
1175
1176 //if the new_filename_path is "", we put the directory of
1177 //the current song
1178 new_filename_path = splt_check_put_dir_of_cur_song(fname_to_split,
1179 splt_t_get_path_of_split(state), &error);
1180 if (error < 0)
1181 {
1182 splt_o_unlock_library(state);
1183 return error;
1184 }
1185
1186 #ifndef __WIN32__
1187 char *linked_fname = splt_io_get_linked_fname(fname_to_split, NULL);
1188 if (linked_fname)
1189 {
1190 splt_c_put_info_message_to_client(state,
1191 _(" info: resolving linked filename to '%s'\n"), linked_fname);
1192
1193 splt_t_set_filename_to_split(state, linked_fname);
1194 fname_to_split = splt_t_get_filename_to_split(state);
1195
1196 free(linked_fname);
1197 linked_fname = NULL;
1198 }
1199 #endif
1200
1201 //checks and sets correct options
1202 splt_check_set_correct_options(state);
1203
1204 //if we have compatible options
1205 //this function is optional,
1206 if (! splt_check_compatible_options(state))
1207 {
1208 error = SPLT_ERROR_INCOMPATIBLE_OPTIONS;
1209 goto function_end;
1210 }
1211
1212 int split_type = splt_o_get_int_option(state, SPLT_OPT_SPLIT_MODE);
1213
1214 splt_t_set_new_filename_path(state, new_filename_path, &error);
1215 if (error < 0) { goto function_end; }
1216
1217 splt_d_print_debug(state, "new fname path = _%s_\n", new_filename_path);
1218
1219 error = splt_io_create_directories(state, new_filename_path);
1220 if (error < 0) { goto function_end; }
1221
1222 splt_check_if_fname_path_is_correct(state, new_filename_path, &error);
1223 if (error < 0) { goto function_end; }
1224
1225 //we check if mp3 or ogg
1226 splt_check_file_type_and_set_plugin(state, SPLT_FALSE, SPLT_TRUE, &error);
1227 if (error < 0) { goto function_end; }
1228
1229 int tags_option = splt_o_get_int_option(state, SPLT_OPT_TAGS);
1230 if (tags_option == SPLT_TAGS_ORIGINAL_FILE)
1231 {
1232 splt_tp_put_tags_from_string(state, SPLT_ORIGINAL_TAGS_DEFAULT, &error);
1233 if (error < 0) { goto function_end; }
1234 }
1235 else if (tags_option == SPLT_TAGS_FROM_FILENAME_REGEX)
1236 {
1237 int regex_error = SPLT_OK;
1238 splt_tp_put_tags_from_filename(state, ®ex_error);
1239 if (regex_error < 0) { error = regex_error; goto function_end; }
1240 }
1241
1242 const char *plugin_name = splt_p_get_name(state,&error);
1243 if (error < 0) { goto function_end; }
1244
1245 splt_c_put_info_message_to_client(state,
1246 _(" info: file matches the plugin '%s'\n"), plugin_name);
1247
1248 //print the new m3u fname
1249 char *m3u_fname_with_path = splt_t_get_m3u_file_with_path(state, &error);
1250 if (error < 0) { goto function_end; }
1251 if (m3u_fname_with_path)
1252 {
1253 splt_c_put_info_message_to_client(state,
1254 _(" M3U file '%s' will be created.\n"), m3u_fname_with_path);
1255
1256 free(m3u_fname_with_path);
1257 m3u_fname_with_path = NULL;
1258 }
1259
1260 //init the plugin for split
1261 splt_p_init(state, &error);
1262 if (error < 0) { goto function_end; }
1263
1264 splt_d_print_debug(state,"Parse type of split ...\n");
1265
1266 if (splt_o_get_int_option(state, SPLT_OPT_AUTO_ADJUST)
1267 && !splt_o_get_int_option(state, SPLT_OPT_QUIET_MODE))
1268 {
1269 if ((split_type != SPLT_OPTION_WRAP_MODE)
1270 && (split_type != SPLT_OPTION_SILENCE_MODE)
1271 && (split_type != SPLT_OPTION_TRIM_SILENCE_MODE)
1272 && (split_type != SPLT_OPTION_ERROR_MODE))
1273 {
1274 splt_c_put_info_message_to_client(state,
1275 _(" Working with SILENCE AUTO-ADJUST (Threshold:"
1276 " %.1f dB Gap: %d sec Offset: %.2f Min: %.2f sec)\n"),
1277 splt_o_get_float_option(state, SPLT_OPT_PARAM_THRESHOLD),
1278 splt_o_get_int_option(state, SPLT_OPT_PARAM_GAP),
1279 splt_o_get_float_option(state, SPLT_OPT_PARAM_OFFSET),
1280 splt_o_get_float_option(state, SPLT_OPT_PARAM_MIN_LENGTH));
1281 }
1282 }
1283
1284 switch (split_type)
1285 {
1286 case SPLT_OPTION_WRAP_MODE:
1287 splt_s_wrap_split(state, &error);
1288 break;
1289 case SPLT_OPTION_SILENCE_MODE:
1290 splt_s_silence_split(state, &error);
1291 break;
1292 case SPLT_OPTION_TRIM_SILENCE_MODE:
1293 splt_s_trim_silence_split(state, &error);
1294 break;
1295 case SPLT_OPTION_TIME_MODE:
1296 splt_s_time_split(state, &error);
1297 break;
1298 case SPLT_OPTION_LENGTH_MODE:
1299 splt_s_equal_length_split(state, &error);
1300 break;
1301 case SPLT_OPTION_ERROR_MODE:
1302 splt_s_error_split(state, &error);
1303 break;
1304 default:
1305 if (split_type == SPLT_OPTION_NORMAL_MODE)
1306 {
1307 if (! splt_o_get_int_option(state, SPLT_OPT_PRETEND_TO_SPLIT))
1308 {
1309 //check if we have at least 2 splitpoints
1310 if (splt_t_get_splitnumber(state) < 2)
1311 {
1312 error = SPLT_ERROR_SPLITPOINTS;
1313 goto function_end;
1314 }
1315 }
1316
1317 splt_check_points_inf_song_length_and_convert_negatives(state, &error);
1318 if (error < 0) { goto function_end; }
1319
1320 splt_check_if_points_in_order(state, &error);
1321 if (error < 0) { goto function_end; }
1322 }
1323
1324 splt_s_normal_split(state, &error);
1325 break;
1326 }
1327
1328 //ends the 'init' of the plugin for the split
1329 splt_p_end(state, &error);
1330
1331 function_end:
1332 if (new_filename_path)
1333 {
1334 free(new_filename_path);
1335 new_filename_path = NULL;
1336 }
1337
1338 splt_o_unlock_library(state);
1339 }
1340 else
1341 {
1342 error = SPLT_ERROR_LIBRARY_LOCKED;
1343 }
1344 }
1345 else
1346 {
1347 error = SPLT_ERROR_STATE_NULL;
1348 }
1349
1350 return error;
1351 }
1352
1353 /*! cancels the current split
1354 \return The error code if any error occours
1355 */
mp3splt_stop_split(splt_state * state)1356 splt_code mp3splt_stop_split(splt_state *state)
1357 {
1358 if (state == NULL)
1359 {
1360 return SPLT_ERROR_STATE_NULL;
1361 }
1362
1363 splt_t_set_stop_split(state, SPLT_TRUE);
1364
1365 return SPLT_OK;
1366 }
1367
1368 /************************************/
1369 /* Cddb and Cue functions */
1370
1371 /*! Fetch the splitpoints from an input file.
1372 */
mp3splt_import(splt_state * state,splt_import_type type,const char * file)1373 splt_code mp3splt_import(splt_state *state, splt_import_type type, const char *file)
1374 {
1375 if (state == NULL)
1376 {
1377 return SPLT_ERROR_STATE_NULL;
1378 }
1379
1380 if (splt_o_library_locked(state))
1381 {
1382 return SPLT_ERROR_LIBRARY_LOCKED;
1383 }
1384
1385 splt_o_lock_library(state);
1386 int err = SPLT_OK;
1387
1388 if (type == CUE_IMPORT)
1389 {
1390 splt_cue_put_splitpoints(file, state, &err);
1391 }
1392 else if (type == CDDB_IMPORT)
1393 {
1394 splt_cddb_put_splitpoints(file, state, &err);
1395 }
1396 else if (type == AUDACITY_LABELS_IMPORT)
1397 {
1398 splt_audacity_put_splitpoints(file, state, &err);
1399 }
1400 else if (type == PLUGIN_INTERNAL_IMPORT)
1401 {
1402 char *old_filename_to_split = strdup(mp3splt_get_filename_to_split(state));
1403 if (old_filename_to_split == NULL)
1404 {
1405 err = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
1406 goto end;
1407 }
1408
1409 err = splt_t_set_filename_to_split(state, file);
1410 if (err < 0) { goto end2; }
1411
1412 splt_check_file_type_and_set_plugin(state, SPLT_TRUE, SPLT_FALSE, &err);
1413 if (err >= 0)
1414 {
1415 splt_t_free_splitpoints_tags(state);
1416 splt_p_import_internal_sheets(state, &err);
1417 }
1418
1419 splt_t_set_filename_to_split(state, old_filename_to_split);
1420
1421 end2:
1422 free(old_filename_to_split);
1423 }
1424
1425 end:
1426 splt_o_unlock_library(state);
1427
1428 return err;
1429 }
1430
1431 /************************************/
1432 /* Freedb functions */
1433
mp3splt_use_proxy(splt_state * state,const char * proxy_address,int proxy_port)1434 splt_code mp3splt_use_proxy(splt_state *state, const char *proxy_address, int proxy_port)
1435 {
1436 return splt_pr_use_proxy(state, proxy_address, proxy_port);
1437 }
1438
mp3splt_use_base64_authentification(splt_state * state,const char * base64_authentification)1439 splt_code mp3splt_use_base64_authentification(splt_state *state,
1440 const char *base64_authentification)
1441 {
1442 return splt_pr_use_base64_authentification(state, base64_authentification);
1443 }
1444
mp3splt_encode_in_base64(splt_state * state,const char * input,int * error)1445 char *mp3splt_encode_in_base64(splt_state *state, const char *input, int *error)
1446 {
1447 int erro = SPLT_OK;
1448 int *err = &erro;
1449 if (error != NULL) { err = error; }
1450
1451 char *input_as_base64 = splt_pr_base64((unsigned char *)input);
1452 if (input_as_base64 == NULL)
1453 {
1454 *err = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
1455 return NULL;
1456 }
1457
1458 return input_as_base64;
1459 }
1460
mp3splt_clear_proxy(splt_state * state)1461 void mp3splt_clear_proxy(splt_state *state)
1462 {
1463 splt_pr_free(state);
1464 }
1465
1466 /*!Do a freedb search
1467
1468 After dong the search continue by calling
1469 mp3splt_write_freedb_file_result().
1470 \param state The central structure this library keeps all its data in
1471 \param search_string The string that is to be searched for
1472 \param error The error code this action returns in
1473 \param search_type the type of the search. Usually set to
1474 SPLT_SEARCH_TYPE_FREEDB2
1475 \param search_server The URL of the search server or NULL to select
1476 the default
1477 \param port The port on the server. -1 means default (Which should be
1478 80).
1479 */
mp3splt_get_freedb_search(splt_state * state,const char * search_string,splt_code * error,int search_type,const char search_server[256],int port)1480 splt_freedb_results *mp3splt_get_freedb_search(splt_state *state,
1481 const char *search_string,
1482 splt_code *error,
1483 int search_type,
1484 const char search_server[256],
1485 int port)
1486 {
1487 int erro = SPLT_OK;
1488 int *err = &erro;
1489 if (error != NULL) { err = error; }
1490
1491 if (search_string == NULL)
1492 {
1493 *err = SPLT_FREEDB_NO_CD_FOUND;
1494 return NULL;
1495 }
1496
1497 if (state != NULL)
1498 {
1499 //we copy the search string, in order not to modify the original one
1500 char *search = strdup(search_string);
1501 if (search != NULL)
1502 {
1503 *err = splt_freedb_process_search(state, search, search_type,
1504 search_server, port);
1505
1506 free(search);
1507 search = NULL;
1508
1509 return state->fdb.search_results;
1510 }
1511 else
1512 {
1513 *err = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
1514 return NULL;
1515 }
1516 }
1517 else
1518 {
1519 *err = SPLT_ERROR_STATE_NULL;
1520 return NULL;
1521 }
1522 }
1523
mp3splt_freedb_init_iterator(splt_freedb_results * freedb_results)1524 void mp3splt_freedb_init_iterator(splt_freedb_results *freedb_results)
1525 {
1526 if (freedb_results == NULL)
1527 {
1528 return;
1529 }
1530
1531 freedb_results->iterator_counter = 0;
1532 }
1533
mp3splt_freedb_next(splt_freedb_results * freedb_results)1534 const splt_freedb_one_result *mp3splt_freedb_next(splt_freedb_results *freedb_results)
1535 {
1536 if (freedb_results == NULL)
1537 {
1538 return NULL;
1539 }
1540
1541 if (freedb_results->iterator_counter < 0 ||
1542 freedb_results->iterator_counter >= freedb_results->number)
1543 {
1544 freedb_results->iterator_counter++;
1545 return NULL;
1546 }
1547
1548 splt_freedb_one_result *result = &freedb_results->results[freedb_results->iterator_counter];
1549
1550 freedb_results->iterator_counter++;
1551
1552 return result;
1553 }
1554
mp3splt_freedb_get_id(const splt_freedb_one_result * result)1555 int mp3splt_freedb_get_id(const splt_freedb_one_result *result)
1556 {
1557 return result->id;
1558 }
1559
mp3splt_freedb_get_name(const splt_freedb_one_result * result)1560 const char *mp3splt_freedb_get_name(const splt_freedb_one_result *result)
1561 {
1562 return result->name;
1563 }
1564
mp3splt_freedb_get_number_of_revisions(const splt_freedb_one_result * result)1565 int mp3splt_freedb_get_number_of_revisions(const splt_freedb_one_result *result)
1566 {
1567 return result->revision_number;
1568 }
1569
1570 /*! returns the content of a cddb file
1571
1572 must only be called \emph{after} running get_freedb_search
1573 otherwise, it will fail (seg fault!?)
1574
1575 you need to write the cddb entry to the disk in
1576 a cddb file to use it be able to use it
1577
1578 \attention result is malloc'ed and must be freed by the caller after
1579 use.
1580 */
mp3splt_write_freedb_file_result(splt_state * state,int disc_id,const char * cddb_file,int cddb_get_type,const char cddb_get_server[256],int port)1581 splt_code mp3splt_write_freedb_file_result(splt_state *state, int disc_id,
1582 const char *cddb_file, int cddb_get_type,
1583 const char cddb_get_server[256], int port)
1584 {
1585 int erro = SPLT_OK;
1586 int *err = &erro;
1587
1588 if (state != NULL)
1589 {
1590 if (!splt_o_library_locked(state))
1591 {
1592 splt_o_lock_library(state);
1593
1594 char *freedb_file_content = NULL;
1595 freedb_file_content = splt_freedb_get_file(state, disc_id, err,
1596 cddb_get_type, cddb_get_server, port);
1597
1598 //if no error, write file
1599 if (*err == SPLT_FREEDB_FILE_OK)
1600 {
1601 if (! splt_o_get_int_option(state, SPLT_OPT_PRETEND_TO_SPLIT))
1602 {
1603 //we write the result to the file
1604 FILE *output = NULL;
1605 if (!(output = splt_io_fopen(cddb_file, "w")))
1606 {
1607 splt_e_set_strerror_msg_with_data(state, cddb_file);
1608 *err = SPLT_ERROR_CANT_WRITE_TO_OUTPUT_FILE;
1609 }
1610 else
1611 {
1612 fprintf(output,"%s",freedb_file_content);
1613 if (fclose(output) != 0)
1614 {
1615 splt_e_set_strerror_msg_with_data(state, cddb_file);
1616 *err = SPLT_ERROR_CANNOT_CLOSE_FILE;
1617 }
1618 output = NULL;
1619 }
1620 }
1621 }
1622
1623 //free some memory
1624 if (freedb_file_content)
1625 {
1626 free(freedb_file_content);
1627 freedb_file_content = NULL;
1628 }
1629
1630 splt_o_unlock_library(state);
1631 }
1632 else
1633 {
1634 *err = SPLT_ERROR_LIBRARY_LOCKED;
1635 }
1636 }
1637 else
1638 {
1639 *err = SPLT_ERROR_STATE_NULL;
1640 }
1641
1642 return *err;
1643 }
1644
1645 /*! Export our split points to a cue file
1646 */
mp3splt_export(splt_state * state,splt_export_type type,const char * out_file,int stop_at_total_time)1647 splt_code mp3splt_export(splt_state *state, splt_export_type type,
1648 const char *out_file, int stop_at_total_time)
1649 {
1650 if (state == NULL)
1651 {
1652 return SPLT_ERROR_STATE_NULL;
1653 }
1654
1655 if (splt_o_library_locked(state))
1656 {
1657 return SPLT_ERROR_LIBRARY_LOCKED;
1658 }
1659
1660 splt_o_lock_library(state);
1661 int err = SPLT_OK;
1662
1663 if (type == CUE_EXPORT)
1664 {
1665 splt_cue_export_to_file(state, out_file, stop_at_total_time, &err);
1666 }
1667
1668 splt_o_unlock_library(state);
1669
1670 return err;
1671 }
1672
1673 //! Sets the output format
mp3splt_set_oformat(splt_state * state,const char * format_string)1674 splt_code mp3splt_set_oformat(splt_state *state, const char *format_string)
1675 {
1676 if (state == NULL)
1677 {
1678 return SPLT_ERROR_STATE_NULL;
1679 }
1680
1681 if (splt_o_library_locked(state))
1682 {
1683 return SPLT_ERROR_LIBRARY_LOCKED;
1684 }
1685
1686 splt_o_lock_library(state);
1687
1688 int err = SPLT_OK;
1689 splt_of_set_oformat(state, format_string, &err, SPLT_FALSE);
1690
1691 splt_o_unlock_library(state);
1692
1693 return err;
1694 }
1695
1696 /************************************/
1697 /* Other utilities */
1698
1699 /*! Split a file that has been generated by mp3wrap
1700
1701 \param state The splt_state structure containing the split points
1702 \param error The error code
1703 */
mp3splt_get_wrap_files(splt_state * state,splt_code * error)1704 splt_wrap *mp3splt_get_wrap_files(splt_state *state, splt_code *error)
1705 {
1706 int erro = SPLT_OK;
1707 int *err = &erro;
1708 if (error != NULL) { err = error; }
1709
1710 if (state != NULL)
1711 {
1712 if (!splt_o_library_locked(state))
1713 {
1714 splt_o_lock_library(state);
1715
1716 //we check the format of the filename
1717 splt_check_file_type_and_set_plugin(state, SPLT_FALSE, SPLT_FALSE, err);
1718
1719 int old_split_mode = splt_o_get_int_option(state, SPLT_OPT_SPLIT_MODE);
1720 splt_o_set_int_option(state, SPLT_OPT_SPLIT_MODE, SPLT_OPTION_WRAP_MODE);
1721 if (*err >= 0)
1722 {
1723 splt_o_lock_messages(state);
1724 splt_p_init(state, err);
1725 if (*err >= 0)
1726 {
1727 splt_o_unlock_messages(state);
1728 splt_p_dewrap(state, SPLT_TRUE, NULL, err);
1729 splt_p_end(state, err);
1730 }
1731 else
1732 {
1733 splt_o_unlock_messages(state);
1734 }
1735 }
1736 splt_o_set_int_option(state, SPLT_OPT_SPLIT_MODE, old_split_mode);
1737
1738 splt_o_unlock_library(state);
1739 }
1740 else
1741 {
1742 *err = SPLT_ERROR_LIBRARY_LOCKED;
1743 }
1744
1745 return state->wrap;
1746 }
1747 else
1748 {
1749 *err = SPLT_ERROR_STATE_NULL;
1750 return NULL;
1751 }
1752 }
1753
mp3splt_wrap_init_iterator(splt_wrap * wrap)1754 void mp3splt_wrap_init_iterator(splt_wrap *wrap)
1755 {
1756 if (!wrap)
1757 {
1758 return;
1759 }
1760
1761 wrap->iterator_counter = 0;
1762 }
1763
mp3splt_wrap_next(splt_wrap * wrap)1764 const splt_one_wrap *mp3splt_wrap_next(splt_wrap *wrap)
1765 {
1766 if (!wrap)
1767 {
1768 return NULL;
1769 }
1770
1771 if (wrap->iterator_counter < 0 ||
1772 wrap->iterator_counter >= wrap->wrap_files_num)
1773 {
1774 wrap->iterator_counter++;
1775 return NULL;
1776 }
1777
1778 splt_one_wrap *one_wrap = (splt_one_wrap *) wrap->wrap_files[wrap->iterator_counter];
1779
1780 wrap->iterator_counter++;
1781
1782 return one_wrap;
1783 }
1784
mp3splt_wrap_get_wrapped_file(const splt_one_wrap * one_wrap)1785 char *mp3splt_wrap_get_wrapped_file(const splt_one_wrap *one_wrap)
1786 {
1787 if (!one_wrap)
1788 {
1789 return NULL;
1790 }
1791
1792 return strdup((const char *)one_wrap);
1793 }
1794
1795 //!set the silence splitpoints without actually splitting
mp3splt_set_silence_points(splt_state * state,splt_code * error)1796 int mp3splt_set_silence_points(splt_state *state, splt_code *error)
1797 {
1798 int erro = SPLT_OK;
1799 int *err = &erro;
1800 if (error != NULL) { err = error; }
1801
1802 int silence_mode = SPLT_OPTION_SILENCE_MODE;
1803 mp3splt_set_option(state, SPLT_OPT_SPLIT_MODE, &silence_mode);
1804
1805 int found_splitpoints = -1;
1806
1807 if (state != NULL)
1808 {
1809 if (!splt_o_library_locked(state))
1810 {
1811 splt_o_lock_library(state);
1812
1813 splt_t_set_stop_split(state, SPLT_FALSE);
1814
1815 splt_check_file_type_and_set_plugin(state, SPLT_FALSE, SPLT_FALSE, err);
1816
1817 if (*err >= 0)
1818 {
1819 splt_p_init(state, err);
1820 if (*err >= 0)
1821 {
1822 found_splitpoints = splt_s_set_silence_splitpoints(state, err);
1823 splt_p_end(state, err);
1824 }
1825 }
1826
1827 splt_o_unlock_library(state);
1828 }
1829 else
1830 {
1831 *err = SPLT_ERROR_LIBRARY_LOCKED;
1832 }
1833 }
1834 else
1835 {
1836 *err = SPLT_ERROR_STATE_NULL;
1837 }
1838
1839 return found_splitpoints;
1840 }
1841
1842 //!set the trim silence splitpoints without actually splitting
mp3splt_set_trim_silence_points(splt_state * state)1843 splt_code mp3splt_set_trim_silence_points(splt_state *state)
1844 {
1845 int erro = SPLT_OK;
1846 int *err = &erro;
1847
1848 int silence_mode = SPLT_OPTION_TRIM_SILENCE_MODE;
1849 mp3splt_set_option(state, SPLT_OPT_SPLIT_MODE, &silence_mode);
1850
1851 if (state != NULL)
1852 {
1853 if (!splt_o_library_locked(state))
1854 {
1855 splt_o_lock_library(state);
1856
1857 splt_t_set_stop_split(state, SPLT_FALSE);
1858
1859 splt_check_file_type_and_set_plugin(state, SPLT_FALSE, SPLT_FALSE, err);
1860
1861 if (*err >= 0)
1862 {
1863 splt_p_init(state, err);
1864 if (*err >= 0)
1865 {
1866 splt_s_set_trim_silence_splitpoints(state, err);
1867 splt_p_end(state, err);
1868 }
1869 }
1870
1871 splt_o_unlock_library(state);
1872 }
1873 else
1874 {
1875 *err = SPLT_ERROR_LIBRARY_LOCKED;
1876 }
1877 }
1878 else
1879 {
1880 *err = SPLT_ERROR_STATE_NULL;
1881 }
1882
1883 return *err;
1884 }
1885
1886 //!returns libmp3splt version; result must be freed
mp3splt_get_version()1887 char *mp3splt_get_version()
1888 {
1889 return strdup(SPLT_PACKAGE_VERSION);
1890 }
1891
1892 /*! Returns the error string that matches an error code
1893
1894 \param state The splt_state The central structure containing all data
1895 for our library
1896 \param error The error code
1897
1898 \attention The resulting string is malloc'ed and must be freed by the
1899 caller after use.
1900 */
1901
mp3splt_get_strerror(splt_state * state,splt_code error_code)1902 char *mp3splt_get_strerror(splt_state *state, splt_code error_code)
1903 {
1904 return splt_e_strerror(state, error_code);
1905 }
1906
1907 /*! Tell where to scan for plug-ins
1908
1909 \param state The splt_state The central structure containing all data
1910 for our library
1911 \return The error code in case that anything goes wrong, else SPLT_OK
1912 */
mp3splt_append_plugins_scan_dir(splt_state * state,const char * dir)1913 splt_code mp3splt_append_plugins_scan_dir(splt_state *state, const char *dir)
1914 {
1915 return splt_p_append_plugin_scan_dir(state, dir);
1916 }
1917
1918 #ifdef __WIN32__
1919 /*! Converts a string from win32 to utf8
1920
1921 \param The UTF16 string from Windows
1922 \result The same string in UTF8
1923 \attention The resulting string is malloc'ed and must be freed by the
1924 caller after use.
1925 */
mp3splt_win32_utf16_to_utf8(const wchar_t * source)1926 char *mp3splt_win32_utf16_to_utf8(const wchar_t *source)
1927 {
1928 return splt_w32_utf16_to_utf8(source);
1929 }
1930 #endif
1931
mp3splt_find_filenames(splt_state * state,const char * filename,int * num_of_files_found,splt_code * error)1932 char **mp3splt_find_filenames(splt_state *state, const char *filename,
1933 int *num_of_files_found, splt_code *error)
1934 {
1935 int erro = SPLT_OK;
1936 int *err = &erro;
1937 if (error != NULL) { err = error; }
1938
1939 char **found_files = NULL;
1940
1941 if (state != NULL)
1942 {
1943 if (!splt_o_library_locked(state))
1944 {
1945 splt_o_lock_library(state);
1946
1947 *num_of_files_found = 0;
1948
1949 if (splt_io_check_if_file(state, filename))
1950 {
1951 if (splt_p_file_is_supported_by_plugins(state, filename))
1952 {
1953 found_files = malloc(sizeof(char *));
1954 if (!found_files)
1955 {
1956 *err = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
1957 return NULL;
1958 }
1959
1960 int fname_size = strlen(filename) + 1;
1961 found_files[0] = malloc(sizeof(char) * fname_size);
1962 memset(found_files[0], '\0', fname_size);
1963
1964 if (!found_files[0])
1965 {
1966 free(found_files);
1967 return NULL;
1968 }
1969
1970 strncat(found_files[0], filename, fname_size);
1971 *num_of_files_found = 1;
1972 }
1973 }
1974 else
1975 {
1976 char *dir = strdup(filename);
1977 if (dir == NULL)
1978 {
1979 *err = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
1980 return NULL;
1981 }
1982
1983 if (dir[strlen(dir)-1] == SPLT_DIRCHAR)
1984 {
1985 dir[strlen(dir)-1] = '\0';
1986 }
1987
1988 splt_io_find_filenames(state, dir, &found_files, num_of_files_found, err);
1989
1990 if (dir)
1991 {
1992 free(dir);
1993 dir = NULL;
1994 }
1995 }
1996
1997 splt_o_unlock_library(state);
1998 }
1999 else
2000 {
2001 *err = SPLT_ERROR_LIBRARY_LOCKED;
2002 }
2003 }
2004 else
2005 {
2006 *err = SPLT_ERROR_STATE_NULL;
2007 return NULL;
2008 }
2009
2010 return found_files;
2011 }
2012
2013 //@}
2014
2015 //! Checks if a name points to a directory
mp3splt_check_if_directory(const char * fname)2016 int mp3splt_check_if_directory(const char *fname)
2017 {
2018 return splt_io_check_if_directory(fname);
2019 }
2020
mp3splt_free_one_tag(splt_tags * tags)2021 void mp3splt_free_one_tag(splt_tags *tags)
2022 {
2023 splt_tu_free_one_tags(&tags);
2024 }
2025
mp3splt_parse_filename_regex(splt_state * state,splt_code * error)2026 splt_tags *mp3splt_parse_filename_regex(splt_state *state, splt_code *error)
2027 {
2028 splt_tags *tags = NULL;
2029 int erro = SPLT_OK;
2030 int *err = &erro;
2031 if (error != NULL) { err = error; }
2032
2033 if (state != NULL)
2034 {
2035 if (!splt_o_library_locked(state))
2036 {
2037 splt_o_lock_library(state);
2038
2039 #ifndef NO_PCRE
2040 tags = splt_fr_parse_from_state(state, error);
2041 #else
2042 splt_c_put_warning_message_to_client(state,
2043 _(" warning: cannot set tags from filename regular expression - compiled without pcre support\n"));
2044 *error = SPLT_REGEX_UNAVAILABLE;
2045 #endif
2046
2047 splt_o_unlock_library(state);
2048 }
2049 else
2050 {
2051 *err = SPLT_ERROR_LIBRARY_LOCKED;
2052 }
2053 }
2054 else
2055 {
2056 *err = SPLT_ERROR_STATE_NULL;
2057 }
2058
2059 return tags;
2060 }
2061
2062