Changeset 384 for libmpc/trunk/common


Ignore:
Timestamp:
03/25/08 16:31:41 (17 years ago)
Author:
r2d
Message:
  • added mpcchap utility to add (and later dump) chapters in a sv8 mpc file
  • moved tag.c from mpcenc to common, as used by mpcchap
File:
1 moved

Legend:

Unmodified
Added
Removed
  • libmpc/trunk/common/tags.c

    r383 r384  
    2222 */
    2323
    24 #include "mpcenc.h"
     24// #include "mpcenc.h"
     25#include <stdio.h>
     26#include <mpc/mpc_types.h>
     27
     28// Path separator
     29#if defined __unix__  ||  defined __bsdi__  ||  defined __FreeBSD__  ||  defined __OpenBSD__  ||  defined __NetBSD__  ||  defined __APPLE__
     30# define PATH_SEP               '/'
     31# define DRIVE_SEP              '\0'
     32#elif defined _WIN32  ||  defined __TURBOC__  ||  defined __ZTC__  ||  defined _MSC_VER
     33# define PATH_SEP               '\\'
     34# define DRIVE_SEP              ':'
     35#else
     36# define PATH_SEP               '/'         // Amiga: C:/
     37# define DRIVE_SEP              ':'
     38#endif
    2539
    2640#ifdef USE_WIDECHAR
     
    805819}
    806820
    807 /*
    808  *  Writes collect tag items and write it to a file.
    809  *  Items are destroyed, so tags can only be written once.
     821#define TAG_NO_HEADER 1
     822#define TAG_NO_FOOTER 2
     823#define TAG_NO_PREAMBLE 4
     824
     825
     826/**
     827 * Writes collect tag items and write it to a file.
     828 * Items are destroyed, so tags can only be written once.
     829 * @param fp
     830 * @param Version
     831 * @param flags options for writing header / footer :
     832 *              1 : do not write header
     833 *              2 : do not write footer
     834 *              4 : do not write "APETAGEX"
     835 * @return
    810836 */
    811 
    812837int
    813 FinalizeTags ( FILE* fp, unsigned int Version )
     838FinalizeTags ( FILE* fp, unsigned int Version, unsigned int flags )
    814839{
    815840    static unsigned char  H [32] = "APETAGEX";
     
    821846    if ( TagCount == 0 )
    822847        return 0;
     848       
     849        if (flags & TAG_NO_PREAMBLE) {
     850                estimatedbytes -= 8;
     851                writtenbytes += 8;
     852        }
     853        if (flags & TAG_NO_FOOTER)
     854                estimatedbytes = 0;
     855        if (flags & TAG_NO_HEADER)
     856                writtenbytes = 0;
    823857
    824858    qsort ( T, TagCount, sizeof (*T), cmpfn2 );
     
    828862
    829863    if ( estimatedbytes >= 8192 + 103 )
    830         stderr_printf ( "\nTag is %.1f Kbyte long. This is longer than the maximum recommended 8 KByte.\n\a", estimatedbytes/1024. );
     864        fprintf (stderr, "\nTag is %.1f Kbyte long. This is longer than the maximum recommended 8 KByte.\n\a", estimatedbytes/1024. );
    831865
    832866    H [ 8] = Version >>  0;
     
    844878
    845879    H [23] = 0x80 | 0x20;
    846     writtenbytes += fwrite ( H, 1, 32, fp );
     880        if (!(flags & TAG_NO_HEADER)) {
     881                if (flags & TAG_NO_PREAMBLE)
     882                        writtenbytes += fwrite ( H + 8, 1, 24, fp );
     883                else
     884                writtenbytes += fwrite ( H, 1, 32, fp );
     885        }
    847886
    848887    for ( i = 0; i < TagCount; i++ ) {
     
    863902
    864903    H [23] = 0x80;
    865     writtenbytes += fwrite ( H, 1, 32, fp );
     904        if (!(flags & TAG_NO_FOOTER)) {
     905                if (flags & TAG_NO_PREAMBLE)
     906                        writtenbytes += fwrite ( H + 8, 1, 24, fp );
     907                else
     908                        writtenbytes += fwrite ( H, 1, 32, fp );
     909        }
    866910
    867911    if ( estimatedbytes != writtenbytes )
    868         stderr_printf ( "\nError writing APE tag.\n" );
     912                fprintf (stderr, "\nError writing APE tag.\n" );
    869913
    870914    TagCount = 0;
     
    915959        return -1;
    916960
    917     if ( 128 != READ ( fp, tmp, 128 ) )
     961        if ( 128 != fread(tmp, 1, 128, fp) )
    918962        return -1;
    919963
     
    9701014    if ( -1 == fseek ( fp, -(long)sizeof T, SEEK_END ) )
    9711015        return -1;
    972     if ( sizeof(T) != READ ( fp, &T, sizeof T ) )
     1016        if ( sizeof(T) != fread  (&T, 1, sizeof T, fp) )
    9731017        return -1;
    9741018    if ( memcmp ( T.ID, "APETAGEX", sizeof(T.ID) ) != 0 )
     
    9831027        return -1;
    9841028    memset ( buff, 0, sizeof(buff) );
    985     if ( TagLen - sizeof T != READ ( fp, buff, TagLen - sizeof T ) )
     1029        if ( TagLen - sizeof T != fread  (buff, 1, TagLen - sizeof T, fp) )
    9861030        return -1;
    9871031
     
    9971041
    9981042    return 0;
    999 }
    1000 
    1001 static void
    1002 FullPathName ( char* dst, size_t dstlen, const char* filename )         // Can contain stuff like ".." and "."
    1003 {
    1004     // const char*  p;
    1005     char*        q     = dst;
    1006 
    1007 #if DRIVE_SEP != '\0'
    1008     int          drive = 0;
    1009 
    1010     if ( isalpha (filename[0])  &&  filename[1] == DRIVE_SEP  &&  filename[2] != PATH_SEP ) {
    1011         drive     = filename[0] & 0x1F;
    1012         filename += 2;
    1013     }
    1014 #endif
    1015 
    1016     if ( filename[0] != PATH_SEP ) {
    1017 #ifdef _WIN32
    1018         _getdcwd( drive, dst, dstlen );
    1019 #else
    1020         getcwd ( dst, dstlen );
    1021 #endif
    1022         q += strlen (q);
    1023 #ifdef _WIN32
    1024         if ( dst[0] != PATH_SEP  ||  dst[1] != '\0' )
    1025 #else
    1026         if ( dst[2] != PATH_SEP  ||  dst[3] != '\0' )
    1027 #endif
    1028             *q++ = PATH_SEP;
    1029     }
    1030 
    1031     strcpy ( q, filename );
    1032     return;
    10331043}
    10341044
     
    10821092};
    10831093
    1084 
    1085 static void
    1086 copy ( char* dst, const char* src, size_t len )
    1087 {
    1088     memcpy ( dst, src, len );
    1089     dst [len] = '\0';
    1090 }
    1091 
    10921094/*
    10931095 *    dst[0] = Artist
     
    11031105#endif
    11041106
    1105 static int
    1106 parse ( char** dst, const char* src, const char* format )
    1107 {
    1108     int          i;
    1109     const char*  srcend = src + strlen(src);
    1110     const char*  p;
    1111     char*        q;
    1112 
    1113     for ( i = 0; i < 6; i++)
    1114         dst[i][0] = '\0';
    1115 
    1116     for ( i = strlen(format); i-- > 0; ) {
    1117         p = srcend;
    1118 #ifndef STFU
    1119         stderr_printf ( "%c: ", format[i] );
    1120 #endif
    1121         switch ( format[i] ) {
    1122         case '.':
    1123         case ' ':
    1124         case '/':                               // !!!!!!!
    1125             if (p[-1] != format[i])
    1126                 return 1;
    1127             p--;
    1128             break;
    1129         case '_':
    1130             if (0 != memcmp (p-4, " -- ", 4))
    1131                 return 1;
    1132             p -= 4;
    1133             break;
    1134         case '-':
    1135             if (0 != memcmp (p-3, " - ", 3))
    1136                 return 1;
    1137             p -= 3;
    1138             break;
    1139         case '0':
    1140             if (p[-1] != ']' || p[-2] != '0' || p[-3] != '0' || p[-4] != '[')
    1141                 return 1;
    1142             copy (dst[4], p-3, 2);
    1143             p -= 4;
    1144             break;
    1145         case 'n':
    1146             if (p[-1] != ']' || !isdigit(p[-2]) || !isdigit(p[-3]) || p[-4] != '[')
    1147                 return 1;
    1148             copy (dst[4], p-3, 2);
    1149             p -= 4;
    1150             break;
    1151         case 'M':
    1152             if ( !isdigit(p[-1]) || !isdigit(p[-2]) )
    1153                 return 1;
    1154             copy (dst[4], p-2, 2);
    1155             p -= 2;
    1156             break;
    1157         case 'N':
    1158             if (p[-1] != ')' || !isdigit(p[-2]) || p[-3] != ' ' || p[-4] != 'D' || p[-5] != 'C' || p[-6] != '(')
    1159                 return 1;
    1160             dst[3][0] = ' ';
    1161             copy (dst[3]+1, p-6, 6);
    1162             p -= 6;
    1163             break;
    1164         case 'A':
    1165             q = dst[0]; goto big;
    1166         case 'C':
    1167             q = dst[1]; goto big;
    1168         case 'T':
    1169             q = dst[2]; goto big;
    1170         big:
    1171             while ( 0 == memcmp (p-4, "/mpc", 4)  ||
    1172                     0 == memcmp (p-4, "/mp3", 4)  ||
    1173                     0 == memcmp (p-4, "/pac", 4)  ||
    1174                     0 == memcmp (p-4, "/ape", 4)  ||
    1175                     0 == memcmp (p-4, "/pac", 4)  ||
    1176                     0 == memcmp (p-3, "/.." , 3)  ||
    1177                     0 == memcmp (p-2, "/."  , 2)
    1178                   ) {
    1179                       do {
    1180                           p--;
    1181                           srcend--;
    1182                       } while ( *p != PATH_SEP );
    1183                 }
    1184             while ( p[-1] != PATH_SEP  &&
    1185                     p[-1] != DRIVE_SEP &&
    1186                     0 != memcmp (p-4, " -- ", 4 )  &&
    1187                     (p[-1] != ')' || !isdigit(p[-2]) || p[-3] != ' ' || p[-4] != 'D' || p[-5] != 'C' || p[-6] != '(')  &&
    1188                     (p[-1] != ' ' || p[-2] != ']' || !isdigit(p[-3]) || !isdigit(p[-4]) || p[-5] != '[') &&
    1189                     (p[-1] != ']' || p[-2] != '0' || p[-3] != '0' || p[-4] != '[')
    1190                   )
    1191                 p--;
    1192             copy ( q, p, srcend - p );
    1193             break;
    1194         case 'x':
    1195             do {
    1196                 p--;
    1197                 if (p[0] == PATH_SEP || p[0] == DRIVE_SEP)
    1198                     return -1;
    1199             } while (*p != '.');
    1200             copy (dst[5], p, srcend-p );
    1201             break;
    1202         }
    1203 #ifndef STFU
    1204         stderr_printf ( "%*.*s\033[7m%*.*s\033[0m\n", p-src, p-src, src, srcend-p, srcend-p, p );
    1205 #endif
    1206         srcend = p;
    1207     }
    1208     return 0;
    1209 }
    1210 
    1211 static int
    1212 hexdigit ( const char s )
    1213 {
    1214     if ( (unsigned char)(s-'0') < 10u )
    1215         return s-'0';
    1216     if ( (unsigned char)(s-'A') <  6u )
    1217         return s-'A'+10;
    1218     return -1;
    1219 }
    1220 
    1221 static void
    1222 spaceconverting ( char* dst, const char* src )          // can work inplace
    1223 {
    1224     for ( ; src[0] != '\0' ; src++) {
    1225         if      ( src[0] == '_' )
    1226             *dst++ = ' ';
    1227         else if ( src[0] == '%'  &&  hexdigit(src[1]) >= 0  &&  hexdigit(src[2]) >= 0 )
    1228             *dst++ = hexdigit(src[1]) * 16 + hexdigit(src[2]), src += 2;
    1229         else
    1230             *dst++ = *src;
    1231     }
    1232     *dst = '\0';
    1233 }
    1234 
    1235 
    1236 static int
    1237 Parser ( const char* src )
    1238 {
    1239     size_t  i;
    1240     char    tmp  [6] [1024];
    1241     char*   buff [6] = { tmp[0], tmp[1], tmp[2], tmp[3], tmp[4], tmp[5] };
    1242     char    merge [1024];
    1243     char*   q;
    1244 
    1245 #ifndef STFU
    1246     stderr_printf ( "\n  %s\n", src );
    1247 #endif
    1248 
    1249     memset ( tmp  , 0, sizeof tmp   );
    1250     memset ( merge, 0, sizeof merge );
    1251 
    1252     for ( i = 0; i < sizeof(parser_strings)/sizeof(*parser_strings); i++ ) {
    1253         if ( 0 == parse ( buff, src, parser_strings[i] ) ) {
    1254             sprintf ( merge, "%s%s", tmp[1], tmp[3] );
    1255             q = merge + strlen (merge);
    1256 
    1257             if ( q-7 >= merge  &&  q[-7]==' '  &&  q[-6]=='('  && atoi(q-5) >= 1900  &&  atoi(q-5) < 2050  &&  q[-1] == ')' ) {
    1258                 q[-1] = '\0';
    1259                 q[-7] = '\0';
    1260                 q -= 5;
    1261             }
    1262             else {
    1263                 q = NULL;
    1264             }
    1265 
    1266             spaceconverting ( tmp[0], tmp[0] );
    1267             spaceconverting ( merge , merge );
    1268             spaceconverting ( tmp[2], tmp[2] );
    1269             spaceconverting ( tmp[4], tmp[4] );
    1270             spaceconverting ( tmp[5], tmp[5] );
    1271 
    1272             stderr_printf ("\n");
    1273             stderr_printf ("Artist = %s\n", tmp[0] );
    1274             stderr_printf ("CD     = %s\n", merge  );
    1275             stderr_printf ("Title  = %s\n", tmp[2] );
    1276             stderr_printf ("No#    = %s\n", tmp[4] );
    1277             stderr_printf ("Extent = %s\n", tmp[5] );
    1278             stderr_printf ("Year   = %s\n", q  ?  q  :  "????" );
    1279 #if 1
    1280             if ( tmp[0][0]  &&  ! TagKeyExists ( "Artist", 0 ) ) addtag ( "Artist", 0, tmp[0], strlen (tmp[0]), 5, 0 );
    1281             if ( merge[0]   &&  ! TagKeyExists ( "Album" , 0 ) ) addtag ( "Album" , 0, merge , strlen (merge) , 5, 0 );
    1282             if ( tmp[2][0]  &&  ! TagKeyExists ( "Title" , 0 ) ) addtag ( "Title" , 0, tmp[2], strlen (tmp[2]), 5, 0 );
    1283             if ( tmp[4][0]  &&  ! TagKeyExists ( "Track" , 0 ) ) addtag ( "Track" , 0, tmp[4], strlen (tmp[4]), 5, 0 );
    1284             if ( q != NULL  &&  ! TagKeyExists ( "Year"  , 0 ) ) addtag ( "Year"  , 0, q     , 4              , 5, 0 );
    1285 #endif
    1286             return 1;
    1287         }
    1288 #ifndef STFU
    1289         stderr_printf ("???\n--\n");
    1290 #endif
    1291     }
    1292 
    1293     return 0;
    1294 }
    1295 
    1296 
    1297 /*******************************************************************************/
    1298 
    1299 
    1300 static int
    1301 CopyTags_Name ( const char* filename )
    1302 {
    1303     char         buff [4096];
    1304 
    1305     FullPathName  ( buff, sizeof buff, filename );
    1306     Parser        ( buff );
    1307     return 0;
    1308 }
    1309 
    1310 
    13111107int
    13121108CopyTags ( const char* filename )
     
    13231119    CopyTags_APE  (fp);                 // APE tags have higher priority than ID3V1 tags
    13241120    CopyTags_ID3  (fp);
    1325 //     CopyTags_Name (filename);
    13261121
    13271122    fclose (fp);
Note: See TracChangeset for help on using the changeset viewer.