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, &regex_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