libmp3splt
plugins/mp3.c
Go to the documentation of this file.
00001 /**********************************************************
00002  * libmp3splt -- library based on mp3splt,
00003  *               for mp3/ogg splitting without decoding
00004  *
00005  * Copyright (c) 2002-2005 M. Trotta - <mtrotta@users.sourceforge.net>
00006  * Copyright (c) 2005-2011 Alexandru Munteanu - io_fx@yahoo.fr
00007  *
00008  *********************************************************/
00009 
00010 /**********************************************************
00011  * This program is free software; you can redistribute it and/or
00012  * modify it under the terms of the GNU General Public License
00013  * as published by the Free Software Foundation; either version 2
00014  * of the License, or (at your option) any later version.
00015  *
00016  * This program is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  * GNU General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU General Public License
00022  * along with this program; if not, write to the Free Software
00023  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
00024  * 02111-1307,
00025  * USA.
00026  *********************************************************/
00032 #include <string.h>
00033 #include <unistd.h>
00034 #include <sys/stat.h>
00035 #include <dirent.h>
00036 #include <math.h>
00037 #include <ctype.h>
00038 
00039 #ifdef __WIN32__
00040 #include <io.h>
00041 #include <fcntl.h>
00042 #endif
00043 
00044 #include "splt.h"
00045 #include "mp3.h"
00046 
00047 /****************************/
00048 /* mp3 constants */
00049 
00054 static const char *splt_mp3_chan[] =
00055 {
00056         "Mono",
00057         "Dual Mono",
00058         "Joint Stereo",
00059         "Stereo",
00060         "?"
00061 };
00062 
00064 static const int splt_mp3_tabsel_123[2][3][16] = {
00065   { {128,32,64,96,128,160,192,224,256,288,320,352,384,416,448,},
00066     {128,32,48,56, 64, 80, 96,112,128,160,192,224,256,320,384,},
00067     {128,32,40,48, 56, 64, 80, 96,112,128,160,192,224,256,320,} },
00068 
00069   { {128,32,48,56,64,80,96,112,128,144,160,176,192,224,256,},
00070     {128,8,16,24,32,40,48,56,64,80,96,112,128,144,160,},
00071     {128,8,16,24,32,40,48,56,64,80,96,112,128,144,160,} }
00072 };
00073 
00077 static const unsigned long splt_mp3_crctab[256] = {
00078   0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
00079   0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
00080   0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
00081   0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
00082   0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
00083   0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
00084   0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
00085   0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
00086   0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
00087   0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
00088   0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
00089   0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
00090   0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
00091   0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
00092   0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
00093   0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
00094   0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
00095   0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
00096   0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
00097   0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
00098   0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
00099   0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
00100   0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
00101   0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
00102   0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
00103   0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
00104   0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
00105   0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
00106   0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
00107   0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
00108   0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
00109   0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
00110   0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
00111   0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
00112   0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
00113   0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
00114   0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
00115   0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
00116   0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
00117   0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
00118   0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
00119   0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
00120   0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
00121   0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
00122   0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
00123   0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
00124   0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
00125   0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
00126   0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
00127   0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
00128   0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
00129   0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
00130   0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
00131   0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
00132   0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
00133   0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
00134   0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
00135   0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
00136   0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
00137   0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
00138   0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
00139   0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
00140   0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
00141   0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
00142 };
00143 
00144 static void splt_mp3_save_end_point(splt_state *state, splt_mp3_state *mp3state,
00145     int save_end_point, off_t end)
00146 {
00147   if (save_end_point)
00148   {
00149     mp3state->end = end;
00150   }
00151   else
00152   {
00153     mp3state->end = 0;
00154   }
00155 }
00156 
00164 static FILE *splt_mp3_open_file_read(splt_state *state, const char *filename,
00165     int *error)
00166 {
00167   FILE *file_input = NULL;
00168 
00169   if (filename != NULL && ((strcmp(filename,"-") == 0) ||
00170         (strcmp(filename,"m-") == 0)))
00171   {
00172     file_input = stdin;
00173 #ifdef __WIN32__
00174     _setmode(fileno(file_input), _O_BINARY);
00175 #endif
00176   }
00177   else
00178   {
00179     file_input = splt_io_fopen(filename, "rb");
00180     if (file_input == NULL)
00181     {
00182       splt_e_set_strerror_msg_with_data(state, filename);
00183       *error = SPLT_ERROR_CANNOT_OPEN_FILE;
00184     }
00185   }
00186 
00187   return file_input;
00188 }
00189 
00193 static FILE *splt_mp3_open_file_write(splt_state *state, const char *output_fname, int *error)
00194 {
00195   FILE *file_output = NULL;
00196 
00197   //for the stdout
00198   if (strcmp(output_fname, "-")==0)
00199   {
00200     file_output = stdout;
00201 #ifdef __WIN32__
00202     _setmode(fileno(file_output), _O_BINARY);
00203 #endif
00204   }
00205   else
00206   {
00207     if (!(file_output = splt_io_fopen(output_fname, "wb+")))
00208     {
00209       splt_e_set_strerror_msg_with_data(state, output_fname);
00210       *error = SPLT_ERROR_CANNOT_OPEN_DEST_FILE;
00211     }
00212   }
00213 
00214   return file_output;
00215 }
00216 
00217 
00218 /****************************/
00219 /* CRC functions */
00220 
00222 static unsigned long splt_mp3_c_crc(splt_state *state,
00223     FILE *in, off_t begin, off_t end, int *error)
00224 {
00225   register unsigned long crc;
00226   int c;
00227 
00228   crc = 0xFFFFFFFF;
00229 
00230   if (fseeko(in, begin, SEEK_SET) == -1)
00231   {
00232     splt_e_set_strerror_msg_with_data(state, splt_t_get_filename_to_split(state));
00233     *error = SPLT_ERROR_SEEKING_FILE;
00234     return 0;
00235   }
00236 
00237   while(begin++ < end)
00238   {
00239     c = fgetc(in);
00240     crc = ((crc >> 8) & 0x00FFFFFF) ^ splt_mp3_crctab[(crc ^ c) & 0xFF];
00241   }
00242 
00243   return (crc ^ 0xFFFFFFFF);
00244 }
00245 
00246 /****************************/
00247 /* mp3 utils */
00248 
00250 static void splt_mp3_init_stream_frame(splt_mp3_state *mp3state)
00251 {
00252   mad_stream_init(&mp3state->stream);
00253   mad_frame_init(&mp3state->frame);
00254 }
00255 
00257 static void splt_mp3_finish_stream_frame(splt_mp3_state *mp3state)
00258 {
00259   mad_stream_finish(&mp3state->stream);
00260   mad_frame_finish(&mp3state->frame);
00261 }
00262 
00267 static void splt_mp3_checksync (splt_mp3_state *mp3state)
00268 {
00269   //char junk[32];
00270   //fprintf(stderr, "\nWarning: Too many sync errors! This may not be a mp3 file. Continue? (y/n) ");
00271   //fgets(junk, 31, stdin);
00272   //if (junk[0]=='y')
00273 
00274   //we don't use user interactivity in a library
00275   //always continue
00276   mp3state->syncdetect = 0;
00277 
00278   //else error("Aborted.",125);
00279 }
00280 
00282 static int splt_mp3_c_bitrate (unsigned long head)
00283 {
00284   if ((head & 0xffe00000) != 0xffe00000) return 0;
00285   if (!((head>>17)&3)) return 0;
00286   if (((head>>12)&0xf) == 0xf) return 0;
00287   if (!((head >> 12) & 0xf)) return 0;
00288   if (((head>>10)&0x3) == 0x3 ) return 0;
00289   if (((head >> 19) & 1)==1 && ((head>>17)&3)==3 && 
00290       ((head>>16)&1)==1) return 0;
00291   if ((head & 0xffff0000) == 0xfffe0000) return 0;
00292 
00293   return ((head>>12)&0xf);
00294 }
00295 
00297 static struct splt_header splt_mp3_makehead (unsigned long headword, 
00298     struct splt_mp3 mp3f, struct splt_header head, off_t ptr)
00299 {
00300   head.ptr = ptr;
00301   head.bitrate = splt_mp3_tabsel_123[1 - mp3f.mpgid][mp3f.layer-1][splt_mp3_c_bitrate(headword)];
00302   head.padding = ((headword>>9)&0x1);
00303   head.framesize = (head.bitrate*144000)/
00304     (mp3f.freq<<(1 - mp3f.mpgid)) + head.padding;
00305 
00306   return head;
00307 }
00308 
00310 static off_t splt_mp3_findhead (splt_mp3_state *mp3state, off_t start)
00311 {
00312   if (splt_io_get_word(mp3state->file_input, 
00313         start, SEEK_SET, &mp3state->headw) == -1)
00314   {
00315     return -1;
00316   }
00317   if (feof(mp3state->file_input)) 
00318   {
00319     return -1;
00320   }
00321   while (!(splt_mp3_c_bitrate(mp3state->headw)))
00322   {
00323     if (feof(mp3state->file_input)) 
00324     {
00325       return -1;
00326     }
00327     mp3state->headw <<= 8;
00328     mp3state->headw |= fgetc(mp3state->file_input);
00329     start++;
00330   }
00331 
00332   return start;
00333 }
00334 
00336 static off_t splt_mp3_findvalidhead (splt_mp3_state *mp3state, off_t start)
00337 {
00338   off_t begin;
00339   struct splt_header h;
00340 
00341   begin = splt_mp3_findhead(mp3state, start);
00342 
00343   do {
00344     start = begin;
00345     if (start == -1) 
00346     {
00347       break;
00348     }
00349     h = splt_mp3_makehead (mp3state->headw, mp3state->mp3file, h, start);
00350     begin = splt_mp3_findhead(mp3state, (start + 1));
00351   } while (begin!=(start + h.framesize));
00352 
00353   return start;
00354 }
00355 
00357 static int splt_mp3_xing_info_off(splt_mp3_state *mp3state)
00358 {
00359   unsigned long headw = 0;
00360   int i;
00361 
00362   for (i=0; i<mp3state->mp3file.xing; i++)
00363   {
00364     if ((headw == SPLT_MP3_XING_MAGIC) || 
00365         (headw == SPLT_MP3_INFO_MAGIC)) // "Xing" or "Info"
00366     {
00367       return i;
00368     }
00369     headw <<= 8;
00370     headw |= mp3state->mp3file.xingbuffer[i];
00371   }
00372 
00373   return 0;
00374 }
00375 
00380 static int splt_mp3_get_frame(splt_mp3_state *mp3state)
00381 {
00382   if(mp3state->stream.buffer==NULL || 
00383       mp3state->stream.error==MAD_ERROR_BUFLEN)
00384   {
00385     size_t readSize, remaining;
00386     unsigned char *readStart;
00387 
00388     if (feof(mp3state->file_input))
00389     {
00390       return -2;
00391     }
00392 
00393     if(mp3state->stream.next_frame!=NULL)
00394     {
00395       remaining = mp3state->stream.bufend - mp3state->stream.next_frame;
00396       memmove(mp3state->inputBuffer, mp3state->stream.next_frame, remaining);
00397       readStart = mp3state->inputBuffer + remaining;
00398       readSize = SPLT_MAD_BSIZE - remaining;
00399     }
00400     else
00401     {
00402       readSize = SPLT_MAD_BSIZE;
00403       readStart=mp3state->inputBuffer;
00404       remaining=0;
00405     }
00406 
00407     readSize=fread(readStart, 1, readSize, mp3state->file_input);
00408     if (readSize <= 0)
00409     {
00410       return -2;
00411     }
00412 
00413     mp3state->buf_len = readSize + remaining;
00414     mp3state->bytes += readSize;
00415     //does not set any error
00416     mad_stream_buffer(&mp3state->stream, mp3state->inputBuffer, 
00417         readSize+remaining);
00418     mp3state->stream.error = MAD_ERROR_NONE;
00419   }
00420 
00421   //mad_frame_decode() returns -1 if error, 0 if no error
00422   return mad_frame_decode(&mp3state->frame,&mp3state->stream);
00423 }
00424 
00442 static int splt_mp3_get_valid_frame(splt_state *state, int *error)
00443 {
00444   splt_mp3_state *mp3state = state->codec;
00445   int ok = 0;
00446   do
00447   {
00448     int ret = splt_mp3_get_frame(mp3state);
00449     if(ret != 0)
00450     {
00451       if (ret == -2)
00452       {
00453         return -1;
00454       }
00455       if (mp3state->stream.error == MAD_ERROR_LOSTSYNC)
00456       {
00457         //syncerrors
00458         state->syncerrors++;
00459         if ((mp3state->syncdetect) && (state->syncerrors>SPLT_MAXSYNC))
00460         {
00461           splt_mp3_checksync(mp3state);
00462         }
00463       }
00464       if(MAD_RECOVERABLE(mp3state->stream.error))
00465       {
00466         continue;
00467       }
00468       else
00469       {
00470         if(mp3state->stream.error==MAD_ERROR_BUFLEN)
00471         {
00472           continue;
00473         }
00474         else
00475         {
00476           splt_e_set_error_data(state, mad_stream_errorstr(&mp3state->stream));
00477           *error = SPLT_ERROR_PLUGIN_ERROR;
00478           return -3;
00479         }
00480       }
00481     }
00482     else
00483     {
00484       //the important stuff
00485       mp3state->data_ptr = (unsigned char *) mp3state->stream.this_frame;
00486       if (mp3state->stream.next_frame!=NULL)
00487       {
00488         mp3state->data_len = (long) (mp3state->stream.next_frame - mp3state->stream.this_frame);
00489       }
00490       ok = 1;
00491     }
00492 
00493   } while (!ok);
00494 
00495   return ok;
00496 }
00497 
00506 static int splt_mp3_getid3v1_offset(FILE *file_input)
00507 {
00508   if (fseeko(file_input, (off_t) -128, SEEK_END)==-1)
00509   {
00510     return 0;
00511   }
00512 
00513   if (fgetc(file_input)=='T')
00514     if (fgetc(file_input)=='A')
00515       if (fgetc(file_input)=='G')
00516         return -128;
00517 
00518   return 0;
00519 }
00520 
00529 static off_t splt_mp3_getid3v2_end_offset(FILE *in, off_t start)
00530 {
00531   unsigned long oword = 0;
00532   if (fseeko(in, start, SEEK_SET)==-1)
00533   {
00534     return 0;
00535   }
00536 
00537   if (fgetc(in)=='I')
00538     if (fgetc(in)=='D')
00539       if (fgetc(in)=='3')
00540       {
00541         int i;
00542         if (fseeko(in, (off_t) 3, SEEK_CUR)==-1)
00543         {
00544           return 0;
00545         }
00546 
00547         for (i=0; i<4; i++)
00548         {
00549           oword = (oword << 7) | fgetc(in);
00550         }
00551 
00552         return (off_t) (oword);
00553       }
00554 
00555   return 0;
00556 }
00557 
00562 static void splt_mp3_state_free(splt_state *state)
00563 {
00564   splt_mp3_state *mp3state = state->codec;
00565 
00566   if (mp3state)
00567   {
00568     if (mp3state->mp3file.xingbuffer)
00569     {
00570       free(mp3state->mp3file.xingbuffer);
00571       mp3state->mp3file.xingbuffer = NULL;
00572     }
00573 
00574     //we free the state
00575     free(mp3state);
00576     state->codec = NULL;
00577   }
00578 }
00579 
00580 /****************************/
00581 /* mp3 tags */
00582 
00583 #ifndef NO_ID3TAG
00584 
00586 static id3_byte_t *splt_mp3_get_id3v2_tag_bytes(FILE *file, id3_length_t *length)
00587 {
00588   id3_byte_t *bytes = NULL;
00589   *length = 0;
00590 
00591   off_t id3v2_end_offset = splt_mp3_getid3v2_end_offset(file, 0);
00592 
00593   if (id3v2_end_offset != 0)
00594   {
00595     size_t id3v2_size = (size_t) (id3v2_end_offset + 10);
00596 
00597     rewind(file);
00598     bytes = splt_io_fread(file, 1, id3v2_size);
00599 
00600     if (! bytes)
00601     {
00602       return NULL;
00603     }
00604 
00605     *length = (unsigned long) id3v2_size;
00606   }
00607 
00608   return bytes;
00609 }
00610 
00611 static id3_byte_t *splt_mp3_get_id3v1_tag_bytes(FILE *file, id3_length_t *length)
00612 {
00613   id3_byte_t *bytes = NULL;
00614   *length = 0;
00615 
00616   off_t id3v1_offset = splt_mp3_getid3v1_offset(file);
00617 
00618   if (id3v1_offset != 0)
00619   {
00620     if (fseeko(file, id3v1_offset, SEEK_END) !=-1)
00621     {
00622       bytes = malloc(sizeof(unsigned char) * 128);
00623 
00624       if (! bytes)
00625       {
00626         return NULL;
00627       }
00628 
00629       if (fread(bytes, 1 , 128, file) != 128)
00630       {
00631         if (bytes)
00632         {
00633           free(bytes);
00634           bytes = NULL;
00635           return NULL;
00636         }
00637       }
00638       else
00639       {
00640         *length = (unsigned long) 128; 
00641       }
00642     }
00643   }
00644 
00645   return bytes;
00646 }
00647 
00657 static id3_byte_t *splt_mp3_get_id3_tag_bytes(splt_state *state, const char *filename,
00658     id3_length_t *length, int *error, int *tags_version)
00659 {
00660   *length = 0;
00661   id3_byte_t *bytes = NULL;
00662 
00663   FILE *file = splt_io_fopen(filename, "rb");
00664 
00665   if (! file)
00666   {
00667     splt_e_set_strerror_msg_with_data(state, filename);
00668     *error = SPLT_ERROR_CANNOT_OPEN_FILE;
00669     goto end;
00670   }
00671   else
00672   {
00673     id3_length_t id3v1_length = 0;
00674     id3_byte_t *id3v1_bytes = splt_mp3_get_id3v1_tag_bytes(file, &id3v1_length);
00675 
00676     id3_length_t id3v2_length = 0;
00677     id3_byte_t *id3v2_bytes = splt_mp3_get_id3v2_tag_bytes(file, &id3v2_length);
00678 
00679     if (id3v2_bytes)
00680     {
00681       *tags_version = 2;
00682       bytes = id3v2_bytes;
00683       *length = id3v2_length;
00684 
00685       if (id3v1_bytes)
00686       {
00687         *tags_version = 12;
00688         free(id3v1_bytes);
00689         id3v1_bytes = NULL;
00690       }
00691     }
00692     else if (id3v1_bytes)
00693     {
00694       *tags_version = 1;
00695       bytes = id3v1_bytes;
00696       *length = id3v1_length;
00697     }
00698   }
00699 
00700 end:
00701   if (file)
00702   {
00703     if (fclose(file) != 0)
00704     {
00705       if (bytes)
00706       {
00707         free(bytes);
00708         bytes = NULL;
00709       }
00710       return NULL;
00711     }
00712   }
00713 
00714   return bytes;
00715 }
00716 
00718 static int splt_mp3_put_original_libid3_frame(splt_state *state,
00719     const struct id3_tag *id3tag, const char *frame_type, int id_type)
00720 {
00721   struct id3_frame *frame = NULL;
00722   union id3_field *field = NULL;
00723   id3_ucs4_t *ucs4 = NULL;
00724   id3_utf8_t *tag_value = NULL;
00725 
00726   int err = SPLT_OK;
00727 
00728   frame = id3_tag_findframe(id3tag, frame_type,0);
00729   if (frame != NULL)
00730   {
00731     if (id_type == SPLT_MP3_ID3_COMMENT)
00732     {
00733       field = id3_frame_field(frame, 3);
00734       ucs4 = (id3_ucs4_t *) id3_field_getfullstring(field);
00735     }
00736     else
00737     {
00738       field = id3_frame_field(frame, 1);
00739       ucs4 = (id3_ucs4_t *) id3_field_getstrings(field,0);
00740     }
00741     if (ucs4 != NULL)
00742     {
00743       tag_value = id3_ucs4_utf8duplicate(ucs4);
00744 
00745       if (tag_value != NULL)
00746       {
00747         switch (id_type)
00748         {
00749           case SPLT_MP3_ID3_ALBUM:
00750             err = splt_tu_set_original_tags_field(state,SPLT_TAGS_ALBUM, tag_value);
00751             break;
00752           case SPLT_MP3_ID3_ARTIST:
00753             err = splt_tu_set_original_tags_field(state,SPLT_TAGS_ARTIST, tag_value);
00754             break;
00755           case SPLT_MP3_ID3_TITLE:
00756             if (strcmp(frame_type,ID3_FRAME_TITLE) == 0)
00757             {
00758               err = splt_tu_set_original_tags_field(state,SPLT_TAGS_TITLE, tag_value);
00759             }
00760             break;
00761           case SPLT_MP3_ID3_YEAR:
00762             err = splt_tu_set_original_tags_field(state,SPLT_TAGS_YEAR, tag_value);
00763             break;
00764           case SPLT_MP3_ID3_TRACK:
00765             ;
00766             int track = atoi((char *)tag_value);
00767             err = splt_tu_set_original_tags_field(state,SPLT_TAGS_TRACK, &track);
00768             break;
00769           case SPLT_MP3_ID3_COMMENT:
00770             err = splt_tu_set_original_tags_field(state,SPLT_TAGS_COMMENT, tag_value);
00771             break;
00772           case SPLT_MP3_ID3_GENRE:
00773             ;
00774             char *genre = (char *)tag_value;
00775 
00776             int id3v1 = atoi(genre);
00777             if ((id3v1 != 0) &&
00778                 (id3v1 < SPLT_ID3V1_NUMBER_OF_GENRES) &&
00779                 (state->original_tags.genre == NULL))
00780             {
00781               err = splt_tu_set_original_tags_field(state, SPLT_TAGS_GENRE, splt_id3v1_genres[id3v1]);
00782             }
00783             else if (strcmp(genre, "0") == 0)
00784             {
00785               err = splt_tu_set_original_tags_field(state, SPLT_TAGS_GENRE, SPLT_UNDEFINED_GENRE);
00786             }
00787             else
00788             {
00789               err = splt_tu_set_original_tags_field(state, SPLT_TAGS_GENRE, genre);
00790             }
00791             break;
00792           default:
00793             break;
00794         }
00795         free(tag_value);
00796         tag_value = NULL;
00797       }
00798       else
00799       {
00800         err = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
00801       }
00802     }
00803   }
00804 
00805   return err;
00806 }
00807 
00809 #define MP3_VERIFY_ERROR() \
00810 if (err != SPLT_OK) \
00811 { \
00812 *tag_error = err; \
00813 goto end; \
00814 };
00815 
00821 static void splt_mp3_get_original_tags(const char *filename,
00822     splt_state *state, int *tag_error)
00823 {
00824   //we get the id3 from the original file using libid3tag
00825   struct id3_tag *id3tag = NULL;
00826 
00827   //get out the tags from the file; id3_file_open doesn't work with win32 utf16 filenames
00828   id3_length_t id3_tag_length = 0;
00829   int tags_version = 0;
00830   id3_byte_t *id3_tag_bytes =
00831     splt_mp3_get_id3_tag_bytes(state, filename, &id3_tag_length, tag_error,
00832         &tags_version);
00833 
00834   if (*tag_error >= 0)
00835   {
00836     if (id3_tag_bytes)
00837     {
00838       id3tag = id3_tag_parse(id3_tag_bytes, id3_tag_length);
00839 
00840       if (id3tag)
00841       {
00842         int err = SPLT_OK;
00843 
00844         err = splt_tu_set_original_tags_field(state,SPLT_TAGS_VERSION, &tags_version);
00845         MP3_VERIFY_ERROR();
00846         err = splt_mp3_put_original_libid3_frame(state,id3tag,ID3_FRAME_ARTIST,
00847             SPLT_MP3_ID3_ARTIST);
00848         MP3_VERIFY_ERROR();
00849         err = splt_mp3_put_original_libid3_frame(state,id3tag,ID3_FRAME_ALBUM,
00850             SPLT_MP3_ID3_ALBUM);
00851         MP3_VERIFY_ERROR();
00852         err = splt_mp3_put_original_libid3_frame(state,id3tag,ID3_FRAME_TITLE,
00853             SPLT_MP3_ID3_TITLE);
00854         MP3_VERIFY_ERROR();
00855         err = splt_mp3_put_original_libid3_frame(state,id3tag,ID3_FRAME_YEAR,
00856             SPLT_MP3_ID3_YEAR);
00857         MP3_VERIFY_ERROR();
00858         err = splt_mp3_put_original_libid3_frame(state,id3tag,ID3_FRAME_GENRE,
00859             SPLT_MP3_ID3_GENRE);
00860         MP3_VERIFY_ERROR();
00861         err = splt_mp3_put_original_libid3_frame(state,id3tag,ID3_FRAME_COMMENT,
00862             SPLT_MP3_ID3_COMMENT);
00863         MP3_VERIFY_ERROR();
00864         err = splt_mp3_put_original_libid3_frame(state,id3tag,ID3_FRAME_TRACK,
00865             SPLT_MP3_ID3_TRACK);
00866         MP3_VERIFY_ERROR();
00867 
00868         id3_tag_delete(id3tag);
00869       }
00870     }
00871 
00872 end: 
00873     ;
00874   }
00875 
00876   if (id3_tag_bytes)
00877   {
00878     free(id3_tag_bytes);
00879     id3_tag_bytes = NULL;
00880   }
00881 }
00882 
00884 void splt_mp3_put_libid3_frame_in_tag_with_content(struct id3_tag *id,
00885     const char *frame_type, int field_number, const char *content, int *error)
00886 {
00887   struct id3_frame *id_frame = NULL;
00888   id3_ucs4_t *field_content = NULL;
00889   union id3_field *id_field = NULL;
00890 
00891   if (content)
00892   {
00893     id_frame = id3_frame_new(frame_type);
00894     if (!id_frame)
00895     {
00896       goto error;
00897     }
00898 
00899     id_field = id3_frame_field(id_frame, field_number);
00900 
00901     id3_field_settextencoding(id3_frame_field(id_frame, 0),
00902         ID3_FIELD_TEXTENCODING_UTF_16);
00903 
00904     field_content = id3_utf8_ucs4duplicate((signed char *)content);
00905     if (! field_content)
00906     {
00907       goto error;
00908     }
00909 
00910     //1 is usually a string list
00911     if (field_number == 1)
00912     {
00913       if (id3_field_addstring(id_field, field_content) == -1)
00914       {
00915         goto error;
00916       }
00917     }
00918     //the comment is a full string: field number 3
00919     else if (field_number == 3)
00920     {
00921       if (id3_field_setfullstring(id_field, field_content) == -1)
00922       {
00923         goto error;
00924       }
00925     }
00926     if (field_content)
00927     {
00928       free(field_content);
00929       field_content = NULL;
00930     }
00931     if (id3_tag_attachframe(id, id_frame) == -1)
00932     {
00933       goto error;
00934     }
00935     id3_frame_delete(id_frame);
00936   }
00937 
00938   return;
00939 
00940 error:
00941   *error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
00942   if (id_frame)
00943   {
00944     id3_frame_delete(id_frame);
00945   }
00946   if (field_content)
00947   {
00948     free(field_content);
00949     field_content = NULL;
00950   }
00951   return;
00952 }
00953 
00954 static char *splt_mp3_build_libid3tag(const char *title, const char *artist,
00955     const char *album, const char *year, const char *genre, 
00956     const char *comment, int track, int *error, unsigned long *number_of_bytes,
00957     int tags_version)
00958 {
00959   struct id3_tag *id = id3_tag_new();
00960 
00961   id3_byte_t *bytes = NULL;
00962   id3_length_t bytes_length = 0;
00963 
00964   if (tags_version == 1)
00965   {
00966     id3_tag_options(id, ID3_TAG_OPTION_ID3V1, ID3_TAG_OPTION_ID3V1);
00967   }
00968   else
00969   {
00970     //turn off CRC and COMPRESSION; many players don't support that ?,
00971     //resulting in No tags (oh !)
00972     id3_tag_options(id, ID3_TAG_OPTION_CRC, 0);
00973     id3_tag_options(id, ID3_TAG_OPTION_COMPRESSION, 0);
00974   }
00975 
00976   splt_mp3_put_libid3_frame_in_tag_with_content(id, ID3_FRAME_TITLE, 1, title, error);
00977   if (*error < 0) { goto error; }
00978   splt_mp3_put_libid3_frame_in_tag_with_content(id, ID3_FRAME_ARTIST, 1, artist, error);
00979   if (*error < 0) { goto error; }
00980   splt_mp3_put_libid3_frame_in_tag_with_content(id, ID3_FRAME_ALBUM, 1, album, error);
00981   if (*error < 0) { goto error; }
00982   splt_mp3_put_libid3_frame_in_tag_with_content(id, ID3_FRAME_YEAR, 1, year, error);
00983   if (*error < 0) { goto error; }
00984   splt_mp3_put_libid3_frame_in_tag_with_content(id, ID3_FRAME_COMMENT, 3, comment, error);
00985   if (*error < 0) { goto error; }
00986   if (track != -1)
00987   {
00988     char track_str[255] = { '\0' };
00989     snprintf(track_str,254,"%d",track);
00990     splt_mp3_put_libid3_frame_in_tag_with_content(id, ID3_FRAME_TRACK, 1,
00991         track_str, error);
00992     if (*error < 0) { goto error; }
00993   }
00994 
00995   splt_mp3_put_libid3_frame_in_tag_with_content(id, ID3_FRAME_GENRE, 1, genre, error);
00996   if (*error < 0) { goto error; }
00997 
00998   //get the number of bytes needed for the tags
00999   bytes_length = id3_tag_render(id, NULL);
01000 
01001   if (bytes_length > 0)
01002   {
01003     //allocate memory for the tags
01004     bytes = malloc(sizeof(id3_byte_t) * bytes_length);
01005     if (!bytes)
01006     {
01007       goto error;
01008     }
01009     memset(bytes, '\0', sizeof(id3_byte_t) * bytes_length);
01010 
01011     bytes_length = id3_tag_render(id, bytes);
01012 
01013     *number_of_bytes = (unsigned long) bytes_length;
01014   }
01015 
01016   id3_tag_delete(id);
01017 
01018   return (char *) bytes;
01019 
01020 error:
01021   *error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
01022   id3_tag_delete(id);
01023   *number_of_bytes = 0;
01024   if (bytes)
01025   {
01026     free(bytes);
01027     bytes = NULL;
01028   }
01029 
01030   return NULL;
01031 }
01032 
01033 #else
01034 
01036 static const char unsigned splt_mp3_id3v1_genre_mapping[SPLT_ID3V1_NUMBER_OF_GENRES] = 
01037 { 0x00,
01038 
01039   0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A,
01040   0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14,
01041   0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 
01042   0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 
01043   0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32,
01044   0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 
01045   0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46,
01046   0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
01047 
01048   0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
01049   0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63,
01050   0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D,
01051   0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
01052   0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D,
01053 
01054   0xFF };
01055 
01057 static unsigned char splt_mp3_get_id3v1_mapping(const char *genre_string)
01058 {
01059   if (genre_string == NULL)
01060   {
01061     return 0xFF;
01062   }
01063 
01064   int i = 0;
01065   for (i = 0; i < SPLT_ID3V1_NUMBER_OF_GENRES; i++)
01066   {
01067     if (strncmp(genre_string, splt_id3v1_genres[i], strlen(genre_string)) == 0)
01068     {
01069       return splt_mp3_id3v1_genre_mapping[i];
01070     }
01071   }
01072 
01073   return 0xFF;
01074 }
01075 
01082 static char *splt_mp3_build_simple_id3v1(const char *title, const char *artist,
01083     const char *album, const char *year, const char *genre, 
01084     const char *comment, int track, int *error, unsigned long *number_of_bytes)
01085 {
01086   char *id = NULL;
01087   char buffer[30] = { '\0' };
01088   int j = 3,i = 0;
01089 
01090   if ((id = malloc(sizeof(char) * 128)) != NULL)
01091   {
01092     memset(id,'\0',128);
01093 
01094     strncpy(id, SPLT_MP3_TAG, 4);
01095 
01096     memset(buffer, '\0', 30);
01097     if (title!=NULL) strncpy(buffer, title, 30);
01098     for (i=0; i<30; i++) id[j++]=buffer[i];
01099 
01100     memset(buffer, '\0', 30);
01101     if (artist!=NULL) strncpy(buffer, artist, 30);
01102     for (i=0; i<30; i++) id[j++]=buffer[i];
01103 
01104     memset(buffer, '\0', 30);
01105     if (album!=NULL) strncpy(buffer, album, 30);
01106     for (i=0; i<30; i++) id[j++]=buffer[i];
01107 
01108     memset(buffer, '\0', 30);
01109     if (year!=NULL) strncpy(buffer, year, 4);
01110     for (i=0; i<4; i++) id[j++]=buffer[i];
01111 
01112     memset(buffer, '\0', 30);
01113     if (comment!=NULL) strncpy(buffer, comment, 30);
01114     for (i=0; i<30; i++) 
01115     {
01116       id[j++]=buffer[i];
01117     }
01118     //if we have a positive track
01119     if (track != -1)
01120     {
01121       if (track != 0x00)
01122       {
01123         id[j-1] = (char) track;
01124       }
01125     }
01126     id[j] = (char) splt_mp3_get_id3v1_mapping(genre);
01127   }
01128   else
01129   {
01130     *error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
01131     return NULL;
01132   }
01133 
01134   *number_of_bytes = 128;
01135 
01136   return id;
01137 }
01138 #endif
01139 
01146 static char *splt_mp3_build_id3_tags(splt_state *state,
01147     const char *title, const char *artist,
01148     const char *album, const char *year, const char *genre,
01149     const char *comment, int track, int *error,
01150     unsigned long *number_of_bytes, int version)
01151 {
01152   char *id = NULL;
01153 
01154 #ifdef NO_ID3TAG
01155   if (version == 1)
01156   {
01157     splt_d_print_debug(state,"Setting ID3v1 tags without libid3tag\n");
01158     id = splt_mp3_build_simple_id3v1(title, artist, album, year, genre, comment, track,
01159         error, number_of_bytes);
01160   }
01161 #else
01162   if (version == 1)
01163   {
01164     splt_d_print_debug(state,"Setting ID3v1 tags with libid3tag\n");
01165     id = splt_mp3_build_libid3tag(title, artist, album, year, genre, comment, track,
01166         error, number_of_bytes, 1);
01167   }
01168   else
01169   {
01170     splt_d_print_debug(state,"Setting ID3v2 tags with libid3tag\n");
01171     id = splt_mp3_build_libid3tag(title, artist, album, year, genre, comment, track,
01172         error, number_of_bytes, 2);
01173   }
01174 #endif
01175 
01176   return id;
01177 }
01178 
01185 static char *splt_mp3_build_tags(const char *filename, splt_state *state, int *error,
01186     unsigned long *number_of_bytes, int id3_version)
01187 {
01188   char *id3_data = NULL;
01189 
01190   if (splt_o_get_int_option(state,SPLT_OPT_TAGS) != SPLT_NO_TAGS)
01191   {
01192     splt_tags *tags = splt_tu_get_current_tags(state);
01193 
01194     if (tags)
01195     {
01196       char *artist_or_performer = splt_tu_get_artist_or_performer_ptr(tags);
01197       id3_data = splt_mp3_build_id3_tags(state,
01198           tags->title, artist_or_performer, tags->album,
01199           tags->year, tags->genre, tags->comment,
01200           tags->track, error, number_of_bytes, id3_version);
01201     }
01202   }
01203 
01204   return id3_data;
01205 }
01206 
01208 int splt_mp3_write_id3v1_tags(splt_state *state, FILE *file_output,
01209     const char *output_fname)
01210 {
01211   const char *filename = splt_t_get_filename_to_split(state);
01212   unsigned long number_of_bytes = 0;
01213   int error = SPLT_OK;
01214 
01215   char *id3_tags = splt_mp3_build_tags(filename, state, &error, &number_of_bytes, 1);
01216 
01217   if ((error >= 0) && (id3_tags) && (number_of_bytes > 0))
01218   {
01219     if (file_output)
01220     {
01221       if (fseeko(file_output, splt_mp3_getid3v1_offset(file_output), SEEK_END)!=-1)
01222       {
01223         if (splt_io_fwrite(state, id3_tags, 1, number_of_bytes, file_output) < number_of_bytes)
01224         {
01225           splt_e_set_error_data(state, output_fname);
01226           error = SPLT_ERROR_CANT_WRITE_TO_OUTPUT_FILE;
01227         }
01228       }
01229       else
01230       {
01231         splt_e_set_strerror_msg_with_data(state, output_fname);
01232         error = SPLT_ERROR_SEEKING_FILE;
01233       }
01234     }
01235   }
01236 
01237   if (id3_tags)
01238   {
01239     free(id3_tags);
01240     id3_tags = NULL;
01241   }
01242 
01243   return error;
01244 }
01245 
01246 #ifndef NO_ID3TAG
01247 int splt_mp3_write_id3v2_tags(splt_state *state, FILE *file_output,
01248     const char *output_fname, off_t *end_offset)
01249 {
01250   const char *filename = splt_t_get_filename_to_split(state);
01251   unsigned long number_of_bytes = 0;
01252   int error = SPLT_OK;
01253 
01254   char *id3_tags = splt_mp3_build_tags(filename, state, &error, &number_of_bytes, 2);
01255 
01256   if ((error >= 0) && (id3_tags) && (number_of_bytes > 0))
01257   {
01258     if (splt_io_fwrite(state, id3_tags, 1, number_of_bytes, file_output) < number_of_bytes)
01259     {
01260       splt_e_set_error_data(state, output_fname);
01261       error = SPLT_ERROR_CANT_WRITE_TO_OUTPUT_FILE;
01262     }
01263     else
01264     {
01265       if (end_offset != NULL)
01266       {
01267         *end_offset = number_of_bytes;
01268       }
01269     }
01270   }
01271 
01272   if (id3_tags)
01273   {
01274     free(id3_tags);
01275     id3_tags = NULL;
01276   }
01277 
01278   return error;
01279 }
01280 #endif
01281 
01283 int splt_mp3_get_output_tags_version(splt_state *state)
01284 {
01285 #ifdef NO_ID3TAG
01286   splt_d_print_debug(state,"Output tags version is ID3v1 without libid3tag\n");
01287   return 1;
01288 #else
01289   int original_tags_version = state->original_tags.tags_version;
01290   int force_tags_version = splt_o_get_int_option(state, SPLT_OPT_FORCE_TAGS_VERSION);
01291 
01292   int output_tags_version = original_tags_version;
01293   if (force_tags_version != 0)
01294   {
01295     output_tags_version = force_tags_version;
01296   }
01297 
01298   if ((output_tags_version == 0) &&
01299       (splt_o_get_int_option(state, SPLT_OPT_TAGS) == SPLT_CURRENT_TAGS))
01300   {
01301     char *filename = splt_t_get_filename_to_split(state);
01302     if (strcmp(filename, "-") != 0)
01303     {
01304       output_tags_version = 12;
01305     }
01306   }
01307 
01308   splt_d_print_debug(state,"Output tags version is ID3v _%d_\n", output_tags_version);
01309 
01310   return output_tags_version;
01311 #endif
01312 }
01313 
01314 /****************************/
01315 /* mp3 infos */
01316 
01325 static splt_mp3_state *splt_mp3_info(FILE *file_input, splt_state *state,
01326     int framemode, int *error)
01327 {
01328   splt_mp3_state *mp3state = state->codec;
01329 
01330   int prev = -1;
01331   long len;
01332 
01333   if ((mp3state = malloc(sizeof(splt_mp3_state)))==NULL)
01334   {
01335     *error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
01336     return NULL;
01337   }
01338   memset(mp3state, 0x0, sizeof(splt_mp3_state));
01339 
01340   char *filename = splt_t_get_filename_to_split(state);
01341 
01342   //always quiet
01343   mp3state->syncdetect = 0;
01344 
01345   //we initialise default values
01346   mp3state->frames = 1;
01347   mp3state->end = 0;
01348   mp3state->first = 1;
01349   mp3state->file_input = file_input;
01350   mp3state->framemode = framemode;
01351   mp3state->headw = 0;
01352   mp3state->mp3file.xing = 0;
01353   mp3state->mp3file.xing_offset = 0;
01354   mp3state->mp3file.xingbuffer = NULL;
01355   //ignore flength error (ex for non seekable stdin)
01356   mp3state->mp3file.len = splt_io_get_file_length(state, file_input, filename, error);
01357   splt_t_set_total_time(state, 0);
01358   mp3state->data_ptr = NULL;
01359   mp3state->data_len = 0;
01360   mp3state->buf_len = 0;
01361   mp3state->bytes = 0;
01362 
01363   //we initialise the mad structures
01364   splt_mp3_init_stream_frame(mp3state);
01365   mad_synth_init(&mp3state->synth);
01366 
01367   mad_timer_reset(&mp3state->timer);
01368 
01369   //we read mp3 infos and set pointers to read the mp3 data
01370   do
01371   {
01372     int ret = splt_mp3_get_frame(mp3state);
01373 
01374     if (ret == -2)
01375     {
01376       splt_e_set_error_data(state,filename);
01377       *error = SPLT_ERROR_INVALID;
01378       goto function_end;
01379     }
01380 
01381     if ((prev == 0) &&
01382         ((ret == 0) || (mp3state->stream.error == MAD_ERROR_BUFLEN)))
01383     {
01384       break;
01385     }
01386 
01387     //if we have succeeded to read a frame
01388     if (ret == 0)
01389     {
01390       //we set pointer to the frame
01391       mp3state->data_ptr = (unsigned char *) mp3state->stream.this_frame;
01392       //we set length of frame
01393       if(mp3state->stream.next_frame!=NULL)
01394       {
01395         mp3state->data_len = (long) (mp3state->stream.next_frame - mp3state->stream.this_frame);
01396       }
01397 
01398       if (mp3state->stream.anc_bitlen > 64)
01399       {
01400         int tag = 0;
01401         struct mad_bitptr ptr = mp3state->stream.anc_ptr;
01402         struct mad_bitptr start = ptr;
01403         //we search for xing (variable bit rate)
01404         unsigned long xing_word = mad_bit_read(&ptr, 32);
01405         if ((xing_word==SPLT_MP3_XING_MAGIC) ||
01406             (xing_word==SPLT_MP3_INFO_MAGIC))
01407         {
01408           tag = 1;
01409         }
01410         //Handle misplaced Xing header in mp3 files with CRC
01411         else 
01412         {
01413           if (xing_word == ((SPLT_MP3_XING_MAGIC << 16) & 0xffffffffL) 
01414               || xing_word == ((SPLT_MP3_INFO_MAGIC << 16) & 0xffffffffL))
01415           {
01416             ptr = start;
01417             mad_bit_skip(&ptr, 16);
01418             tag = 1;
01419           }
01420         }
01421 
01422         //if we have xing, put infos
01423         if (tag)
01424         {
01425           xing_word = mad_bit_read(&ptr, 32);
01426           if (xing_word & SPLT_MP3_XING_FRAMES)
01427           {
01428             mad_timer_t total;
01429             mp3state->frames = mad_bit_read(&ptr, 32);
01430             total = mp3state->frame.header.duration;
01431             mad_timer_multiply(&total, mp3state->frames);
01432             float total_time_milliseconds = (float) mad_timer_count(total, MAD_UNITS_MILLISECONDS);
01433             total_time_milliseconds /= 10.f;
01434             splt_t_set_total_time(state, (long) ceilf(total_time_milliseconds));
01435           }
01436 
01437           if (xing_word & SPLT_MP3_XING_BYTES)
01438           {
01439             if (mp3state->mp3file.len == 0)
01440               mp3state->mp3file.len = mad_bit_read(&ptr, 32);
01441           }
01442 
01443           if (splt_o_get_int_option(state, SPLT_OPT_XING))
01444           {
01445             mp3state->mp3file.xing = mp3state->data_len;
01446 
01447             if ((mp3state->mp3file.xingbuffer = 
01448                   malloc(mp3state->mp3file.xing))==NULL)
01449             {
01450               *error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
01451               goto function_end;
01452             }
01453 
01454             memcpy(mp3state->mp3file.xingbuffer, mp3state->data_ptr,
01455                 mp3state->mp3file.xing);
01456             mp3state->mp3file.xing_offset = splt_mp3_xing_info_off(mp3state);
01457           }
01458 
01459           splt_o_set_int_option(state, SPLT_OPT_FRAME_MODE, SPLT_TRUE);
01460           mp3state->framemode = 1;
01461 
01462           if (!splt_o_messages_locked(state))
01463           {
01464             if (!splt_o_get_iopt(state, SPLT_INTERNAL_FRAME_MODE_ENABLED))
01465             {
01466               int split_mode =
01467                 splt_o_get_int_option(state, SPLT_OPT_SPLIT_MODE);
01468 
01469               if (split_mode != SPLT_OPTION_WRAP_MODE &&
01470                   split_mode != SPLT_OPTION_ERROR_MODE)
01471               {
01472                 splt_c_put_info_message_to_client(state,
01473                     _(" info: found Xing or Info header. Switching to frame mode... \n"));
01474                 splt_o_set_iopt(state, SPLT_INTERNAL_FRAME_MODE_ENABLED, SPLT_TRUE);
01475               }
01476             }
01477           }
01478           continue;
01479         }
01480       }
01481     }
01482 
01483     prev = ret;
01484   } while (1);
01485 
01486   len = (long) (mp3state->buf_len - (mp3state->data_ptr - mp3state->inputBuffer));
01487 
01488   if (len < 0)
01489   {
01490     splt_e_set_error_data(state,filename);
01491     *error = SPLT_ERROR_INVALID;
01492     goto function_end;
01493   }
01494 
01495   //we put useful infos in the state
01496   mp3state->mp3file.firsth = (off_t) (mp3state->bytes - len);
01497   mp3state->bytes = mp3state->mp3file.firsth;
01498   mp3state->headw = 
01499     (unsigned long) ((mp3state->data_ptr[0] << 24) | 
01500         (mp3state->data_ptr[1] << 16) |
01501         (mp3state->data_ptr[2] << 8) | (mp3state->data_ptr[3]));
01502   mp3state->mp3file.mpgid = (int) ((mp3state->headw >> 19)&1);
01503   mp3state->mp3file.layer = mp3state->frame.header.layer;
01504 
01505   mp3state->mp3file.freq = mp3state->frame.header.samplerate;
01506   mp3state->mp3file.bitrate = mp3state->frame.header.bitrate/SPLT_MP3_BYTE;
01507 
01508   mp3state->mp3file.firsthead = 
01509     splt_mp3_makehead(mp3state->headw, mp3state->mp3file, mp3state->mp3file.firsthead, mp3state->mp3file.firsth);
01510 
01511   mp3state->mp3file.fps = (float) (mp3state->mp3file.freq*(2-mp3state->mp3file.mpgid));
01512   mp3state->mp3file.fps /= SPLT_MP3_PCM;
01513 
01514   //we put the channels stuff (mono, stereo)
01515   switch(mp3state->frame.header.mode)
01516   {
01517     case MAD_MODE_SINGLE_CHANNEL:
01518       mp3state->mp3file.channels = 0;
01519       break;
01520     case MAD_MODE_DUAL_CHANNEL:
01521       mp3state->mp3file.channels = 1;
01522       break;
01523     case MAD_MODE_JOINT_STEREO:
01524       mp3state->mp3file.channels = 2;
01525       break;
01526     case MAD_MODE_STEREO:
01527       mp3state->mp3file.channels = 3;
01528       break;
01529     default:
01530       mp3state->mp3file.channels = 4;
01531       break;
01532   }
01533 
01534   //we put the total time for constant bit rate
01535   //if it was not set for the variable bit rate
01536   if (splt_t_get_total_time(state) == 0)
01537   {
01538     if (mp3state->mp3file.len > 0)
01539     {
01540       long temp = (long)
01541         (((double)(mp3state->mp3file.len - mp3state->mp3file.firsth)
01542           / (double)mp3state->mp3file.bitrate) * 100.0);
01543 
01544       splt_t_set_total_time(state, temp);
01545     }
01546   }
01547 
01548 function_end:
01549   //we free memory allocated by mad_frame_decode(..)
01550   //TODO: memory leak
01551   //splt_mp3_finish_stream_frame(mp3state);
01552   mad_synth_finish(&mp3state->synth);
01553 
01554   return mp3state;
01555 }
01556 
01558 static void splt_mp3_end(splt_state *state, int *error)
01559 {
01560   splt_mp3_state *mp3state = state->codec;
01561   if (mp3state)
01562   {
01563     splt_mp3_finish_stream_frame(mp3state);
01564     if (mp3state->file_input)
01565     {
01566       if (mp3state->file_input != stdin)
01567       {
01568         if (fclose(mp3state->file_input) != 0)
01569         {
01570           splt_e_set_strerror_msg_with_data(state, splt_t_get_filename_to_split(state));
01571           *error = SPLT_ERROR_CANNOT_CLOSE_FILE;
01572         }
01573       }
01574       mp3state->file_input = NULL;
01575     }
01576     //we free the mp3 state 
01577     splt_mp3_state_free(state);
01578   }
01579   state->codec = NULL;
01580 }
01581 
01583 static void splt_mp3_get_info(splt_state *state, FILE *file_input, int *error)
01584 {
01585   //checks if valid mp3 file
01586   //before last argument, if framemode or not
01587   //last argument if we put messages to clients or not
01588   state->codec = splt_mp3_info(file_input, state,
01589         splt_o_get_int_option(state,SPLT_OPT_FRAME_MODE), error);
01590   //if error
01591   if ((*error < 0) || (state->codec == NULL))
01592   {
01593     if (state->codec != NULL)
01594     {
01595       splt_mp3_end(state, error);
01596     }
01597     return;
01598   }
01599   //print informations about the current file to the client
01600   else
01601   {
01602     if ((! splt_o_messages_locked(state)) &&
01603         (splt_o_get_int_option(state, SPLT_OPT_SPLIT_MODE) != SPLT_OPTION_WRAP_MODE) &&
01604         (splt_o_get_int_option(state, SPLT_OPT_SPLIT_MODE) != SPLT_OPTION_ERROR_MODE))
01605     {
01606       splt_mp3_state *mp3state = state->codec;
01607       struct splt_mp3 *mfile = &mp3state->mp3file;
01608 
01609       char mpeg_infos[1024] = { '\0' };
01610       snprintf(mpeg_infos, 1024, _(" info: MPEG %d Layer %d - %d Hz - %s"),
01611           (2-mfile->mpgid), mfile->layer, mfile->freq, splt_mp3_chan[mfile->channels]);
01612 
01613       char frame_mode_infos[256] = { '\0' };
01614       if (mp3state->framemode)
01615       {
01616         if (splt_o_get_int_option(state, SPLT_OPT_INPUT_NOT_SEEKABLE))
01617         {
01618           snprintf(frame_mode_infos, 255, _(" - FRAME MODE NS"));
01619         }
01620         else
01621         {
01622           snprintf(frame_mode_infos, 255, _(" - FRAME MODE"));
01623         }
01624       }
01625       else if (splt_o_get_int_option(state, SPLT_OPT_INPUT_NOT_SEEKABLE))
01626       {
01627         snprintf(frame_mode_infos, 255, _(" - NS - %d Kb/s"),
01628             mfile->bitrate * SPLT_MP3_BYTE / 1000);
01629       }
01630       else
01631       {
01632         snprintf(frame_mode_infos, 255, _(" - %d Kb/s"),
01633             mfile->bitrate * SPLT_MP3_BYTE / 1000);
01634       }
01635 
01636       char total_time[256] = { '\0' };
01637       int total_seconds = (int) (splt_t_get_total_time(state) / 100);
01638       int minutes = total_seconds / 60;
01639       int seconds = total_seconds % 60;
01640       snprintf(total_time,255, _(" - Total time: %dm.%02ds"), minutes, seconds%60);
01641 
01642       splt_c_put_info_message_to_client(state, 
01643           "%s%s%s\n", mpeg_infos, frame_mode_infos, total_time);
01644     }
01645   }
01646 }
01647 
01648 /****************************/
01649 /* mp3 scan for silence */
01650 
01661 static int splt_mp3_silence(splt_mp3_state *mp3state, int channels, mad_fixed_t threshold)
01662 {
01663   int i, j;
01664   mad_fixed_t sample;
01665   int silence = 1;
01666 
01667   for (j=0; j<channels; j++)
01668   {
01669     for(i=0; i<mp3state->synth.pcm.length; i++)
01670     {
01671       //get silence spot ?
01672       sample = mad_f_abs(mp3state->synth.pcm.samples[j][i]);
01673       mp3state->temp_level = mp3state->temp_level * 0.999 + sample * 0.001;
01674 
01675       if (sample > threshold)
01676       {
01677         silence = 0;
01678       }
01679     }
01680   }
01681 
01682   return silence;
01683 }
01684 
01695 static int splt_mp3_scan_silence(splt_state *state, off_t begin, 
01696     unsigned long length, float threshold, 
01697     float min, short output, int *error)
01698 {
01699   int len = 0, found = 0, shot;
01700   short first, flush = 0, stop = 0;
01701   unsigned long silence_begin = 0, silence_end = 0, time;
01702   //unsigned long count = 0;
01703   off_t pos;
01704   mad_fixed_t th;
01705 
01706   splt_mp3_state *mp3state = state->codec;
01707 
01708   splt_c_put_progress_text(state,SPLT_PROGRESS_SCAN_SILENCE);
01709 
01710   pos = begin;
01711   th = mad_f_tofixed(splt_co_convert_from_dB(threshold));
01712 
01713   //we seek to the begin
01714   if (fseeko(mp3state->file_input, begin, SEEK_SET)==-1)
01715   {
01716     splt_e_set_strerror_msg_with_data(state, splt_t_get_filename_to_split(state));
01717     *error = SPLT_ERROR_SEEKING_FILE;
01718     return -1;
01719   }
01720 
01721   first = output;
01722   shot = SPLT_DEFAULTSHOT;
01723 
01724   //initialise mad stuff
01725   splt_mp3_init_stream_frame(mp3state);
01726   mad_synth_init(&mp3state->synth);
01727 
01728   mad_timer_reset(&mp3state->timer);
01729 
01730   mp3state->temp_level = 0.0;
01731 
01732   //we do the effective scan
01733   do
01734   {
01735     int mad_err = SPLT_OK;
01736     switch (splt_mp3_get_valid_frame(state, &mad_err))
01737     {
01738       case 1:
01739         //1 we have a valid frame
01740         //we get mad infos and put them in the mp3state
01741         mad_timer_add(&mp3state->timer, mp3state->frame.header.duration);
01742         mad_synth_frame(&mp3state->synth,&mp3state->frame);
01743         time = (unsigned long) mad_timer_count(mp3state->timer, MAD_UNITS_CENTISECONDS);
01744 
01745         if (length > 0)
01746         {
01747           if (time >= length)
01748           {
01749             flush = 1;
01750             stop = 1;
01751           }
01752         }
01753 
01754         if ((!flush) && (splt_mp3_silence(mp3state, MAD_NCHANNELS(&mp3state->frame.header), th)))
01755         {
01756           if (len == 0) silence_begin = time;
01757           if (first == 0) 
01758           {
01759             len++;
01760           }
01761           if (shot < SPLT_DEFAULTSHOT)
01762             shot+=2;
01763           silence_end = time;
01764         }
01765         else
01766         {
01767           if (len > SPLT_DEFAULTSILLEN)
01768           {
01769             if ((flush) || (shot <= 0))
01770             {
01771               double begin_position, end_position;
01772               begin_position = (double) (silence_begin / 100.f);
01773               end_position = (double) (silence_end / 100.f);
01774               len = (int) (silence_end - silence_begin);
01775 
01776               if ((end_position - begin_position - min) >= 0.f)
01777               {
01778                 if (splt_siu_ssplit_new(&state->silence_list, begin_position, end_position,
01779                       len, error) == -1)
01780                 {
01781                   stop = 1;
01782                   found = -1;
01783                   break;
01784                 }
01785                 found++;
01786               }
01787 
01788               len = 0;
01789               shot = SPLT_DEFAULTSHOT;
01790             }
01791           }
01792           else 
01793           {
01794             len = 0;
01795           }
01796 
01797           if ((first) && (shot <= 0))
01798           {
01799             first = 0;
01800           }
01801 
01802           if (shot > 0) 
01803           {
01804             shot--;
01805           }
01806         }
01807 
01808         if (mp3state->mp3file.len > 0)
01809         {
01810           pos = ftello(mp3state->file_input);
01811 
01812           //if (count++ % 10 == 0)
01813           {
01814             float level = splt_co_convert_to_dB(mad_f_todouble(mp3state->temp_level));
01815             if (state->split.get_silence_level)
01816             {
01817               state->split.get_silence_level(time, level, state->split.silence_level_client_data);
01818             }
01819             state->split.p_bar->silence_db_level = level;
01820             state->split.p_bar->silence_found_tracks = found;
01821           }
01822 
01823           //if we don't have silence split,
01824           //put the 1/4 of progress
01825           if (splt_o_get_int_option(state, SPLT_OPT_SPLIT_MODE) != 
01826               SPLT_OPTION_SILENCE_MODE)
01827           {
01828             splt_c_update_progress(state,(double)(time),
01829                 (double)(length), 4,1/(float)4,
01830                 SPLT_DEFAULT_PROGRESS_RATE);
01831           }
01832           else
01833           {
01834             //if we have cancelled the split
01835             if (splt_t_split_is_canceled(state))
01836             {
01837               stop = 1;
01838             }
01839             splt_c_update_progress(state,(double)pos,
01840                 (double)(mp3state->mp3file.len),
01841                 1,0,SPLT_DEFAULT_PROGRESS_RATE);
01842           }
01843         }
01844         break;
01845       case 0:
01846         //0 we do nothing
01847         break;
01848       case -1:
01849         // -1 means eof
01850         stop = 1;
01851         break;
01852       case -3:
01853         //error from libmad
01854         stop = 1;
01855         *error = mad_err;
01856         found = -1;
01857         break;
01858       default:
01859         break;
01860     }
01861   } while (!stop && (found < SPLT_MAXSILENCE));
01862 
01863   //only if we have silence mode, we set progress to 100%
01864   if (splt_o_get_int_option(state, SPLT_OPT_SPLIT_MODE) == 
01865       SPLT_OPTION_SILENCE_MODE)
01866   {
01867     splt_c_update_progress(state,1.0,1.0,1,1,1);
01868   }
01869 
01870   //we finish with mad_*
01871   splt_mp3_finish_stream_frame(mp3state);
01872   mad_synth_finish(&mp3state->synth);
01873 
01874   return found;
01875 }
01876 
01877 /****************************/
01878 /* mp3 split */
01879 
01880 static off_t splt_mp3_write_data_ptr(splt_state *state, const char *filename,
01881     const char *output_fname, FILE *file_output, int *error)
01882 {
01883   splt_mp3_state *mp3state = state->codec;
01884 
01885   long len = (long) (mp3state->inputBuffer + mp3state->buf_len - mp3state->data_ptr);
01886 
01887   if (len < 0)
01888   {
01889     splt_e_set_error_data(state, filename);
01890     *error = SPLT_ERROR_WHILE_READING_FILE;
01891     return len;
01892   }
01893 
01894   if (splt_io_fwrite(state, mp3state->data_ptr, 1, len, file_output) < len)
01895   {
01896     splt_e_set_error_data(state,output_fname);
01897     *error = SPLT_ERROR_CANT_WRITE_TO_OUTPUT_FILE;
01898     return len;
01899   }
01900 
01901   mp3state->data_len = 0;
01902 
01903   return len;
01904 }
01905 
01906 
01919 static int splt_mp3_simple_split(splt_state *state, const char *output_fname,
01920     off_t begin, off_t end, int do_write_tags, short write_first_frame)
01921 {
01922   splt_d_print_debug(state,"Mp3 simple split on output _%s_\n", output_fname);
01923   splt_d_print_debug(state,"Mp3 simple split offset begin is _%ld_\n", begin);
01924   splt_d_print_debug(state,"Mp3 simple split offset end is _%ld_\n", end);
01925 
01926   splt_mp3_state *mp3state = state->codec;
01927 
01928   int error = SPLT_OK_SPLIT;
01929 
01930   FILE *file_output = NULL;
01931   off_t position = 0;
01932   unsigned char buffer[SPLT_MP3_READBSIZE] = { '\0' };
01933   long readed = 0;
01934   //for the progress
01935   off_t temp_end = 0;
01936   //the start point of the split
01937   long start = begin;
01938   int split_mode = splt_o_get_int_option(state, SPLT_OPT_SPLIT_MODE);
01939 
01940   splt_c_put_progress_text(state, SPLT_PROGRESS_CREATE);
01941 
01942   char *filename = splt_t_get_filename_to_split(state);
01943 
01944   position = ftello(mp3state->file_input); // Save current position
01945 
01946   if (fseeko(mp3state->file_input, begin, SEEK_SET)==-1)
01947   {
01948     return SPLT_ERROR_BEGIN_OUT_OF_FILE;
01949   }
01950 
01951   //get the file size
01952   off_t st_size;
01953   char *fname_to_split = splt_t_get_filename_to_split(state);
01954   if(splt_io_stat(fname_to_split, NULL, &st_size) == 0)
01955   {
01956     mp3state->end2 = st_size;
01957   }
01958   else
01959   {
01960     splt_e_set_strerror_msg_with_data(state, fname_to_split);
01961     return SPLT_ERROR_CANNOT_OPEN_FILE;
01962   }
01963 
01964   if (! splt_o_get_int_option(state, SPLT_OPT_PRETEND_TO_SPLIT))
01965   {
01966     file_output = splt_mp3_open_file_write(state, output_fname, &error);
01967     if (error < 0) { return error; }
01968   }
01969 
01970   int output_tags_version = splt_mp3_get_output_tags_version(state);
01971 
01972 #ifndef NO_ID3TAG
01973   //write id3 tags version 2 at the start of the file, if necessary
01974   if (do_write_tags && (output_tags_version == 2 || output_tags_version == 12))
01975   {
01976     int err = SPLT_OK;
01977     if ((err = splt_mp3_write_id3v2_tags(state, file_output,
01978             output_fname, NULL)) < 0)
01979     {
01980       error = err;
01981       goto function_end;
01982     }
01983   }
01984 #endif
01985 
01986   if (mp3state->mp3file.xing != 0)
01987   {
01988     if (splt_o_get_int_option(state, SPLT_OPT_XING))
01989     {
01990       //error mode split must only contain original file data
01991       if (state->options.split_mode != SPLT_OPTION_ERROR_MODE)
01992       {
01993         if (splt_io_fwrite(state, mp3state->mp3file.xingbuffer, 1, 
01994               mp3state->mp3file.xing, file_output) < mp3state->mp3file.xing)
01995         {
01996           splt_e_set_error_data(state, output_fname);
01997           error = SPLT_ERROR_CANT_WRITE_TO_OUTPUT_FILE;
01998           goto function_end;
01999         }
02000       }
02001     }
02002   }
02003 
02004   if (write_first_frame)
02005   {
02006     splt_mp3_write_data_ptr(state, filename, output_fname, file_output, &error);
02007     if (error < 0) { goto function_end; }
02008   }
02009 
02010   while (!feof(mp3state->file_input))
02011   {
02012     readed = SPLT_MP3_READBSIZE;
02013     if (end != -1)
02014     {
02015       if (begin >= end) 
02016       {
02017         break;
02018       }
02019       if ((end - begin) < SPLT_MP3_READBSIZE)
02020       {
02021         readed = end - begin;
02022       }
02023     }
02024 
02025     if ((readed = fread(buffer, 1, readed, mp3state->file_input))==-1)
02026     {
02027       break;
02028     }
02029 
02030     if (splt_io_fwrite(state, buffer, 1, readed, file_output) < readed)
02031     {
02032       splt_e_set_error_data(state,output_fname);
02033       error = SPLT_ERROR_CANT_WRITE_TO_OUTPUT_FILE;
02034       goto function_end;
02035     }
02036     begin += readed;
02037 
02038     //we update the progress bar
02039     if ((split_mode == SPLT_OPTION_WRAP_MODE) ||
02040         (split_mode == SPLT_OPTION_ERROR_MODE) ||
02041         ((split_mode == SPLT_OPTION_NORMAL_MODE)
02042          && (!splt_o_get_int_option(state, SPLT_OPT_AUTO_ADJUST)) 
02043          && (!splt_o_get_int_option(state, SPLT_OPT_FRAME_MODE))))
02044     {
02045       temp_end = end;
02046       //for the last split
02047       if (end == -1)
02048       {
02049         temp_end = mp3state->end2;
02050       }
02051 
02052       splt_c_update_progress(state,(double)(begin-start),
02053           (double)(temp_end-start),1,0,
02054           SPLT_DEFAULT_PROGRESS_RATE);
02055     }
02056     else
02057     {
02058       //if auto adjust, we have 50%
02059       if (splt_o_get_int_option(state, SPLT_OPT_AUTO_ADJUST))
02060       {
02061         splt_c_update_progress(state,(double)(begin-start),
02062             (double)(end-start),
02063             2,0.5, SPLT_DEFAULT_PROGRESS_RATE);
02064       }
02065       else
02066       {
02067         if (splt_o_get_int_option(state, SPLT_OPT_SPLIT_MODE)
02068             == SPLT_OPTION_TIME_MODE)
02069         {
02070           temp_end = end;
02071           //for the last split
02072           if (end == -1)
02073           {
02074             temp_end = mp3state->end2;
02075           }
02076 
02077           //if framemode
02078           if (splt_o_get_int_option(state, SPLT_OPT_FRAME_MODE))
02079           {
02080             splt_c_update_progress(state,(double)(begin-start),
02081                 (double)(temp_end-start),
02082                 2,0.5, SPLT_DEFAULT_PROGRESS_RATE);
02083           }
02084           else
02085           {
02086             splt_c_update_progress(state,(double)(begin-start),
02087                 (double)(temp_end-start),
02088                 1,0, SPLT_DEFAULT_PROGRESS_RATE);
02089           }
02090         }
02091         else
02092         {
02093           splt_c_update_progress(state,(double)(begin-start),
02094               (double)(end-start),
02095               2,0.5, SPLT_DEFAULT_PROGRESS_RATE);
02096         }
02097       }
02098     }
02099   }
02100 
02101   //write id3 tags version 1 at the end of the file, if necessary
02102   if (do_write_tags && (output_tags_version == 1 || output_tags_version == 12))
02103   {
02104     int err = SPLT_OK;
02105     if ((err = splt_mp3_write_id3v1_tags(state, file_output, output_fname)) < 0)
02106     {
02107       error = err;
02108       goto function_end;
02109     }
02110   }
02111 
02112   if (fseeko(mp3state->file_input, position, SEEK_SET)==-1)
02113   {
02114     splt_e_set_strerror_msg_with_data(state, filename);
02115     goto function_end;
02116   }
02117 
02118 function_end:
02119   if (file_output)
02120   {
02121     if (file_output != stdout)
02122     {
02123       if (fclose(file_output) != 0)
02124       {
02125         splt_e_set_strerror_msg_with_data(state, filename);
02126         return SPLT_ERROR_CANNOT_CLOSE_FILE;
02127       }
02128     }
02129     file_output = NULL;
02130   }
02131 
02132   return error;
02133 }
02134 
02150 static double splt_mp3_split(const char *output_fname, splt_state *state,
02151     double fbegin_sec, double fend_sec, int *error, int save_end_point)
02152 {
02153   splt_d_print_debug(state,"Mp3 split...\n");
02154   splt_d_print_debug(state,"Output filename is _%s_\n", output_fname);
02155   splt_d_print_debug(state,"Begin position is _%lf_\n", fbegin_sec);
02156   splt_d_print_debug(state,"End position is _%lf_\n", fend_sec);
02157 
02158   splt_mp3_state *mp3state = state->codec;
02159 
02160   int adjustoption = splt_o_get_int_option(state, SPLT_OPT_PARAM_GAP);
02161   short seekable = ! splt_o_get_int_option(state, SPLT_OPT_INPUT_NOT_SEEKABLE);
02162   float threshold = splt_o_get_float_option(state, SPLT_OPT_PARAM_THRESHOLD);
02163 
02164   short fend_sec_is_not_eof =
02165     !splt_u_fend_sec_is_bigger_than_total_time(state, fend_sec);
02166 
02167   short eof=0, check_bitrate=0;
02168 
02169   char *filename = splt_t_get_filename_to_split(state);
02170 
02171   FILE *file_output = NULL;
02172   short writing = 0, finished=0;
02173   unsigned long fbegin=0;
02174   off_t wrote = 0;
02175   long len = 0;
02176   //for the progress
02177   unsigned long stopped_frames = 0;
02178   int progress_adjust_val = 2;
02179 
02180   if (adjustoption) 
02181   {
02182     progress_adjust_val = 4;
02183   }
02184 
02185   splt_c_put_progress_text(state,SPLT_PROGRESS_CREATE);
02186 
02187   double sec_end_time = fend_sec;
02188 
02189   //if not seekable
02190   if (!seekable)
02191   {
02192     if (! splt_o_get_int_option(state, SPLT_OPT_PRETEND_TO_SPLIT))
02193     {
02194       file_output = splt_mp3_open_file_write(state, output_fname, error);
02195       if (*error < 0) { return sec_end_time; };
02196     }
02197 
02198     int output_tags_version = splt_mp3_get_output_tags_version(state);
02199 
02200     off_t id3v2_end_offset = 0;
02201 #ifndef NO_ID3TAG
02202     //write id3 tags version 2 at the start of the file
02203     if (output_tags_version == 2 || output_tags_version == 12)
02204     {
02205       int err = SPLT_OK;
02206       if ((err = splt_mp3_write_id3v2_tags(state, file_output,
02207               output_fname, &id3v2_end_offset)) < 0)
02208       {
02209         *error = err;
02210         goto bloc_end;
02211       }
02212     }
02213 #endif
02214 
02215     //if we have the framemode
02216     if (mp3state->framemode)
02217     {
02218       splt_d_print_debug(state,"Starting not seekable mp3 frame mode...\n");
02219 
02220       long begin_c, end_c, time;
02221       //convert seconds to hundreths
02222       begin_c = (long) (fbegin_sec * 100);
02223       if (fend_sec > 0)
02224       {
02225         end_c = (long) (fend_sec * 100);
02226       }
02227       else 
02228       {
02229         end_c = 0;
02230       }
02231       time = 0;
02232 
02233       do
02234       {
02235         //we write xing if necessary
02236         if (!writing && (time >= begin_c))
02237         {
02238           writing = 1;
02239           fbegin = mp3state->frames;
02240 
02241           if (mp3state->mp3file.xing > 0)
02242           {
02243             wrote = splt_io_fwrite(state, mp3state->mp3file.xingbuffer,
02244                 1, mp3state->mp3file.xing, file_output);
02245             if (wrote < mp3state->mp3file.xing)
02246             {
02247               splt_e_set_error_data(state,output_fname);
02248               *error = SPLT_ERROR_CANT_WRITE_TO_OUTPUT_FILE;
02249               goto bloc_end;
02250             }
02251           }
02252         }
02253 
02254         //we do the split
02255         if (writing)
02256         {
02257           if (mp3state->data_len > 0)
02258           {
02259             if ((len = splt_io_fwrite(state, mp3state->data_ptr, 1, mp3state->data_len, file_output))
02260                 < mp3state->data_len)
02261             {
02262               splt_e_set_error_data(state,output_fname);
02263               *error = SPLT_ERROR_CANT_WRITE_TO_OUTPUT_FILE;
02264               goto bloc_end;
02265             }
02266             wrote = (off_t) (wrote + len);
02267             mp3state->data_len = 0;
02268           }
02269 
02270           if ((end_c > 0) && (time >= end_c))
02271           {
02272             finished = 1;
02273           }
02274           if (eof || finished)
02275           {
02276             finished = 1;
02277             if (eof) { *error = SPLT_OK_SPLIT_EOF; }
02278             break;
02279           }
02280         }
02281 
02282         //progress bar
02283         if (splt_o_get_int_option(state,SPLT_OPT_SPLIT_MODE)
02284             == SPLT_OPTION_TIME_MODE)
02285         {
02286           splt_c_update_progress(state,(double)(time-begin_c),
02287               (double)(end_c-begin_c),1,0,
02288               SPLT_DEFAULT_PROGRESS_RATE);
02289         }
02290         else
02291         {
02292           splt_c_update_progress(state,(double)(time),
02293               (double)(end_c),1,0,
02294               SPLT_DEFAULT_PROGRESS_RATE);
02295         }
02296 
02297         int mad_err = SPLT_OK;
02298         switch (splt_mp3_get_valid_frame(state, &mad_err))
02299         {
02300           case 1:
02301             mad_timer_add(&mp3state->timer, mp3state->frame.header.duration);
02302             mp3state->frames++;
02303             time = (unsigned long) mad_timer_count(mp3state->timer, MAD_UNITS_CENTISECONDS);
02304             break;
02305           case 0:
02306             break;
02307           case -1:
02308             eof = 1;
02309             *error = SPLT_OK_SPLIT_EOF;
02310             break;
02311           case -3:
02312             //error from libmad
02313             *error = mad_err;
02314             goto bloc_end;
02315             break;
02316           default:
02317             break;
02318         }
02319 
02320       } while (!finished);
02321     }
02322     //if we don't have the framemode
02323     else
02324     {
02325       splt_d_print_debug(state,"Starting mp3 not seekable non frame mode...\n");
02326 
02327       off_t begin = 0, end = 0;
02328       if (fend_sec_is_not_eof)
02329       {
02330         end = (off_t) (fend_sec * mp3state->mp3file.bitrate + mp3state->mp3file.firsth);
02331       }
02332       else
02333       {
02334         end = -1;
02335       }
02336 
02337       //find begin point because no 'end' saved point
02338       if (mp3state->end == 0)
02339       {
02340         begin = (off_t) (fbegin_sec * mp3state->mp3file.bitrate + mp3state->mp3file.firsth);
02341 
02342         if ((mp3state->bytes == begin) && (mp3state->data_len > 0))
02343         {
02344           wrote += splt_mp3_write_data_ptr(state, filename, output_fname, file_output, error);
02345           if (*error < 0) { goto bloc_end; }
02346         }
02347         else
02348         {
02349           while (mp3state->bytes < begin)
02350           {
02351             off_t to_read;
02352             if (feof(mp3state->file_input))
02353             {
02354               *error = SPLT_ERROR_BEGIN_OUT_OF_FILE;
02355               goto bloc_end;
02356             }
02357             to_read = (begin - mp3state->bytes);
02358             if (to_read > SPLT_MAD_BSIZE)
02359               to_read = SPLT_MAD_BSIZE;
02360             if ((mp3state->data_len = fread(mp3state->inputBuffer, 1, to_read, mp3state->file_input))<=0)
02361             {
02362               *error = SPLT_ERROR_BEGIN_OUT_OF_FILE;
02363               goto bloc_end;
02364             }
02365             mp3state->bytes+=mp3state->data_len;
02366           }
02367 
02368           int mad_err = SPLT_OK;
02369           splt_mp3_init_stream_frame(mp3state);
02370           switch (splt_mp3_get_valid_frame(state, &mad_err))
02371           {
02372             case 1:
02373               len = (long) (mp3state->inputBuffer + mp3state->buf_len - mp3state->data_ptr);
02374               if (len < 0)
02375               {
02376                 splt_e_set_error_data(state,filename);
02377                 *error = SPLT_ERROR_WHILE_READING_FILE;
02378                 goto bloc_end;
02379               }
02380               if (splt_io_fwrite(state, mp3state->data_ptr, 1, len, file_output) < len)
02381               {
02382                 splt_e_set_error_data(state,output_fname);
02383                 *error = SPLT_ERROR_CANT_WRITE_TO_OUTPUT_FILE;
02384                 goto bloc_end;
02385               }
02386               wrote = (off_t) (wrote + len);
02387               mp3state->data_len = 0;
02388               break;
02389             case 0:
02390               break;
02391             case -1:
02392               eof = 1;
02393               *error = SPLT_ERROR_BEGIN_OUT_OF_FILE;
02394               break;
02395             case -3:
02396               //error from libmad
02397               *error = mad_err;
02398               goto bloc_end;
02399               break;
02400             default:
02401               break;
02402           }
02403         }
02404       }
02405       //set the 'begin' as the saved 'end'
02406       else
02407       {
02408         len = (long) (mp3state->inputBuffer + mp3state->buf_len - mp3state->data_ptr);
02409         if (len < 0)
02410         {
02411           splt_e_set_error_data(state,filename);
02412           *error = SPLT_ERROR_WHILE_READING_FILE;
02413           goto bloc_end;
02414         }
02415         if (splt_io_fwrite(state, mp3state->data_ptr, 1, len, file_output) < len)
02416         {
02417           splt_e_set_error_data(state,output_fname);
02418           *error = SPLT_ERROR_CANT_WRITE_TO_OUTPUT_FILE;
02419           goto bloc_end;
02420         }
02421         wrote = (off_t) (wrote + len);
02422         mp3state->data_len = 0;
02423         begin = mp3state->end;
02424       }
02425 
02426       long split_begin_point = mp3state->bytes;
02427       //while not end of file, read write:
02428       while (!eof)
02429       {
02430         off_t to_read = SPLT_MAD_BSIZE;
02431         if (end > 0)
02432         {
02433           to_read = (end - mp3state->bytes);
02434           if (to_read <= 0)
02435           {
02436             break;
02437           }
02438           if (to_read > SPLT_MAD_BSIZE)
02439             to_read = SPLT_MAD_BSIZE;
02440         }
02441 
02442         if (feof(mp3state->file_input) || 
02443             ((mp3state->data_len = 
02444               fread(mp3state->inputBuffer, 1, to_read, mp3state->file_input))<=0))
02445         {
02446           eof = 1;
02447           *error = SPLT_OK_SPLIT_EOF;
02448           break;
02449         }
02450 
02451         if (splt_io_fwrite(state, mp3state->inputBuffer, 1,
02452               mp3state->data_len, file_output) < mp3state->data_len)
02453         {
02454           splt_e_set_error_data(state,output_fname);
02455           *error = SPLT_ERROR_CANT_WRITE_TO_OUTPUT_FILE;
02456           goto bloc_end;
02457         }
02458 
02459         mp3state->bytes += mp3state->data_len;
02460 
02461         splt_c_update_progress(state, (double) (mp3state->bytes-split_begin_point),
02462             (double)(end-split_begin_point), 1,0,SPLT_DEFAULT_PROGRESS_RATE);
02463       }
02464 
02465       splt_mp3_save_end_point(state, mp3state, save_end_point, end);
02466 
02467       if (!eof)
02468       {
02469         //take the whole last frame : might result in more frames
02470         //but if we don't do it, we might have less frames
02471         int mad_err = SPLT_OK;
02472         splt_mp3_init_stream_frame(mp3state);
02473         switch (splt_mp3_get_valid_frame(state, &mad_err))
02474         {
02475           case 1:
02476             len = (long) (mp3state->data_ptr - mp3state->inputBuffer);
02477             if (len < 0)
02478             {
02479               splt_e_set_error_data(state,filename);
02480               *error = SPLT_ERROR_WHILE_READING_FILE;
02481               goto bloc_end;
02482             }
02483             if (splt_io_fwrite(state, mp3state->inputBuffer, 1, len, file_output) < len)
02484             {
02485               splt_e_set_error_data(state,output_fname);
02486               *error = SPLT_ERROR_CANT_WRITE_TO_OUTPUT_FILE;
02487               goto bloc_end;
02488             }
02489             break;
02490           case 0:
02491             break;
02492           case -1:
02493             eof = 1;
02494             *error = SPLT_OK_SPLIT_EOF;
02495             break;
02496           case -3:
02497             *error = mad_err;
02498             goto bloc_end;
02499             break;
02500           default:
02501             break;
02502         }
02503       }
02504     }
02505 
02506     //we write id3 and other stuff
02507     if (file_output)
02508     {
02509       if (mp3state->mp3file.xing > 0)
02510       {
02511         if (fseeko(file_output, mp3state->mp3file.xing_offset+4+id3v2_end_offset, SEEK_SET)!=-1)
02512         {
02513           unsigned long headw = (unsigned long) (mp3state->frames - fbegin + 1); // Frames
02514           fputc((headw >> 24) & 0xFF, file_output);
02515           fputc((headw >> 16) & 0xFF, file_output);
02516           fputc((headw >> 8) & 0xFF, file_output);
02517           fputc((headw >> 0) & 0xFF, file_output);
02518           headw = (unsigned long) (wrote); // Bytes
02519           fputc((headw >> 24) & 0xFF, file_output);
02520           fputc((headw >> 16) & 0xFF, file_output);
02521           fputc((headw >> 8) & 0xFF, file_output);
02522           fputc((headw >> 0) & 0xFF, file_output);
02523         }
02524         else
02525         {
02526           splt_e_set_strerror_msg_with_data(state, output_fname);
02527           *error = SPLT_ERROR_SEEKING_FILE;
02528           goto bloc_end;
02529         }
02530       }
02531 
02532       //write id3 tags version 1 at the end of the file
02533       if (output_tags_version == 1 || output_tags_version == 12)
02534       {
02535         int err = SPLT_OK;
02536         if ((err = splt_mp3_write_id3v1_tags(state, file_output, output_fname)) < 0)
02537         {
02538           *error = err;
02539           goto bloc_end;
02540         }
02541       }
02542     }
02543 
02544 bloc_end:
02545     if (file_output)
02546     {
02547       if (file_output != stdout)
02548       {
02549         if (fclose(file_output) != 0)
02550         {
02551           splt_e_set_strerror_msg_with_data(state, output_fname);
02552           *error = SPLT_ERROR_CANNOT_CLOSE_FILE;
02553         }
02554       }
02555     }
02556     file_output = NULL;
02557 
02558     if (*error == SPLT_OK) { *error = SPLT_OK_SPLIT; }
02559 
02560     return sec_end_time;
02561   }
02562   //if seekable:
02563   else
02564   {
02565     short write_first_frame = SPLT_FALSE;
02566     off_t begin = 0, end = 0;
02567     //if framemode
02568     if (mp3state->framemode)
02569     {
02570       splt_d_print_debug(state,"Starting seekable mp3 frame mode...\n");
02571 
02572       unsigned long fbegin, fend, adjust;
02573       fbegin = fend = adjust = 0;
02574       //prefer to split a bit before the start than loosing some frame
02575       //so we don't 'ceilf'
02576       fbegin = fbegin_sec * mp3state->mp3file.fps;
02577 
02578       if (fend_sec_is_not_eof)
02579       {
02580         //if adjustoption
02581         if (adjustoption)
02582         {
02583           if (fend_sec_is_not_eof)
02584           {
02585             float adj = (float) (adjustoption);
02586             float len = (fend_sec - fbegin_sec);
02587             if (adj > len)
02588             {
02589               adj = len;
02590             }
02591             if (fend_sec > adj)
02592             {
02593               fend_sec -= adj;
02594             }
02595             adjust = (unsigned long) (adj * 100.f);
02596           }
02597           else 
02598           {
02599             adjust = 0;
02600           }
02601         }
02602         //prefer to split a bit after the end than loosing some frame
02603         //before the end
02604         fend = (unsigned long) ceilf(fend_sec * mp3state->mp3file.fps);
02605       }
02606       else 
02607       {
02608         fend = 0xFFFFFFFF;
02609       }
02610 
02611       splt_d_print_debug(state,"Finding begin...\n");
02612 
02613       if (mp3state->end == 0)
02614       {
02615         if (mp3state->first)
02616         {
02617           mp3state->h.ptr = mp3state->mp3file.firsthead.ptr;
02618           mp3state->h.framesize = mp3state->mp3file.firsthead.framesize;
02619           begin = mp3state->mp3file.firsthead.ptr;
02620           mp3state->first = 0;
02621         }
02622 
02623         splt_c_put_progress_text(state,SPLT_PROGRESS_PREPARE);
02624 
02625         // Finds begin by counting frames
02626         while (mp3state->frames < fbegin)
02627         {
02628           begin = splt_mp3_findhead(mp3state, mp3state->h.ptr + mp3state->h.framesize);
02629           if (begin == -1) { *error = SPLT_ERROR_BEGIN_OUT_OF_FILE; goto bloc_end2; }
02630 
02631           //count the number of syncerrors
02632           if ((begin!=mp3state->h.ptr + mp3state->h.framesize)&&(state->syncerrors>=0)) 
02633           {
02634             state->syncerrors++;
02635           }
02636           if ((mp3state->syncdetect)&&(state->syncerrors> SPLT_MAXSYNC))
02637           {
02638             splt_mp3_checksync(mp3state);
02639           }
02640 
02641           mp3state->h = splt_mp3_makehead(mp3state->headw, mp3state->mp3file, mp3state->h, begin);
02642           mp3state->frames++;
02643 
02644           //if we have adjust mode, then put only 25%
02645           //else put 50%
02646           if (adjustoption)
02647           {
02648             splt_c_update_progress(state,(double)(mp3state->frames),
02649                 (double)fend, 8,
02650                 0,SPLT_DEFAULT_PROGRESS_RATE);
02651           }
02652           else
02653           {
02654             splt_c_update_progress(state,(double)(mp3state->frames),
02655                 (double)fend,progress_adjust_val,
02656                 0,SPLT_DEFAULT_PROGRESS_RATE);
02657           }
02658         }
02659       }
02660       else
02661       {
02662         begin = mp3state->end;
02663       }
02664 
02665       splt_d_print_debug(state,"Begin is _%ld_\n", begin);
02666 
02667       if (mp3state->mp3file.len > 0)
02668       {
02669         if (begin >= mp3state->mp3file.len) // If we can check, we just do that :)
02670         {
02671           *error = SPLT_ERROR_BEGIN_OUT_OF_FILE;
02672           goto bloc_end2;
02673         }
02674       }
02675 
02676       splt_c_put_progress_text(state,SPLT_PROGRESS_PREPARE);
02677 
02678       long int frames_begin = mp3state->frames;
02679       // Finds end by counting frames
02680       while (mp3state->frames <= fend)
02681       {
02682         mp3state->frames++;
02683         end = splt_mp3_findhead(mp3state, mp3state->h.ptr + mp3state->h.framesize);
02684         if (end == -1)
02685         {
02686           end = mp3state->h.ptr + mp3state->h.framesize; // Last valid offset
02687           eof=1;
02688           *error = SPLT_OK_SPLIT_EOF;
02689           break;
02690         }
02691 
02692         //count the number of syncerrors
02693         if ((end != mp3state->h.ptr + mp3state->h.framesize)&&(state->syncerrors>=0))
02694         {
02695           state->syncerrors++;
02696         }
02697         if ((mp3state->syncdetect)&&(state->syncerrors>SPLT_MAXSYNC))
02698         {
02699           splt_mp3_checksync(mp3state);
02700         }
02701 
02702         mp3state->h = splt_mp3_makehead (mp3state->headw, mp3state->mp3file, mp3state->h, end);
02703 
02704         //if we have a progress callback function
02705         //time split only calculates the end of the 
02706         //split
02707         int split_mode = splt_o_get_int_option(state, SPLT_OPT_SPLIT_MODE);
02708         if (((split_mode == SPLT_OPTION_TIME_MODE) || 
02709               (split_mode == SPLT_OPTION_SILENCE_MODE))
02710             && (!splt_o_get_int_option(state,SPLT_OPT_AUTO_ADJUST)))
02711         {
02712           splt_c_update_progress(state, (double)(mp3state->frames-fbegin),
02713               (double)(fend-fbegin), progress_adjust_val,
02714               0, SPLT_DEFAULT_PROGRESS_RATE);
02715         }
02716         else
02717         {
02718           if (adjustoption)
02719           {
02720             if(adjust)
02721             {
02722               if (split_mode == SPLT_OPTION_TIME_MODE)
02723               {
02724                 splt_c_update_progress(state,
02725                     (double)(mp3state->frames-frames_begin),
02726                     (double)(fend-frames_begin),
02727                     4,0,SPLT_DEFAULT_PROGRESS_RATE);
02728               }
02729               else
02730               {
02731                 splt_c_update_progress(state,
02732                     (double)(mp3state->frames-frames_begin),
02733                     (double)(fend-frames_begin),
02734                     8,1/(float)8,SPLT_DEFAULT_PROGRESS_RATE);
02735               }
02736             }
02737           }
02738           else
02739           {
02740             splt_c_update_progress(state,
02741                 (double)(mp3state->frames-stopped_frames),
02742                 (double)(fend-stopped_frames),
02743                 progress_adjust_val,
02744                 0,SPLT_DEFAULT_PROGRESS_RATE);
02745           }
02746         }
02747 
02748         //if adjust option, scans for silence
02749         if ((adjust) && (mp3state->frames >= fend))
02750         {
02751           int silence_points_found =
02752             splt_mp3_scan_silence(state, end, 2 * adjust, threshold, 0.f, 0, error);
02753           //if error, go out
02754           if (silence_points_found == -1)
02755           {
02756             goto bloc_end2;
02757           }
02758           else if (silence_points_found > 0)
02759           {
02760             adjust = (unsigned long) (splt_siu_silence_position(state->silence_list, mp3state->off) 
02761                 * mp3state->mp3file.fps);
02762           }
02763           else
02764           {
02765             adjust = (unsigned long) (adjustoption * mp3state->mp3file.fps);
02766           }
02767           fend += adjust;
02768           end = splt_mp3_findhead(mp3state, end);
02769 
02770           sec_end_time = mp3state->frames / mp3state->mp3file.fps;
02771 
02772           splt_siu_ssplit_free(&state->silence_list);
02773           adjust=0;
02774           //progress
02775           splt_c_put_progress_text(state,SPLT_PROGRESS_PREPARE);
02776           stopped_frames = mp3state->frames;
02777         }
02778       }
02779 
02780       splt_mp3_save_end_point(state, mp3state, save_end_point, end);
02781 
02782       //if xing, we get xing
02783       if (mp3state->mp3file.xing > 0)
02784       {
02785         unsigned long headw;
02786         headw = (unsigned long) (mp3state->frames - fbegin + 1); // Frames
02787         mp3state->mp3file.xingbuffer[mp3state->mp3file.xing_offset+4] = (headw >> 24) & 0xFF;
02788         mp3state->mp3file.xingbuffer[mp3state->mp3file.xing_offset+5] = (headw >> 16) & 0xFF;
02789         mp3state->mp3file.xingbuffer[mp3state->mp3file.xing_offset+6] = (headw >> 8) & 0xFF;
02790         mp3state->mp3file.xingbuffer[mp3state->mp3file.xing_offset+7] = headw  & 0xFF;
02791         //we put the length of the file if end is -1
02792         if (end == -1)
02793         {
02794           end = mp3state->mp3file.len;
02795         }
02796         headw = (unsigned long) (end - begin + mp3state->mp3file.xing); // Bytes
02797         mp3state->mp3file.xingbuffer[mp3state->mp3file.xing_offset+8] = (headw >> 24) & 0xFF;
02798         mp3state->mp3file.xingbuffer[mp3state->mp3file.xing_offset+9] = (headw >> 16) & 0xFF;
02799         mp3state->mp3file.xingbuffer[mp3state->mp3file.xing_offset+10] = (headw >> 8) & 0xFF;
02800         mp3state->mp3file.xingbuffer[mp3state->mp3file.xing_offset+11] = headw  & 0xFF;
02801       }
02802     }
02803     else
02804     //if not framemode
02805     {
02806       splt_d_print_debug(state,"Starting mp3 seekable non frame mode...\n");
02807 
02808       long first_frame_offset = mp3state->inputBuffer + mp3state->buf_len - mp3state->data_ptr;
02809 
02810       //find begin point if the last 'end' not saved
02811       if (mp3state->end == 0) 
02812       {
02813         begin = (off_t) (fbegin_sec * mp3state->mp3file.bitrate + mp3state->mp3file.firsth);
02814 
02815         if ((mp3state->bytes == begin) && (mp3state->data_len > 0))
02816         {
02817           write_first_frame = SPLT_TRUE;
02818           begin += first_frame_offset;
02819         }
02820         else
02821         {
02822           begin = splt_mp3_findvalidhead(mp3state, begin);
02823         }
02824 
02825         if (begin == -1)
02826         {
02827           *error = SPLT_ERROR_BEGIN_OUT_OF_FILE;
02828           goto bloc_end2;
02829         }
02830         if (splt_mp3_tabsel_123[1 - mp3state->mp3file.mpgid][mp3state->mp3file.layer-1][splt_mp3_c_bitrate(mp3state->headw)] != 
02831             mp3state->mp3file.firsthead.bitrate)
02832         {
02833           check_bitrate = 1;
02834         }
02835       }
02836       //set the begin point from the last 'end' saved
02837       else 
02838       {
02839         begin = mp3state->end;
02840       }
02841 
02842       if (fend_sec_is_not_eof)
02843       {
02844         end = (off_t) (fend_sec * mp3state->mp3file.bitrate + mp3state->mp3file.firsth);
02845         if (write_first_frame)
02846         {
02847           end += first_frame_offset;
02848         }
02849         //take the whole last frame : might result in more frames
02850         //but if we don't do it, we might have less frames
02851         end = splt_mp3_findvalidhead(mp3state, end);
02852         if (splt_mp3_tabsel_123[1 - mp3state->mp3file.mpgid][mp3state->mp3file.layer-1][splt_mp3_c_bitrate(mp3state->headw)] != 
02853             mp3state->mp3file.firsthead.bitrate)
02854           check_bitrate = 1;
02855       }
02856       else
02857       {
02858         end = -1;
02859       }
02860 
02861       splt_mp3_save_end_point(state, mp3state, save_end_point, end);
02862     }
02863 
02864     //seekable real split
02865     int err = splt_mp3_simple_split(state, output_fname, begin, end,
02866         SPLT_TRUE, write_first_frame);
02867     if (err < 0) { *error = err; }
02868 
02869     if (!save_end_point)
02870     {
02871       if (splt_o_get_long_option(state, SPLT_OPT_OVERLAP_TIME) > 0)
02872       {
02873         mp3state->frames = 1;
02874         mp3state->first = 1;
02875       }
02876     }
02877   }
02878 
02879   if (check_bitrate)
02880   {
02881     *error = SPLT_MIGHT_BE_VBR;
02882   }
02883 
02884   if (*error == SPLT_OK) { *error = SPLT_OK_SPLIT; }
02885 
02886 bloc_end2:
02887 
02888   return sec_end_time;
02889 }
02890 
02891 /****************************/
02892 /* mp3 syncerror */
02893 
02896 static off_t splt_mp3_adjustsync(splt_mp3_state *mp3state, off_t begin, off_t end)
02897 {
02898   off_t position;
02899   position = begin;
02900   if (fseeko(mp3state->file_input, position, SEEK_SET)==-1)
02901   {
02902     return (off_t) (-1);
02903   }
02904 
02905   // First we search for ID3v1
02906   while (position++ < end)
02907   {
02908     if (fgetc(mp3state->file_input)=='T') {
02909       if (fgetc(mp3state->file_input)=='A') {
02910         if (fgetc(mp3state->file_input)=='G')
02911           return (position + 127);
02912         else position++;
02913       }
02914       if (fseeko(mp3state->file_input, -1, SEEK_CUR) == -1)
02915       {
02916         return (off_t) (-1);
02917       }
02918     }
02919   }
02920 
02921   position = begin;
02922 
02923   if (fseeko(mp3state->file_input, position, SEEK_SET)==-1)
02924   {
02925     return (off_t) (-1);
02926   }
02927 
02928   // Now we search for ID3v2
02929   while (position++ < end) 
02930   {
02931     if (fgetc(mp3state->file_input)=='I')
02932     {
02933       if (fgetc(mp3state->file_input)=='D')
02934       {
02935         if (fgetc(mp3state->file_input)=='3')
02936         {
02937           return (position - 1);
02938         }
02939         else 
02940         {
02941           position++;
02942         }
02943       }
02944       if(fseeko(mp3state->file_input, -1, SEEK_CUR)==-1)
02945       {
02946         return (off_t) (-1);
02947       }
02948     }
02949   }
02950 
02951   return end;
02952 }
02953 
02955 static void splt_mp3_syncerror_search(splt_state *state, int *error)
02956 {
02957   off_t offset = 0;
02958   char *filename = splt_t_get_filename_to_split(state);
02959   int sync_err = SPLT_OK;
02960 
02961   splt_mp3_state *mp3state = state->codec;
02962 
02963   splt_c_put_progress_text(state,SPLT_PROGRESS_SEARCH_SYNC);
02964 
02965   mp3state->h.ptr = mp3state->mp3file.firsthead.ptr;
02966   mp3state->h.framesize = mp3state->mp3file.firsthead.framesize;
02967 
02968   //we get the file length for the progress
02969   off_t st_size;
02970   if(splt_io_stat(filename, NULL, &st_size) == 0)
02971   {
02972     //put the start point
02973     sync_err = splt_se_serrors_append_point(state, 0);
02974     if (sync_err != SPLT_OK)
02975     {
02976       *error = sync_err;
02977       return;
02978     }
02979 
02980     //search for sync errors and put in splitpoints
02981     while (state->serrors->serrors_points_num < SPLT_MAXSYNC)
02982     {
02983       offset = splt_mp3_findhead(mp3state, mp3state->h.ptr + mp3state->h.framesize);
02984       if (offset==-1)
02985       {
02986         break;
02987       }
02988 
02989       if (offset != mp3state->h.ptr + mp3state->h.framesize)
02990       {
02991         off_t serror_point =
02992           splt_mp3_adjustsync(mp3state, mp3state->h.ptr, offset);
02993 
02994         sync_err = splt_se_serrors_append_point(state, serror_point);
02995         if (sync_err != SPLT_OK)
02996         {
02997           *error = sync_err;
02998           return;
02999         }
03000         offset = splt_mp3_findvalidhead(mp3state, serror_point);
03001         if (splt_io_get_word(mp3state->file_input, offset, SEEK_SET, &mp3state->headw) == -1)
03002         {
03003           *error = SPLT_ERR_SYNC;
03004           return;
03005         }
03006       }
03007 
03008       mp3state->h = splt_mp3_makehead (mp3state->headw, mp3state->mp3file,
03009           mp3state->h, offset);
03010 
03011       if (splt_t_split_is_canceled(state))
03012       {
03013         *error = SPLT_SPLIT_CANCELLED;
03014         return;
03015       }
03016 
03017       //progress
03018       splt_c_update_progress(state,(double)(offset),
03019           (double)(st_size),1,0,
03020           SPLT_DEFAULT_PROGRESS_RATE);
03021     }
03022   }
03023   else
03024   {
03025     splt_e_set_strerror_msg_with_data(state, filename);
03026     *error = SPLT_ERROR_CANNOT_OPEN_FILE;
03027     return;
03028   }
03029 
03030   if (state->serrors->serrors_points_num == 0)
03031   {
03032     *error = SPLT_ERR_NO_SYNC_FOUND;
03033     return;
03034   }
03035 
03036   if (state->serrors->serrors_points_num == SPLT_MAXSYNC)
03037   {
03038     *error = SPLT_ERR_TOO_MANY_SYNC_ERR;
03039     return;
03040   }
03041 
03042   //put the end point
03043   sync_err = splt_se_serrors_append_point(state, LONG_MAX);
03044   if (sync_err != SPLT_OK)
03045   {
03046     *error = sync_err;
03047     return;
03048   }
03049 
03050   *error = SPLT_SYNC_OK;
03051 
03052   return;
03053 }
03054 
03055 /****************************/
03056 /* mp3 dewrap */
03057 
03059 static const unsigned char splt_mp3_albumwraphead[22] =
03060 {
03061   0xa, 0x23, 0x54, 0x49, 0x54, 0x32, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x41, 0x6c, 0x62, 0x75, 0x6d, 0x57, 0x72, 0x61, 0x70,
03062 };
03063 
03069 static void splt_mp3_dewrap(int listonly, const char *dir, int *error, splt_state *state)
03070 {
03071   if (listonly)
03072   {
03073     *error = SPLT_OK;
03074   }
03075   else
03076   {
03077     *error = SPLT_DEWRAP_OK;
03078   }
03079 
03080   //if albumwrap or mp3wrap
03081   short albumwrap=0, mp3wrap=0;
03082   //wrapfiles = the wrapped files number
03083   int wrapfiles=0, i, j, k=0;
03084   unsigned char c;
03085   char filename[2048] = { '\0' };
03086   off_t begin=0, end=0, len = 0, id3offset = 0;
03087   char junk[2048] = { '\0' };
03088   char *file_to_dewrap = splt_t_get_filename_to_split(state);
03089 
03090   //if error
03091   if (*error < 0)
03092   {
03093     return;
03094   }
03095   else
03096   {
03097     splt_mp3_state *mp3state = state->codec;
03098 
03099     if (*error >= 0)
03100     {
03101       len = splt_io_get_file_length(state, mp3state->file_input, file_to_dewrap, error);
03102       if (error < 0) { return; }
03103 
03104       id3offset = splt_mp3_getid3v2_end_offset(mp3state->file_input, 0);
03105 
03106       //we go at the beginning of the file
03107       if (fseeko(mp3state->file_input, id3offset, SEEK_SET)==-1)
03108       {
03109         *error = SPLT_DEWRAP_ERR_FILE_NOT_WRAPED_DAMAGED;
03110         return;
03111       }
03112 
03113       splt_d_print_debug(state,"Searching for wrap string...\n");
03114 
03115       //we search the WRAP string in the file to see if it was wrapped
03116       //with mp3wrap
03117       for (i=0; i<16384; i++)
03118       {
03119         if (feof(mp3state->file_input))
03120         {
03121           *error = SPLT_DEWRAP_ERR_FILE_NOT_WRAPED_DAMAGED;
03122           return;
03123         }
03124         if ((id3offset = ftello(mp3state->file_input))==-1)
03125         {
03126           *error = SPLT_DEWRAP_ERR_FILE_NOT_WRAPED_DAMAGED;
03127           return;
03128         }
03129         if (fgetc(mp3state->file_input)=='W')
03130           if (fgetc(mp3state->file_input)=='R')
03131             if (fgetc(mp3state->file_input)=='A')
03132               if (fgetc(mp3state->file_input)=='P')
03133               {
03134                 mp3wrap = 1;
03135                 break;
03136               }
03137       }
03138 
03139       //we check if the file was wrapped with albumwrap
03140       //only if not mp3wrap
03141       if (!mp3wrap && (id3offset!=0))
03142       {    
03143         if (fseeko(mp3state->file_input, (off_t) 8, SEEK_SET)==-1)
03144         {
03145           *error = SPLT_DEWRAP_ERR_FILE_NOT_WRAPED_DAMAGED;
03146           return;
03147         }      
03148         albumwrap = 1;
03149         for (i=0; i<22; i++)
03150         {
03151           if (splt_mp3_albumwraphead[i]!=fgetc(mp3state->file_input))
03152           {
03153             albumwrap = 0;
03154             break;
03155           }
03156         }
03157       }
03158 
03159       //we do the mp3wrap or albumwrap
03160       if (albumwrap || mp3wrap)
03161       {
03162         splt_d_print_debug(state,"Effective dewrap...\n");
03163 
03164         //mp3wrap checkings and we get the wrap file number
03165         if (mp3wrap) {
03166           splt_d_print_debug(state,"Mp3 mp3wrap check...\n");
03167           short indexver;
03168 
03169           //Mp3Wrap version
03170           char major_v = fgetc(mp3state->file_input);
03171           char minor_v = fgetc(mp3state->file_input);
03172 
03173           splt_c_put_info_message_to_client(state, 
03174               _(" Detected file created with: Mp3Wrap v. %c.%c\n"),
03175               major_v,minor_v);
03176 
03177           indexver = fgetc(mp3state->file_input);
03178           if (indexver > SPLT_MP3_INDEXVERSION)
03179           {
03180             *error = SPLT_DEWRAP_ERR_VERSION_OLD;
03181             return;
03182           }
03183           wrapfiles = (int) fgetc(mp3state->file_input);
03184           if (feof(mp3state->file_input)) 
03185           {
03186             *error = SPLT_DEWRAP_ERR_FILE_NOT_WRAPED_DAMAGED;
03187             return;
03188           }
03189           //crc
03190           if (indexver > 0x0)
03191           {
03192             unsigned long crc = 0, fcrc = 0;
03193             if (splt_io_get_word(mp3state->file_input, 0, SEEK_CUR, &fcrc)==-1)
03194             {
03195               *error = SPLT_DEWRAP_ERR_FILE_NOT_WRAPED_DAMAGED;
03196               return;
03197             }
03198 
03199             //perform CRC only if we don't have quiet mode
03200             if (! splt_o_get_int_option(state, SPLT_OPT_QUIET_MODE))
03201             {
03202               begin = ftello(mp3state->file_input);
03203               if (fseeko(mp3state->file_input, 
03204                     splt_mp3_getid3v1_offset(mp3state->file_input), SEEK_END)==-1)
03205               {
03206                 splt_e_set_strerror_msg_with_data(state, file_to_dewrap);
03207                 *error = SPLT_ERROR_SEEKING_FILE;
03208                 return;
03209               }
03210               end = ftello(mp3state->file_input);
03211               splt_c_put_info_message_to_client(state,
03212                   _(" Check for file integrity: calculating CRC please wait... "));
03213               crc = splt_mp3_c_crc(state, mp3state->file_input, begin, end, error);
03214               if (*error < 0)
03215               {
03216                 return;
03217               }
03218               if (crc != fcrc)
03219               {
03220                 //No interactivity in the library (for the moment)
03221                 //fprintf (stderr, "BAD\nWARNING: Bad CRC. File might be damaged. Continue anyway? (y/n) ");
03222                 //fgets(junk, 32, stdin);
03223                 //if (junk[0]!='y')
03224                 //error("Aborted.",125);
03225                 //- no interactivity in the library for the moment
03226                 *error = SPLT_ERROR_CRC_FAILED;
03227                 return;
03228               }
03229               else 
03230               {
03231                 splt_c_put_info_message_to_client(state, _(" OK\n"));
03232               }
03233               if (fseeko(mp3state->file_input, begin, SEEK_SET)==-1)
03234               {
03235                 splt_e_set_strerror_msg_with_data(state, file_to_dewrap);
03236                 *error = SPLT_ERROR_SEEKING_FILE;
03237                 return;
03238               }
03239             }
03240           }
03241         }
03242 
03243         //the albumwrap checkings and we get the wrap files number in
03244         //wrapfiles variable
03245         if (albumwrap)
03246         {
03247           splt_d_print_debug(state,"Mp3 albumwrap check...\n");
03248 
03249           splt_c_put_info_message_to_client(state, 
03250               _(" Detected file created with: AlbumWrap\n"));
03251 
03252           if (fseeko(mp3state->file_input, (off_t) 0x52d, SEEK_SET)==-1)
03253           {
03254             *error = SPLT_DEWRAP_ERR_FILE_NOT_WRAPED_DAMAGED;
03255             return;
03256           }
03257           i = 0;
03258           while (((c=fgetc(mp3state->file_input))!=0x20) &&(i<2048))
03259             junk[i++] = c;
03260           junk[i] = '\0';
03261           wrapfiles = atoi (junk);
03262         }
03263         if (wrapfiles<=0)
03264         {
03265           *error = SPLT_DEWRAP_ERR_NO_FILE_OR_BAD_INDEX;
03266           return;
03267         }
03268 
03269         //we put the number of "splitpoints"
03270         state->split.splitnumber = wrapfiles+1;
03271 
03272         splt_c_put_info_message_to_client(state, _(" Total files: %d\n"),wrapfiles);
03273         
03274         //we do the dewrap
03275         for (i=0; i<wrapfiles; i++)
03276         {
03277           if (!splt_t_split_is_canceled(state))
03278           {
03279             //we put the current file to split
03280             splt_t_set_current_split(state, i+1);
03281 
03282             //if the first time, we get the begin,
03283             //otherwise the begin will be the end of the previous
03284             if (i==0)
03285             {
03286               //we get the begin wrap
03287               if (mp3wrap)
03288               {
03289                 unsigned long w;
03290                 if (splt_io_get_word (mp3state->file_input, 0, SEEK_CUR, &w)==-1)
03291                 {
03292                   splt_e_set_error_data(state,file_to_dewrap);
03293                   *error = SPLT_DEWRAP_ERR_FILE_DAMAGED_INCOMPLETE;
03294                   return;
03295                 }
03296                 begin = (off_t) (w + id3offset);
03297               }
03298 
03299               //we get the begin wrap
03300               if (albumwrap)
03301               {
03302                 if (fseeko (mp3state->file_input,
03303                       (off_t) SPLT_MP3_ABWINDEXOFFSET, SEEK_SET)==-1)
03304                 {
03305                   splt_e_set_error_data(state,file_to_dewrap);
03306                   *error = SPLT_DEWRAP_ERR_FILE_DAMAGED_INCOMPLETE;
03307                   return;
03308                 }
03309                 j = 0;
03310                 while ((c=fgetc(mp3state->file_input))!='[')
03311                   if (j++ > 32) 
03312                   {
03313                     splt_e_set_error_data(state,file_to_dewrap);
03314                     *error = SPLT_DEWRAP_ERR_FILE_DAMAGED_INCOMPLETE;
03315                     return;
03316                   }
03317                 if (fseeko(mp3state->file_input, (off_t) 3, SEEK_CUR)==-1)
03318                 {
03319                   splt_e_set_error_data(state,file_to_dewrap);
03320                   *error = SPLT_DEWRAP_ERR_FILE_DAMAGED_INCOMPLETE;
03321                   return;
03322                 }
03323                 j = 0;
03324                 while ((j<2048) && ((c = fgetc(mp3state->file_input))!='['))
03325                   if (c!='.') junk[j++] = c;
03326                   else k = j;
03327                 junk[j] = '\0';
03328                 begin = (off_t) atol (junk);
03329                 k = j - k;
03330                 if (k<4)
03331                 {
03332                   for (j=0; j<(4-k); j++)
03333                   {
03334                     begin = begin * 10;
03335                   }
03336                 }
03337               }
03338             }
03339             else 
03340             {
03341               begin = end;
03342             }
03343 
03344             //we get the end and checkings..
03345             if (mp3wrap)
03346             {
03347               unsigned long w;
03348               j = 0;
03349               do
03350               {
03351                 c = fgetc(mp3state->file_input);
03352                 //for files wrapped using windows
03353                 if (c==SPLT_NDIRCHAR)
03354                 {
03355                   c=SPLT_DIRCHAR;
03356                 }
03357                 filename[j++] = c;
03358               }  while ((c!=0x00)&&(j<2048));
03359 
03360               if (splt_io_get_word (mp3state->file_input, 0, SEEK_CUR, &w) == -1)
03361               {
03362                 splt_e_set_error_data(state,file_to_dewrap);
03363                 *error = SPLT_DEWRAP_ERR_FILE_DAMAGED_INCOMPLETE;
03364                 return;
03365               }
03366 
03367               end = (off_t) (w + id3offset);
03368 
03369               //create output directories for the wrapped files
03370               //if we don't list only and if we don't have an output
03371               //directory
03372               if (!listonly && (!dir || dir[0] == '\0'))
03373               {
03374                 memset(junk, 0x00, 2048);
03375                 char *ptr = filename;
03376                 while (((ptr = strchr(ptr, SPLT_DIRCHAR))!=NULL)&&((ptr-filename)<2048))
03377                 {
03378                   ptr++;
03379                   strncpy(junk, filename, ptr-filename);
03380                   if (! splt_io_check_if_directory(junk))
03381                   {
03382                     if ((splt_io_mkdir(state, junk)) == -1)
03383                     {
03384                       *error = SPLT_ERROR_CANNOT_CREATE_DIRECTORY;
03385                       splt_e_set_strerror_msg_with_data(state, junk);
03386                       return;
03387                     }
03388                   }
03389                 }
03390               }
03391             }
03392 
03393             //we get the end wrap point for albumwrap and
03394             //checkings.. 
03395             if (albumwrap)
03396             {
03397               if (i<wrapfiles-1)
03398               {
03399                 if (fseeko (mp3state->file_input, 
03400                       (off_t) (SPLT_MP3_ABWINDEXOFFSET + (i * SPLT_MP3_ABWLEN)), SEEK_SET)==-1)
03401                 {
03402                   splt_e_set_error_data(state,file_to_dewrap);
03403                   *error = SPLT_DEWRAP_ERR_FILE_DAMAGED_INCOMPLETE;
03404                   return;
03405                 }
03406                 j = 0;
03407                 while ((j<2048) && ((c = fgetc(mp3state->file_input))!='['))
03408                   if (c!='.') junk[j++] = c;
03409                   else k = j;
03410                 junk[j] = '\0';
03411                 end = (off_t) atol (junk);
03412                 k = j - k;
03413                 if (k<4)
03414                   for (j=0; j<(4-k); j++)
03415                     end = end * 10;
03416                 end += begin;
03417               }
03418               else end = len;
03419 
03420               if (fseeko (mp3state->file_input, 
03421                     (off_t) (SPLT_MP3_ABWINDEXOFFSET + (i*SPLT_MP3_ABWLEN)), SEEK_SET)==-1)
03422               {
03423                 splt_e_set_error_data(state,file_to_dewrap);
03424                 *error = SPLT_DEWRAP_ERR_FILE_DAMAGED_INCOMPLETE;
03425               }
03426               j = 0;
03427               while ((c=fgetc(mp3state->file_input))!='[')
03428                 if (j++ > 32) 
03429                 {
03430                   splt_e_set_error_data(state,file_to_dewrap);
03431                   *error = SPLT_DEWRAP_ERR_FILE_DAMAGED_INCOMPLETE;
03432                   return;
03433                 }
03434               if (fseeko (mp3state->file_input, (off_t) 3, SEEK_CUR)==-1)
03435               {
03436                 splt_e_set_error_data(state,file_to_dewrap);
03437                 *error = SPLT_DEWRAP_ERR_FILE_DAMAGED_INCOMPLETE;
03438                 return;
03439               }
03440               j = 0;
03441               while ((c=fgetc(mp3state->file_input))!='[')
03442                 if (j++ > 32) 
03443                 {
03444                   splt_e_set_error_data(state,file_to_dewrap);
03445                   *error = SPLT_DEWRAP_ERR_FILE_DAMAGED_INCOMPLETE;
03446                   return;
03447                 }
03448               if (fseeko(mp3state->file_input, (off_t) 3, SEEK_CUR)==-1)
03449               {
03450                 splt_e_set_error_data(state,file_to_dewrap);
03451                 *error = SPLT_DEWRAP_ERR_FILE_DAMAGED_INCOMPLETE;
03452                 return;
03453               }
03454               j = 0;
03455               while (j<=400)
03456                 filename[j++] = fgetc(mp3state->file_input);
03457               for (j=400; j>0; j--) {
03458                 if (filename[j]==0x20)
03459                   filename[j]='\0';
03460                 else break;
03461               }
03462               filename[j+1] = '\0';
03463             }
03464 
03465             splt_d_print_debug(state,"Found the file _%s_\n", filename);
03466             splt_d_print_debug(state,"Cut the dirchar");
03467 
03468             //we cut the .DIRCHAR before the filename
03469             char str_temp[4];
03470             snprintf(str_temp,4,"%c%c",'.',SPLT_DIRCHAR);
03471             if (strstr(filename,str_temp) != NULL)
03472             {
03473               char *filename2 = strdup(filename);
03474               if (!filename2)
03475               {
03476                 *error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
03477                 return;
03478               }
03479               else
03480               {
03481                 snprintf(filename,2048, "%s", filename2+2);
03482                 free(filename2);
03483                 filename2 = NULL;
03484               }
03485             }
03486 
03487             if (feof(mp3state->file_input)) 
03488             {
03489               splt_e_set_error_data(state,file_to_dewrap);
03490               *error = SPLT_DEWRAP_ERR_FILE_DAMAGED_INCOMPLETE;
03491               return;
03492             }
03493 
03494             //if we only list the contents
03495             //we put the files in the wrap_files
03496             if (listonly)
03497             {
03498               splt_d_print_debug(state,"Only list wrapped files\n");
03499 
03500               int put_file_error = SPLT_OK;
03501               put_file_error = splt_w_wrap_put_file(state, wrapfiles, i, filename);
03502               if (put_file_error != SPLT_OK)
03503               {
03504                 *error = put_file_error;
03505                 return;
03506               }
03507             }
03508             //if we split the file
03509             //we split from begin to end calculated previously
03510             else
03511             {
03512               splt_d_print_debug(state,"Split wrapped file\n");
03513 
03514               int ret = 0;
03515               //if we have an output directory
03516               //-try to create it
03517               if (dir && (dir[0] != '\0'))
03518               {
03519                 char temp[2048] = { '\0' };
03520                 strncpy(temp, filename, 2048);
03521                 char *ptr = temp;
03522                 //if we have an output dir, cut directory path from filename
03523                 if ((ptr = strrchr(temp,SPLT_DIRCHAR)) == NULL)
03524                 {
03525                   ptr = temp;
03526                 }
03527                 else
03528                 {
03529                   if (ptr-temp > 0)
03530                   {
03531                     ptr++;
03532                   }
03533                 }
03534                 //if dir == .DIRCHAR
03535                 if (strcmp(dir,str_temp) == 0)
03536                 {
03537                   snprintf(filename, 2048,"%s%s", dir, ptr);
03538                 }
03539                 else
03540                 {
03541                   if (dir[strlen(dir)-1] == SPLT_DIRCHAR)
03542                   {
03543                     snprintf(filename, 2048,"%s%s", dir, ptr);
03544                   }
03545                   else
03546                   {
03547                     snprintf(filename, 2048,"%s%c%s", dir, SPLT_DIRCHAR, ptr);
03548                   }
03549                 }
03550                 splt_d_print_debug(state,"wrap dir _%s_\n", dir);
03551                 splt_d_print_debug(state,"wrap after dir _%s_\n", ptr);
03552               }
03553 
03554               //free xingbuffer
03555               if (mp3state->mp3file.xingbuffer)
03556               {
03557                 free(mp3state->mp3file.xingbuffer);
03558                 mp3state->mp3file.xingbuffer = NULL;
03559               }
03560               mp3state->mp3file.xing = 0;
03561 
03562               int append_err = SPLT_OK;
03563               append_err = splt_sp_append_splitpoint(state,0,
03564                   splt_su_get_fname_without_path(filename), SPLT_SPLITPOINT);
03565               if (append_err != SPLT_OK)
03566               {
03567                 *error = append_err;
03568                 return;
03569               }
03570 
03571               //cut extension
03572               int cut_err = splt_sp_cut_splitpoint_extension(state,i);
03573               if (cut_err != SPLT_OK)
03574               {
03575                 *error = cut_err;
03576                 return;
03577               }
03578 
03579               //do the real wrap split
03580               ret = splt_mp3_simple_split(state, filename, begin, end,
03581                   SPLT_FALSE, SPLT_FALSE);
03582 
03583               //if we could split put the split file
03584               if (ret >= 0)
03585               {
03586                 ret = splt_c_put_split_file(state, filename);
03587                 if (ret < 0) { *error = ret; }
03588               }
03589               else
03590               {
03591                 *error = ret;
03592               }
03593             }
03594           }
03595         }
03596       }
03597       else
03598       {
03599         *error = SPLT_DEWRAP_ERR_FILE_NOT_WRAPED_DAMAGED;
03600         return;
03601       }
03602     }
03603   }
03604 }
03605 
03607 void splt_mp3_init(splt_state *state, int *error)
03608 {
03609   FILE *file_input = NULL;
03610   char *filename = splt_t_get_filename_to_split(state);
03611 
03612   state->syncerrors = 0;
03613 
03614   //if we can open the file
03615   if ((file_input = splt_mp3_open_file_read(state, filename, error)) != NULL)
03616   {
03617     splt_mp3_get_info(state, file_input, error);
03618 
03619     if (*error >= 0)
03620     {
03621       splt_mp3_state *mp3state = state->codec;
03622       mp3state->off = splt_o_get_float_option(state,SPLT_OPT_PARAM_OFFSET);
03623 
03624       //we initialise frames to 1
03625       if (splt_t_get_total_time(state) > 0)
03626       {
03627         mp3state->frames = 1;
03628       }
03629     }
03630   }
03631 }
03632 
03645 void splt_pl_set_plugin_info(splt_plugin_info *info, int *error)
03646 {
03647   float plugin_version = 1.0;
03648 
03649   //set plugin version
03650   info->version = plugin_version;
03651 
03652   //set plugin name
03653   info->name = malloc(sizeof(char) * 40);
03654   if (info->name != NULL)
03655   {
03656     snprintf(info->name, 39, "mp3 (libmad)");
03657   }
03658   else
03659   {
03660     *error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
03661     return;
03662   }
03663 
03664   //set plugin extension
03665   info->extension = malloc(sizeof(char) * (strlen(SPLT_MP3EXT)+2));
03666   if (info->extension != NULL)
03667   {
03668     snprintf(info->extension, strlen(SPLT_MP3EXT)+1, SPLT_MP3EXT);
03669   }
03670   else
03671   {
03672     *error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
03673     return;
03674   }
03675 
03676   info->upper_extension = splt_su_convert(info->extension, SPLT_TO_UPPERCASE, error);
03677 }
03678 
03680 void splt_pl_init(splt_state *state, int *error)
03681 {
03682   if (splt_io_input_is_stdin(state))
03683   {
03684     char *filename = splt_t_get_filename_to_split(state);
03685     if (filename[1] == '\0')
03686     {
03687       splt_c_put_info_message_to_client(state, 
03688           _(" warning: stdin '-' is supposed to be mp3 stream.\n"));
03689     }
03690   }
03691 
03692   splt_mp3_init(state, error);
03693 }
03694 
03696 void splt_pl_end(splt_state *state, int *error)
03697 {
03698   //put infos about the frames processed and the number of sync errors
03699   //ONLY if framemode
03700   if ((splt_o_get_int_option(state, SPLT_OPT_SPLIT_MODE) != SPLT_OPTION_SILENCE_MODE)
03701       && (splt_o_get_int_option(state, SPLT_OPT_SPLIT_MODE) != SPLT_OPTION_ERROR_MODE)
03702       && (splt_o_get_int_option(state, SPLT_OPT_SPLIT_MODE) != SPLT_OPTION_WRAP_MODE))
03703   {
03704     if (splt_o_get_int_option(state, SPLT_OPT_FRAME_MODE))
03705     {
03706       if (*error >= 0)
03707       {
03708         splt_mp3_state *mp3state = state->codec;
03709         //-if we don't save the end point, the ->frames are set to 1 at the
03710         //end of the split
03711         if (mp3state->frames != 1)
03712         {
03713           splt_c_put_info_message_to_client(state, 
03714               _(" Processed %lu frames - Sync errors: %lu\n"),
03715               mp3state->frames, state->syncerrors);
03716         }
03717       }
03718     }
03719   }
03720   splt_mp3_end(state, error);
03721 }
03722 
03724 int splt_pl_check_plugin_is_for_file(splt_state *state, int *error)
03725 {
03726   char *filename = splt_t_get_filename_to_split(state);
03727 
03728   if (filename != NULL && ((strcmp(filename,"-") == 0) ||
03729       (strcmp(filename,"m-") == 0)))
03730   {
03731     return SPLT_TRUE;
03732   }
03733 
03734   int is_mp3 = SPLT_FALSE;
03735 
03736   splt_o_lock_messages(state);
03737   splt_mp3_init(state, error);
03738   splt_o_unlock_messages(state);
03739   if (*error >= 0)
03740   {
03741     splt_mp3_state *mp3state = state->codec;
03742     if (mp3state)
03743     {
03744       is_mp3 = SPLT_TRUE;
03745     }
03746   }
03747   splt_mp3_end(state, error);
03748  
03749   return is_mp3;
03750 }
03751 
03753 void splt_pl_search_syncerrors(splt_state *state, int *error)
03754 {
03755   //we detect sync errors
03756   splt_mp3_syncerror_search(state, error);
03757 }
03758 
03760 void splt_pl_dewrap(splt_state *state, int listonly, const char *dir, int *error)
03761 {
03762   splt_w_wrap_free(state);
03763   splt_mp3_dewrap(listonly, dir, error, state);
03764 }
03765 
03766 double splt_pl_split(splt_state *state, const char *final_fname,
03767     double begin_point, double end_point, int *error, int save_end_point)
03768 {
03769   return splt_mp3_split(final_fname, state, begin_point, end_point, error, save_end_point);
03770 }
03771 
03773 int splt_pl_simple_split(splt_state *state, char *output_fname, off_t begin, off_t end)
03774 {
03775   int error = SPLT_OK;
03776 
03777   splt_mp3_state *mp3state = state->codec;
03778 
03779   //we initialise frames to 1
03780   if (splt_t_get_total_time(state) > 0)
03781   {
03782     mp3state->frames = 1;
03783   }
03784 
03785   //effective mp3 split
03786   error = splt_mp3_simple_split(state, output_fname, begin, end,
03787       SPLT_FALSE, SPLT_FALSE);
03788 
03789   return error;
03790 }
03791 
03793 int splt_pl_scan_silence(splt_state *state, int *error)
03794 {
03795   float offset = splt_o_get_float_option(state,SPLT_OPT_PARAM_OFFSET);
03796   float threshold = splt_o_get_float_option(state, SPLT_OPT_PARAM_THRESHOLD);
03797   float min_length = splt_o_get_float_option(state, SPLT_OPT_PARAM_MIN_LENGTH);
03798   int found = 0;
03799 
03800   splt_mp3_state *mp3state = state->codec;
03801   mp3state->off = offset;
03802 
03803   found = splt_mp3_scan_silence(state, mp3state->mp3file.firsthead.ptr, 0,
03804       threshold, min_length, 1, error);
03805 
03806   return found;
03807 }
03808 
03810 void splt_pl_set_original_tags(splt_state *state, int *error)
03811 {
03812   splt_d_print_debug(state, "Getting original tags ...");
03813 #ifndef NO_ID3TAG
03814   splt_d_print_debug(state, "Taking original ID3 tags from file using libid3tag ...\n");
03815   splt_mp3_get_original_tags(splt_t_get_filename_to_split(state), state, error);
03816 #else
03817   splt_d_print_debug(state, "Warning ! NO_ID3TAG");
03818   //splt_e_error(SPLT_IERROR_SET_ORIGINAL_TAGS,__func__, 0, NULL);
03819 #endif
03820 }
03821