libmp3splt
src/filename_regex.c
00001 /**********************************************************
00002  *
00003  * libmp3splt -- library based on mp3splt,
00004  *               for mp3/ogg splitting without decoding
00005  *
00006  * Copyright (c) 2010-2011 Alexandru Munteanu - io_fx@yahoo.fr
00007  *
00008  * http://mp3splt.sourceforge.net
00009  *
00010  *********************************************************/
00011 
00012 /**********************************************************
00013  *
00014  * This program is free software; you can redistribute it and/or
00015  * modify it under the terms of the GNU General Public License
00016  * as published by the Free Software Foundation; either version 2
00017  * of the License, or (at your option) any later version.
00018  *
00019  * This program is distributed in the hope that it will be useful,
00020  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00021  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00022  * GNU General Public License for more details.
00023  *
00024  * You should have received a copy of the GNU General Public License
00025  * along with this program; if not, write to the Free Software
00026  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
00027  * 02111-1307,
00028  * USA.
00029  *
00030  *********************************************************/
00031 
00032 #ifndef NO_PCRE
00033 
00034 #include <string.h>
00035 #include <pcre.h>
00036 
00037 #include "splt.h"
00038 
00039 static char *splt_fr_get_pattern(pcre *re, const char *filename, int *ovector,
00040     int rc, char *key);
00041 static void splt_fr_copy_pattern_to_tags(pcre *re, const char *filename, 
00042     int *ovector, int rc, char *key, int tags_field, splt_tags *tags,
00043     int format, int replace_underscores, int *error);
00044 static int splt_fr_get_int_pattern(pcre *re, const char *filename, 
00045     int *ovector, int rc, char *key);
00046 static void splt_fr_set_char_field_on_tags_and_convert(splt_tags *tags,
00047     int tags_field, char *pattern, int format, int replace_underscores, int *error);
00048 
00054 splt_tags *splt_fr_parse_from_state(splt_state *state, int *error)
00055 {
00056   const char *filename_to_split = splt_t_get_filename_to_split(state);
00057   char *regex = splt_t_get_input_filename_regex(state);
00058   char *default_comment = splt_t_get_default_comment_tag(state);
00059   char *default_genre = splt_t_get_default_genre_tag(state);
00060 
00061   char *filename = splt_su_get_fname_without_path_and_extension(filename_to_split, error);
00062   if (*error < 0)
00063   {
00064     return NULL;
00065   }
00066 
00067   splt_tags *tags = splt_fr_parse(state, filename, regex, default_comment, default_genre, error);
00068 
00069   if (filename)
00070   {
00071     free(filename);
00072     filename = NULL;
00073   }
00074 
00075   return tags;
00076 }
00077 
00078 splt_tags *splt_fr_parse(splt_state *state, const char *filename, const char *regex,
00079     const char *default_comment, const char *default_genre, int *error)
00080 {
00081   const char *errorbits;
00082   int erroroffset;
00083 
00084   splt_d_print_debug(state, "filename for regex = _%s_\n", filename);
00085   splt_d_print_debug(state, "regex = _%s_\n", regex);
00086 
00087   if (regex == NULL)
00088   {
00089     *error = SPLT_INVALID_REGEX;
00090     splt_e_set_error_data(state, _("no regular expression provided"));
00091     return NULL;
00092   }
00093 
00094   pcre *re = pcre_compile(regex, PCRE_CASELESS | PCRE_UTF8, &errorbits, &erroroffset, NULL);
00095   if (!re)
00096   {
00097     *error = SPLT_INVALID_REGEX;
00098     char *message = splt_su_get_formatted_message(state, "@%u: %s",
00099         erroroffset, errorbits);
00100     splt_e_set_error_data(state, message);
00101     return NULL;
00102   }
00103 
00104   int ovector[90] = {0,};
00105   const size_t ovsize = sizeof(ovector)/sizeof(*ovector);
00106 
00107   int rc = pcre_exec(re, NULL, filename, strlen(filename), 0, 0, ovector, ovsize);
00108   if (rc == PCRE_ERROR_NOMATCH)
00109   {
00110     *error = SPLT_REGEX_NO_MATCH;
00111     pcre_free(re);
00112     return NULL;
00113   }
00114 
00115   splt_tags *tags = splt_tu_new_tags(state, error);
00116   if (*error < 0)
00117   {
00118     pcre_free(re);
00119     return NULL;
00120   }
00121   splt_tu_reset_tags(tags);
00122 
00123   int replace_underscores = 
00124     splt_o_get_int_option(state, SPLT_OPT_REPLACE_UNDERSCORES_TAG_FORMAT);
00125 
00126   int format = splt_o_get_int_option(state, SPLT_OPT_ARTIST_TAG_FORMAT);
00127   splt_fr_copy_pattern_to_tags(re, filename, ovector, rc, "artist",
00128       SPLT_TAGS_ARTIST, tags, format, replace_underscores, error);
00129   if (*error < 0) { goto error; }
00130 
00131   format = splt_o_get_int_option(state, SPLT_OPT_ALBUM_TAG_FORMAT);
00132   splt_fr_copy_pattern_to_tags(re, filename, ovector, rc, "album",
00133       SPLT_TAGS_ALBUM, tags, format, replace_underscores, error);
00134   if (*error < 0) { goto error; }
00135 
00136   splt_fr_copy_pattern_to_tags(re, filename, ovector, rc, "year",
00137       SPLT_TAGS_YEAR, tags, SPLT_NO_CONVERSION, SPLT_FALSE, error);
00138   if (*error < 0) { goto error; }
00139 
00140   char *pattern = NULL;
00141   format = splt_o_get_int_option(state, SPLT_OPT_COMMENT_TAG_FORMAT);
00142   pattern = splt_fr_get_pattern(re, filename, ovector, rc, "comment");
00143   if (pattern)
00144   {
00145     splt_fr_set_char_field_on_tags_and_convert(tags, SPLT_TAGS_COMMENT,
00146         pattern, format, replace_underscores, error);
00147     pcre_free_substring(pattern);
00148     if (*error < 0) { goto error; }
00149   }
00150   else
00151   {
00152     splt_tu_set_field_on_tags(tags, SPLT_TAGS_COMMENT, default_comment);
00153   }
00154 
00155   int track = splt_fr_get_int_pattern(re, filename, ovector, rc, "tracknum");
00156   if (track != -1)
00157   {
00158     splt_tu_set_field_on_tags(tags, SPLT_TAGS_TRACK, &track);
00159   }
00160 
00161   //TODO: total tracks support
00162   int total_tracks = splt_fr_get_int_pattern(re, filename, ovector, rc, "tracks");
00163 
00164   format = splt_o_get_int_option(state, SPLT_OPT_TITLE_TAG_FORMAT);
00165   char *title = splt_fr_get_pattern(re, filename, ovector, rc, "title");
00166   if (title)
00167   {
00168     splt_fr_set_char_field_on_tags_and_convert(tags, SPLT_TAGS_TITLE,
00169         title, format, replace_underscores, error);
00170     pcre_free_substring(title);
00171     if (*error < 0) { goto error; }
00172   }
00173   else 
00174   {
00175     if (track != -1 && total_tracks != -1)
00176     {
00177       title = splt_su_get_formatted_message(state, "Track %d of %d", track, total_tracks);
00178     }
00179     else if (track != -1 && total_tracks == -1)
00180     {
00181       title = splt_su_get_formatted_message(state, "Track %d", track);
00182     }
00183 
00184     if (title)
00185     {
00186       splt_fr_set_char_field_on_tags_and_convert(tags, SPLT_TAGS_TITLE, title,
00187           SPLT_NO_CONVERSION, SPLT_FALSE, error);
00188 
00189       free(title);
00190       title = NULL;
00191 
00192       if (*error < 0) { goto error; }
00193     }
00194   }
00195 
00196   char *genre = splt_fr_get_pattern(re, filename, ovector, rc, "genre");
00197   if (genre)
00198   {
00199     splt_tu_set_field_on_tags(tags, SPLT_TAGS_GENRE, genre);
00200     pcre_free_substring(genre);
00201     if (*error < 0) { goto error; }
00202   }
00203   else
00204   {
00205     splt_tu_set_field_on_tags(tags, SPLT_TAGS_GENRE, default_genre);
00206   }
00207 
00208   pcre_free(re);
00209 
00210   *error = SPLT_REGEX_OK;
00211 
00212   return tags;
00213 
00214 error:
00215   pcre_free(re);
00216   splt_tu_free_one_tags(&tags); 
00217   return NULL;
00218 }
00219 
00220 static void splt_fr_copy_pattern_to_tags(pcre *re, const char *filename, 
00221     int *ovector, int rc, char *key, int tags_field, splt_tags *tags,
00222     int format, int replace_underscores, int *error)
00223 {
00224   char *pattern = NULL;
00225   pattern = splt_fr_get_pattern(re, filename, ovector, rc, key);
00226 
00227   splt_fr_set_char_field_on_tags_and_convert(tags, tags_field, pattern,
00228       format, replace_underscores, error);
00229 
00230   if (pattern)
00231   {
00232     pcre_free_substring(pattern);
00233   }
00234 }
00235 
00236 static int splt_fr_get_int_pattern(pcre *re, const char *filename, 
00237     int *ovector, int rc, char *key)
00238 {
00239   int value = -1;
00240 
00241   char *pattern = NULL;
00242   pattern = splt_fr_get_pattern(re, filename, ovector, rc, key);
00243   if (pattern)
00244   {
00245     value = atoi(pattern);
00246     pcre_free_substring(pattern);
00247   }
00248 
00249   return value;
00250 }
00251 
00252 static char *splt_fr_get_pattern(pcre *re, const char *filename, int *ovector,
00253     int rc, char *key)
00254 {
00255   char *pattern = NULL;
00256 
00257   if (pcre_get_named_substring(re, filename, ovector, rc, key,
00258         (const char**)&pattern) == PCRE_ERROR_NOSUBSTRING)
00259   {
00260     return NULL;
00261   }
00262   else
00263   {
00264     return pattern;
00265   }
00266 }
00267 
00268 static void splt_fr_set_char_field_on_tags_and_convert(splt_tags *tags,
00269     int tags_field, char *pattern, int format, int replace_underscores, int *error)
00270 {
00271   if (replace_underscores)
00272   {
00273     splt_su_replace_all_char(pattern, '_', ' ');
00274   }
00275 
00276   char *converted_pattern = splt_su_convert(pattern, format, error);
00277   if (*error < 0) { return; }
00278 
00279   splt_tu_set_field_on_tags(tags, tags_field, converted_pattern);
00280 
00281   if (converted_pattern)
00282   {
00283     free(converted_pattern);
00284     converted_pattern = NULL;
00285   }
00286 }
00287 
00288 #endif
00289