libmp3splt
src/cddb.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, USA.
00025  *********************************************************/
00026 
00031 #include <string.h>
00032 #include <ctype.h>
00033 #include <math.h>
00034 
00035 #include "splt.h"
00036 #include "cddb_cue_common.h"
00037 
00038 #include "cddb.h"
00039 
00040 static void splt_cddb_process_line(char **l, cddb_utils *cdu, splt_state *state);
00041 static void splt_cddb_process_disc_length_line(const char *line_content, cddb_utils *cdu, splt_state *state);
00042 static void splt_cddb_convert_points(cddb_utils *cdu, splt_state *state);
00043 static void splt_cddb_process_offset_line(const char *line_content, cddb_utils *cdu, splt_state *state);
00044 static cddb_utils *splt_cddb_cdu_new(splt_state *state, int *error);
00045 static void splt_cddb_cdu_free(cddb_utils **cdu);
00046 static void splt_cddb_process_year_line(const char *line_content,
00047     cddb_utils *cdu, splt_state *state);
00048 static void splt_cddb_process_genre_line(char *line_content, cddb_utils *cdu, splt_state *state);
00049 static void splt_cddb_process_dtitle_line(const char *line_content, cddb_utils *cdu, splt_state *state);
00050 static void splt_cddb_process_ttitle_line(const char *line_content, cddb_utils *cdu, splt_state *state);
00051 static void splt_cddb_process_id3g_line(const char *line_content, cddb_utils *cdu, splt_state *state);
00052 
00053 int splt_cddb_put_splitpoints(const char *file, splt_state *state, int *error)
00054 {
00055   if (file == NULL)
00056   {
00057     *error = SPLT_INVALID_CDDB_FILE;
00058     return 0;
00059   }
00060 
00061   splt_c_put_info_message_to_client(state, 
00062       _(" reading informations from CDDB file %s ...\n"),file);
00063 
00064   splt_t_free_splitpoints_tags(state);
00065 
00066   *error = SPLT_CDDB_OK;
00067 
00068   int err = SPLT_OK;
00069   FILE *file_input = NULL;
00070   char *line = NULL;
00071   int tracks = 0;
00072 
00073   cddb_utils *cdu = splt_cddb_cdu_new(state, &err);
00074   if (err < 0) { *error = err; return tracks; }
00075   cdu->file = file;
00076 
00077   if (!(file_input=splt_io_fopen(file, "r")))
00078   {
00079     splt_e_set_strerror_msg_with_data(state, file);
00080     *error = SPLT_ERROR_CANNOT_OPEN_FILE;
00081     return tracks;
00082   }
00083 
00084   if (fseek(file_input, 0, SEEK_SET) != 0)
00085   {
00086     splt_e_set_strerror_msg_with_data(state, file);
00087     *error = SPLT_ERROR_SEEKING_FILE;
00088     goto function_end;
00089   }
00090 
00091   err = splt_tu_set_tags_field(state, 0, SPLT_TAGS_GENRE, SPLT_UNDEFINED_GENRE);
00092   if (err < 0) { *error = err; goto function_end; }
00093  
00094   while ((line = splt_io_readline(file_input, error)) != NULL)
00095   {
00096     if (*error < 0) { goto function_end; }
00097 
00098     splt_cddb_process_line(&line, cdu, state);
00099     tracks = cdu->tracks;
00100     if (cdu->error < 0) { *error = cdu->error; goto function_end; }
00101   }
00102 
00103   splt_cc_put_filenames_from_tags(state, tracks, error);
00104 
00105 function_end:
00106   splt_cddb_cdu_free(&cdu);
00107 
00108   if (line)
00109   {
00110     free(line);
00111     line = NULL;
00112   }
00113 
00114   if (fclose(file_input) != 0)
00115   {
00116     splt_e_set_strerror_msg_with_data(state, file);
00117     *error = SPLT_ERROR_CANNOT_CLOSE_FILE;
00118   }
00119   file_input = NULL;
00120 
00121   if (*error >= 0)
00122   {
00123     splt_c_put_info_message_to_client(state, _("  Tracks: %d\n\n"), tracks);
00124   }
00125 
00126   return tracks;
00127 }
00128 
00129 static void splt_cddb_process_line(char **l, cddb_utils *cdu, splt_state *state)
00130 {
00131   if (!l || !*l) { return; }
00132 
00133   char *line = *l;
00134 
00135   splt_su_line_to_unix(line);
00136   splt_su_str_cut_last_char(line);
00137 
00138   char *line_content = NULL;
00139   if ((line_content = strstr(line, "Track frame offset")) != NULL)
00140   {
00141     cdu->read_offsets = SPLT_TRUE;
00142   }
00143   else if ((line_content = strstr(line, "Disc length")) != NULL)
00144   {
00145     splt_cddb_process_disc_length_line(line_content, cdu, state);
00146   }
00147   else if (cdu->read_offsets)
00148   {
00149     splt_cddb_process_offset_line(line, cdu, state);
00150   }
00151   else if ((line_content = strstr(line, "YEAR")) != NULL)
00152   {
00153     splt_cddb_process_year_line(line_content, cdu, state);
00154   }
00155   else if ((line_content = strstr(line, "GENRE")) != NULL)
00156   {
00157     splt_cddb_process_genre_line(line_content, cdu, state);
00158   }
00159   else if ((line_content = strstr(line, "DTITLE")) != NULL)
00160   {
00161     splt_cddb_process_dtitle_line(line_content, cdu, state);
00162   }
00163   else if ((line_content = strstr(line, "TTITLE")) != NULL)
00164   {
00165     splt_cddb_process_ttitle_line(line_content, cdu, state);
00166   }
00167   else if ((line_content = strstr(line, "ID3G")) != NULL)
00168   {
00169     splt_cddb_process_id3g_line(line_content, cdu, state);
00170   }
00171 
00172   free(*l);
00173   *l = NULL;
00174 }
00175 
00176 static void splt_cddb_process_id3g_line(const char *line_content, cddb_utils *cdu, splt_state *state)
00177 {
00178   int err = SPLT_OK;
00179 
00180   int id3g = atoi(line_content + 6);
00181   if (id3g < SPLT_ID3V1_NUMBER_OF_GENRES)
00182   {
00183     err = splt_tu_set_tags_field(state, 0, SPLT_TAGS_GENRE, splt_id3v1_genres[id3g]);
00184     if (err < 0) { cdu->error = err; return; }
00185   }
00186 }
00187 
00188 static void splt_cddb_process_ttitle_line(const char *line_content, cddb_utils *cdu, splt_state *state)
00189 {
00190   int err = SPLT_OK;
00191 
00192   int index = atoi(line_content+6);
00193 
00194   char *equal_ptr = NULL;
00195   if ((equal_ptr = strchr(line_content, '=')) == NULL) 
00196   {
00197     splt_e_set_error_data(state, cdu->file);
00198     cdu->error = SPLT_INVALID_CDDB_FILE;
00199     return;
00200   }
00201 
00202   if (equal_ptr == line_content)
00203   {
00204     splt_e_set_error_data(state, cdu->file);
00205     cdu->error = SPLT_INVALID_CDDB_FILE;
00206     return;
00207   }
00208 
00209   char *slash = strchr(equal_ptr, '/');
00210   if (slash != NULL)
00211   {
00212     char *title = splt_su_trim_spaces(slash + 1);
00213     err = splt_tu_set_tags_field(state, index, SPLT_TAGS_TITLE, title);
00214     if (err < 0) { cdu->error = err; return; }
00215     *slash = '\0';
00216 
00217     char *performer = splt_su_trim_spaces(equal_ptr + 1);
00218    err = splt_tu_set_tags_field(state, index, SPLT_TAGS_PERFORMER, performer);
00219     if (err < 0) { cdu->error = err; return; }
00220   }
00221   else
00222   {
00223     char *title = splt_su_trim_spaces(equal_ptr + 1);
00224     err = splt_tu_set_tags_field(state, index, SPLT_TAGS_TITLE, title);
00225     if (err < 0) { cdu->error = err; return; }
00226   }
00227 }
00228 
00229 static void splt_cddb_process_dtitle_line(const char *line_content, cddb_utils *cdu, splt_state *state)
00230 {
00231   int err = SPLT_OK;
00232 
00233   char *equal_ptr = NULL;
00234   if ((equal_ptr = strchr(line_content, '=')) == NULL) 
00235   {
00236     splt_e_set_error_data(state, cdu->file);
00237     cdu->error = SPLT_INVALID_CDDB_FILE;
00238     return;
00239   }
00240 
00241   int we_have_album = SPLT_FALSE;
00242 
00243   char *slash = strchr(equal_ptr, '/');
00244   if (slash != NULL)
00245   {
00246     char *album = splt_su_trim_spaces(slash + 1);
00247     err = splt_tu_set_tags_field(state, 0, SPLT_TAGS_ALBUM, album);
00248     if (err < 0) { cdu->error = err; return; }
00249     *slash = '\0';
00250     we_have_album = SPLT_TRUE;
00251   }
00252 
00253   char *artist = splt_su_trim_spaces(equal_ptr + 1);
00254   err = splt_tu_set_tags_field(state, 0, SPLT_TAGS_ARTIST, artist);
00255   if (err < 0) { cdu->error = err; return; }
00256 
00257   splt_c_put_info_message_to_client(state, _("\n  Artist: %s\n"), artist);
00258   if (we_have_album)
00259   {
00260     splt_c_put_info_message_to_client(state, _("  Album: %s\n"), 
00261         splt_tu_get_tags_field(state, 0, SPLT_TAGS_ALBUM));
00262   }
00263 }
00264 
00265 static void splt_cddb_process_genre_line(char *line_content, cddb_utils *cdu, splt_state *state)
00266 {
00267   char *genre = line_content + 6;
00268   splt_su_cut_spaces_from_end(genre);
00269 
00270   if (*genre == '\0')
00271   {
00272     return;
00273   }
00274 
00275   int err = splt_tu_set_tags_field(state, 0, SPLT_TAGS_GENRE, genre);
00276   if (err < 0) { cdu->error = err; }
00277 }
00278 
00279 static void splt_cddb_process_year_line(const char *line_content,
00280     cddb_utils *cdu, splt_state *state)
00281 {
00282   int err = splt_tu_set_tags_field(state, 0, SPLT_TAGS_YEAR, line_content+5);
00283   if (err < 0) { cdu->error = err; }
00284 }
00285 
00286 static void splt_cddb_process_disc_length_line(const char *line_content,
00287     cddb_utils *cdu, splt_state *state)
00288 {
00289   int err = SPLT_OK;
00290 
00291   cdu->read_offsets = SPLT_FALSE;
00292 
00293   splt_t_set_splitnumber(state, cdu->tracks);
00294   splt_t_clean_split_data(state, cdu->tracks);
00295 
00296   double value = splt_su_str_line_to_double(line_content);
00297   err = splt_sp_append_splitpoint(state, value * 100, NULL, SPLT_SPLITPOINT);
00298 
00299   if (err < 0) { cdu->error = err; return; }
00300 
00301   splt_cddb_convert_points(cdu, state);
00302 }
00303 
00304 static void splt_cddb_convert_points(cddb_utils *cdu, splt_state *state)
00305 {
00306   int err = SPLT_OK;
00307 
00308   long first_point = splt_sp_get_splitpoint_value(state, 0, &err);
00309   if (err < 0) { cdu->error = err; return; }
00310 
00311   int i = 0;
00312   for (i = cdu->tracks - 1; i >= 0; i--)
00313   {
00314     long point = splt_sp_get_splitpoint_value(state, i, &err);
00315     if (err < 0) { cdu->error = err; return; }
00316 
00317     //cddb specs
00318     long difference = point - first_point;
00319     float value = (float) difference / 75.f;
00320     err = splt_sp_set_splitpoint_value(state, i, (long) ceilf(value));
00321     if (err < 0) { cdu->error = err; return; }
00322   }
00323 }
00324 
00325 static void splt_cddb_process_offset_line(const char *line, 
00326     cddb_utils *cdu, splt_state *state)
00327 {
00328   if (splt_su_str_line_has_digit(line))
00329   {
00330     int err = SPLT_OK;
00331 
00332     double value = splt_su_str_line_to_double(line);
00333     err = splt_sp_append_splitpoint(state, value * 100, NULL, SPLT_SPLITPOINT);
00334 
00335     if (err < 0) { cdu->error = err; return; }
00336 
00337     cdu->tracks++;
00338   }
00339 }
00340 
00341 static cddb_utils *splt_cddb_cdu_new(splt_state *state, int *error)
00342 {
00343   cddb_utils *cdu = malloc(sizeof(cddb_utils));
00344   if (cdu == NULL)
00345   {
00346     *error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
00347     return NULL;
00348   }
00349 
00350   cdu->read_offsets = SPLT_FALSE;
00351   cdu->error = SPLT_OK;
00352   cdu->tracks = 0;
00353   cdu->file = NULL;
00354   cdu->field_counter = 0;
00355 
00356   return cdu;
00357 }
00358 
00359 static void splt_cddb_cdu_free(cddb_utils **cdu)
00360 {
00361   if (!cdu || !*cdu)
00362   {
00363     return;
00364   }
00365 
00366   free(*cdu);
00367   *cdu = NULL;
00368 }
00369