libmp3splt
src/checks.c
00001 /**********************************************************
00002  *
00003  * libmp3splt -- library based on mp3splt,
00004  *               for mp3/ogg splitting without decoding
00005  *
00006  * Copyright (c) 2002-2005 M. Trotta - <mtrotta@users.sourceforge.net>
00007  * Copyright (c) 2005-2011 Alexandru Munteanu - io_fx@yahoo.fr
00008  *
00009  * http://mp3splt.sourceforge.net
00010  *
00011  *********************************************************/
00012 
00013 /**********************************************************
00014  *
00015  * This program is free software; you can redistribute it and/or
00016  * modify it under the terms of the GNU General Public License
00017  * as published by the Free Software Foundation; either version 2
00018  * of the License, or (at your option) any later version.
00019  *
00020  * This program is distributed in the hope that it will be useful,
00021  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00022  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023  * GNU General Public License for more details.
00024  *
00025  * You should have received a copy of the GNU General Public License
00026  * along with this program; if not, write to the Free Software
00027  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
00028  * 02111-1307,
00029  * USA.
00030  *
00031  *********************************************************/
00032 
00033 #include <sys/stat.h>
00034 #include <string.h>
00035 
00036 #include "splt.h"
00037 
00038 #ifdef __WIN32__
00039 #include "windows.h"
00040 #endif
00041 
00042 static void close_files(splt_state *state, const char *file1, FILE **f1,
00043     const char *file2, FILE **f2, int *error);
00044 
00045 void splt_check_points_inf_song_length(splt_state *state, int *error)
00046 {
00047   if (splt_io_input_is_stdin(state))
00048   {
00049     return;
00050   }
00051 
00052   int splitnumber = splt_t_get_splitnumber(state);
00053   if (splitnumber < 1)
00054   {
00055     return;
00056   }
00057 
00058   int err = SPLT_OK;
00059   int found_max_splitpoint = SPLT_FALSE;
00060   long total_time = splt_t_get_total_time(state);
00061 
00062   int i = 0;
00063   for (i = 0; i < splitnumber - 1; i++)
00064   {
00065     long splitpoint_value = splt_sp_get_splitpoint_value(state, i, &err);
00066     if (err < SPLT_OK) { *error = err; return; }
00067 
00068     if (splitpoint_value > total_time)
00069     {
00070       found_max_splitpoint = SPLT_TRUE;
00071       splt_t_set_splitnumber(state, i+1);
00072 
00073       *error = SPLT_SPLITPOINT_BIGGER_THAN_LENGTH;
00074       splt_e_set_error_data_from_splitpoint(state, splitpoint_value);
00075       splt_sp_set_splitpoint_value(state, i, total_time);
00076 
00077       break;
00078     }
00079   }
00080 }
00081 
00082 void splt_check_if_points_in_order(splt_state *state, int *error)
00083 {
00084   int splitnumber = splt_t_get_splitnumber(state);
00085   if (splitnumber < 1)
00086   {
00087     return;
00088   }
00089 
00090   int err = SPLT_OK;
00091   int i = 0;
00092   for (i = 0; i < (splitnumber-1); i++)
00093   {
00094     long splitpoint_value = splt_sp_get_splitpoint_value(state, i, &err);
00095     if (err != SPLT_OK) { *error = err; return; }
00096     long next_splitpoint_value = splt_sp_get_splitpoint_value(state, i+1, &err);
00097     if (err != SPLT_OK) { *error = err; return; }
00098 
00099     if (splitpoint_value < 0)
00100     {
00101       splt_e_set_error_data_from_splitpoint(state, splitpoint_value);
00102       *error = SPLT_ERROR_NEGATIVE_SPLITPOINT;
00103       return;
00104     }
00105 
00106     if (splitpoint_value == LONG_MAX)
00107     {
00108       splt_sp_set_splitpoint_value(state, i, splt_t_get_total_time(state));
00109     }
00110 
00111     if (splitpoint_value > next_splitpoint_value) 
00112     {
00113       splt_e_set_error_data_from_splitpoints(state,
00114           splitpoint_value, next_splitpoint_value);
00115       *error = SPLT_ERROR_SPLITPOINTS_NOT_IN_ORDER;
00116       return;
00117     }
00118 
00119     if (splitpoint_value == next_splitpoint_value)
00120     {
00121       splt_e_set_error_data_from_splitpoint(state, splitpoint_value);
00122       *error = SPLT_ERROR_EQUAL_SPLITPOINTS;
00123       return;
00124     }
00125   }
00126 }
00127 
00128 void splt_check_if_fname_path_is_correct(splt_state *state,
00129     const char *fname_path, int *error)
00130 {
00131   splt_d_print_debug(state,"Check if the new filename path is correct _%s_\n",fname_path);
00132 
00133   char current_directory[4] = { '\0' };
00134   snprintf(current_directory, 4, "%c%c", '.', SPLT_DIRCHAR);
00135 
00136   if ((strcmp(fname_path, "") != 0) &&
00137       (strcmp(fname_path, current_directory) != 0))
00138   {
00139     if (!splt_io_check_if_directory(fname_path))
00140     {
00141       splt_e_set_strerr_msg_with_data(state,
00142           _("directory does not exists"), fname_path);
00143       *error = SPLT_ERROR_INCORRECT_PATH;
00144     }
00145   }
00146 }
00147 
00148 char *splt_check_put_dir_of_cur_song(const char *filename,
00149     const char *path, int *error)
00150 {
00151   int err = SPLT_OK;
00152   char *filename_path = NULL;
00153 
00154   if (path == NULL || path[0] == '\0')
00155   {
00156     err = splt_su_copy(filename, &filename_path);
00157     if (err < 0) { *error = err; return NULL; }
00158 
00159     char *c = strrchr(filename_path, SPLT_DIRCHAR);
00160     if (c == NULL)
00161     {
00162       filename_path[0] = '\0';
00163       return filename_path;
00164     }
00165 
00166     *(c+1) = '\0';
00167     return filename_path;
00168   }
00169 
00170   err = splt_su_copy(path, &filename_path);
00171   if (err < 0) { *error = err; return NULL; }
00172 
00173   return filename_path;
00174 }
00175 
00176 int splt_check_compatible_options(splt_state *state)
00177 {
00178   return SPLT_TRUE;
00179 }
00180 
00181 void splt_check_set_correct_options(splt_state *state)
00182 {
00183   splt_d_print_debug(state,"Check and set correct options...\n");
00184 
00185   int split_mode = splt_o_get_int_option(state,SPLT_OPT_SPLIT_MODE);
00186 
00187   if (( split_mode == SPLT_OPTION_SILENCE_MODE)
00188       || splt_o_get_int_option(state,SPLT_OPT_AUTO_ADJUST))
00189   {
00190     splt_o_set_int_option(state, SPLT_OPT_FRAME_MODE, SPLT_OPT_FRAME_MODE);
00191 
00192     if  ((splt_o_get_float_option(state,SPLT_OPT_PARAM_THRESHOLD) < -96.f) || 
00193         (splt_o_get_float_option(state,SPLT_OPT_PARAM_THRESHOLD) > 0.f))
00194     {
00195       splt_o_set_float_option(state,SPLT_OPT_PARAM_THRESHOLD, SPLT_DEFAULT_PARAM_THRESHOLD);
00196     }
00197 
00198     if  ((splt_o_get_float_option(state,SPLT_OPT_PARAM_OFFSET) < -2.f) || 
00199         (splt_o_get_float_option(state,SPLT_OPT_PARAM_OFFSET) > 2.f))
00200     {
00201       splt_o_set_float_option(state,SPLT_OPT_PARAM_OFFSET, SPLT_DEFAULT_PARAM_OFFSET);
00202     }
00203 
00204     if (splt_o_get_int_option(state,SPLT_OPT_PARAM_GAP) < 0)
00205     {
00206       splt_o_set_int_option(state,SPLT_OPT_PARAM_GAP, SPLT_DEFAULT_PARAM_GAP);
00207     }
00208 
00209     if (splt_o_get_float_option(state,SPLT_OPT_PARAM_MIN_LENGTH) < 0.f)
00210     {
00211       splt_o_set_float_option(state, SPLT_OPT_PARAM_MIN_LENGTH, SPLT_DEFAULT_PARAM_MINIMUM_LENGTH);
00212       splt_o_set_int_option(state, SPLT_OPT_AUTO_ADJUST, SPLT_FALSE);
00213     }
00214   }
00215 
00216   if (!splt_o_get_int_option(state,SPLT_OPT_AUTO_ADJUST))
00217   {
00218     splt_o_set_int_option(state,SPLT_OPT_PARAM_GAP, 0);
00219   }
00220 
00221   if ((splt_o_get_int_option(state,SPLT_OPT_INPUT_NOT_SEEKABLE)) &&
00222       (splt_o_get_int_option(state,SPLT_OPT_AUTO_ADJUST) ||
00223        (split_mode == SPLT_OPTION_SILENCE_MODE) ||
00224        (split_mode == SPLT_OPTION_ERROR_MODE) ||
00225        (split_mode == SPLT_OPTION_WRAP_MODE)))
00226   {
00227     splt_o_set_int_option(state, SPLT_OPT_INPUT_NOT_SEEKABLE, SPLT_FALSE);
00228   }
00229 }
00230 
00231 void splt_check_file_type(splt_state *state, int *error)
00232 {
00233   int err = SPLT_OK;
00234 
00235   splt_d_print_debug(state,"Detecting file format...\n");
00236   const char *filename = splt_t_get_filename_to_split(state);
00237 
00238   splt_d_print_debug(state,"Checking the format of _%s_\n", filename);
00239 
00240   splt_plugins *pl = state->plug;
00241   int plugin_found = SPLT_FALSE;
00242   int i = 0;
00243   for (i = 0;i < pl->number_of_plugins_found;i++)
00244   {
00245     splt_p_set_current_plugin(state, i);
00246     err = SPLT_OK;
00247 
00248     if (splt_o_get_int_option(state, SPLT_OPT_INPUT_NOT_SEEKABLE) &&
00249         ! splt_io_input_is_stdin(state))
00250     {
00251       const char *extension = splt_p_get_extension(state, &err);
00252       const char *upper_extension = splt_p_get_extension(state, &err);
00253       if (err == SPLT_OK)
00254       {
00255         if (splt_su_str_ends_with(filename, extension) ||
00256             splt_su_str_ends_with(filename, upper_extension))
00257         {
00258           plugin_found = SPLT_TRUE;
00259           break;
00260         }
00261       }
00262     }
00263     else
00264     {
00265       if (splt_p_check_plugin_is_for_file(state, &err))
00266       {
00267         if (err == SPLT_OK)
00268         {
00269           plugin_found = SPLT_TRUE;
00270           break;
00271         }
00272       }
00273     }
00274   }
00275 
00276   if (! plugin_found)
00277   {
00278     splt_e_set_error_data(state, filename);
00279     *error = SPLT_ERROR_NO_PLUGIN_FOUND_FOR_FILE;
00280     splt_d_print_debug(state,"No plugin found !\n");
00281     splt_d_print_debug(state,"Verifying if the file _%s_ is a file ...\n", filename);
00282 
00283     FILE *test = NULL;
00284     if ((test = splt_io_fopen(filename,"r")) == NULL)
00285     {
00286       splt_e_set_strerror_msg_with_data(state, filename);
00287       *error = SPLT_ERROR_CANNOT_OPEN_FILE;
00288       return;
00289     }
00290 
00291     if (fclose(test) != 0)
00292     {
00293       splt_e_set_strerror_msg_with_data(state, filename);
00294       *error = SPLT_ERROR_CANNOT_CLOSE_FILE;
00295       return;
00296     }
00297   }
00298 }
00299 
00300 int splt_check_is_the_same_file(splt_state *state, const char *file1,
00301     const char *file2, int *error)
00302 {
00303   if (file1 == NULL || file2 == NULL)
00304   {
00305     return SPLT_FALSE;
00306   }
00307 
00308   FILE *file1_ = NULL;
00309   FILE *file2_ = NULL;
00310 
00311   if (file1[strlen(file1) - 1] == '-')
00312   {
00313     return SPLT_FALSE;
00314   }
00315 
00316   splt_d_print_debug(state,"Checking if _%s_ is like _%s_ \n", file1, file2);
00317 
00318   int is_file1 = splt_io_check_if_file(state, file1);
00319   int is_file2 = splt_io_check_if_file(state, file2);
00320   if (!is_file1 || !is_file2)
00321   {
00322     return SPLT_FALSE;
00323   }
00324 
00325   if ((file1_ = splt_io_fopen(file1,"r")) == NULL)
00326   {
00327     goto end;
00328   }
00329 
00330   if ((file2_ = splt_io_fopen(file2,"r")) == NULL)
00331   {
00332     goto end;
00333   }
00334 
00335   //mingw for windows returns 0 as inode and 0 as device
00336   //when using the fstat function.
00337 #ifdef __WIN32__
00338   BY_HANDLE_FILE_INFORMATION handle_info_file1;
00339   BY_HANDLE_FILE_INFORMATION handle_info_file2;
00340   int file1_d = fileno(file1_);
00341   int file2_d = fileno(file2_);
00342 
00343   if (!GetFileInformationByHandle((HANDLE)_get_osfhandle(file1_d), &handle_info_file1))
00344   {
00345     goto end;
00346   }
00347   if (!GetFileInformationByHandle((HANDLE)_get_osfhandle(file2_d), &handle_info_file2))
00348   {
00349     goto end;
00350   }
00351 
00352   if ((handle_info_file1.nFileIndexHigh == handle_info_file2.nFileIndexHigh)&&
00353       (handle_info_file1.nFileIndexLow == handle_info_file2.nFileIndexLow))
00354   {
00355     close_files(state, file1, &file1_,file2, &file2_,error);
00356     return SPLT_TRUE;
00357   }
00358 #else
00359   int file1_d = fileno(file1_);
00360   struct stat file1_stat;
00361   if (fstat(file1_d, &file1_stat) != 0)
00362   {
00363     goto end;
00364   }
00365 
00366   int file2_d = fileno(file2_);
00367   struct stat file2_stat;
00368   if (fstat(file2_d,&file2_stat) != 0)
00369   {
00370     goto end;
00371   }
00372 
00373   if ((file1_stat.st_ino == file2_stat.st_ino) &&
00374       (file1_stat.st_dev == file2_stat.st_dev))
00375   {
00376     close_files(state, file1, &file1_,file2, &file2_,error);
00377     return SPLT_TRUE;
00378   }
00379 #endif
00380 
00381 end:
00382   close_files(state, file1, &file1_,file2, &file2_,error);
00383 
00384   return SPLT_FALSE;
00385 }
00386 
00387 static void close_files(splt_state *state, const char *file1, FILE **f1,
00388     const char *file2, FILE **f2, int *error)
00389 {
00390   if (*f1)
00391   {
00392     if (fclose(*f1) != 0)
00393     {
00394       splt_e_set_strerror_msg_with_data(state, file1);
00395       *error = SPLT_ERROR_CANNOT_CLOSE_FILE;
00396     }
00397     else
00398     {
00399       *f1 = NULL;
00400     }
00401   }
00402 
00403   if (*f2)
00404   {
00405     if (fclose(*f2) != 0)
00406     {
00407       splt_e_set_strerror_msg_with_data(state, file2);
00408       *error = SPLT_ERROR_CANNOT_CLOSE_FILE;
00409     }
00410     else
00411     {
00412       *f2 = NULL;
00413     }
00414   }
00415 }
00416