/* " " "." . "/" / " -- " _ "[#0]" 0 "[#n]" [number] n "(#N)" (CD x) N "#A" Artist A "#C" CD C "#T" Title T "#x" extention x /#C -- [#n] #A -- #T#x | Acid Jazz/100% Acid Jazz -- [04] Leena Conquest (and Hip Hop Fingers) -- Boundaries (Radio Edit).pac /#A/#C -- [#n] #T#x | Andreas Vollenweider/Eolian Minstrel -- [02] Across the Iron River.pac /#A/#C#N -- [#n] #T#x | Barbra Streisand/The Concert (CD 1) -- [01] Overture /#A -- #C -- [#n] #T#x | Friedemann/Friedemann -- Aquamarin -- [09] In the Court of the Mermaid.pac /#C/[#n] #A -- #T#x | Jazz Lyrik Prosa/[11] Eberhard Esche -- Anektode.pac /#A -- #T#x | Lais/Lais -- 06.pac /#C/(#N) -- [#n] #A -- #T#x | Tanz- und Folkfest 2001 -- Klingende Post/(CD 2) -- [09] Andy Irvine -- Gladiators.pac /#A -- #C -- [#0]#x | Friedemann/Friedemann -- Aquamarin -- [00].pac /#A/#C (#N) -- [#0]#x | Tangerine Dream/The Warsaw Concert (CD 2) -- [00].pac /#A/#T#x | Heinz-Rudolf Kunze/Dein ist mein ganzes Herz.pac /#A/#C -- [#0]#x | Sting/Nada como el Sol -- [00].mpc */ #include #include "mppdec.h" #if defined HAVE_INCOMPLETE_READ && FILEIO != 1 size_t complete_read ( int fd, void* dest, size_t bytes ) { size_t bytesread = 0; size_t ret; while ( bytes > 0 ) { ret = read ( fd, dest, bytes ); if ( ret == 0 || ret == (size_t)-1 ) break; dest = (void*)(((char*)dest) + ret); bytes -= ret; bytesread += ret; } return bytesread; } #endif static int tag ( const char* filename, const char* Artist, const char* CD, const char* Title, int no ) { FILE_T fp; char tmp [128]; // sleep (1); fp = OPENRW (filename); if ( fp == INVALID_FILEDESC ) return -1; if ( -1 == SEEK ( fp, -128L, SEEK_END ) ) return -1; if ( 128 != READ ( fp, tmp, 128 ) ) return 0; if ( 0 != memcmp ( tmp, "TAG", 3 ) ) { SEEK ( fp, -0L, SEEK_END ); printf ("*** Add Tag ***\n"); memset (tmp, 0, sizeof(tmp)); } else { SEEK ( fp, -128L, SEEK_END ); printf ("*** Modify Tag ***\n"); } printf ("------------------\nArtist=%s\nCD =%s\nTitle =%s\nNo =%u\n-----------------\n", Artist, CD, Title, no ); strncpy ( tmp + 0, "TAG" , 3 ); strncpy ( tmp + 3, Title , 30 ); strncpy ( tmp + 33, Artist, 30 ); strncpy ( tmp + 63, CD , 30 ); strncpy ( tmp + 93, " ", 4 ); // memcpy ( tip->Comment, tmp + 97, 30 ); tmp[125] = '\0'; tmp[126] = no; tmp[127] = (char)-1; if ( 128 != WRITE ( fp, tmp, 128 ) ) return 0; CLOSE (fp); printf ( "Okay\n\n"); return 0; } static void copy ( char* dst, const char* src, size_t len ) { memcpy ( dst, src, len ); dst[len] = '\0'; } /* * dst[0] = Artist * dst[1] = CD * dst[2] = Title * dst[3] = +CD * dst[4] = number * dst[5] = ext */ static int parse ( char** dst, const char* src, const char* format ) { int i; const char* srcend = src + strlen(src); const char* p; char* q; for ( i = 0; i < 6; i++) dst[i][0] = '\0'; for ( i = strlen(format); i-- > 0; ) { p = srcend; printf ("%c: ", format[i] ); switch ( format[i] ) { case '.': case ' ': case '/': // !!!!!!! if (p[-1] != format[i]) return 1; p--; break; case '_': if (0 != memcmp (p-4, " -- ", 4)) return 1; p -= 4; break; case '0': if (p[-1] != ']' || p[-2] != '0' || p[-3] != '0' || p[-4] != '[') return 1; p -= 4; break; case 'n': if (p[-1] != ']' || !isdigit(p[-2]) || !isdigit(p[-3]) || p[-4] != '[') return 1; copy (dst[4], p-3, 2); p -= 4; break; case 'N': if (p[-1] != ')' || !isdigit(p[-2]) || p[-3] != ' ' || p[-4] != 'D' || p[-5] != 'C' || p[-6] != '(') return 1; dst[3][0] = ' '; copy (dst[3]+1, p-6, 6); p -= 6; break; case 'A': q = dst[0]; goto big; case 'C': q = dst[1]; goto big; case 'T': q = dst[2]; goto big; big: while ( 0 == memcmp (p-4, "/mpc", 4) || 0 == memcmp (p-4, "/mp3", 4) || 0 == memcmp (p-4, "/pac", 4) ) srcend -= 4, p -= 4; while ( p[-1] != PATH_SEP && p[-1] != DRIVE_SEP && 0 != memcmp (p-4, " -- ", 4 ) && (p[-1] != ')' || !isdigit(p[-2]) || p[-3] != ' ' || p[-4] != 'D' || p[-5] != 'C' || p[-6] != '(') && (p[-1] != ' ' || p[-2] != ']' || !isdigit(p[-3]) || !isdigit(p[-4]) || p[-5] != '[') && (p[-1] != ']' || p[-2] != '0' || p[-3] != '0' || p[-4] != '[') ) p--; copy ( q, p, srcend - p ); break; case 'x': do { p--; if (p[0] == PATH_SEP || p[0] == DRIVE_SEP) return -1; } while (*p != '.'); copy (dst[5], p, srcend-p ); break; } printf ("%*.*s\033[7m%*.*s\033[0m\n", p-src, p-src, src, srcend-p, srcend-p, p ); srcend = p; } return 0; } static int hexdigit ( const char s ) { if ( (unsigned char)(s-'0') < 10u ) return s-'0'; if ( (unsigned char)(s-'A') < 6u ) return s-'A'+10; return -1; } static void spaceconverting ( char* dst, const char* src ) { for ( ; src[0] != '\0' ; src++) { if ( src[0] == '_' ) *dst++ = ' '; else if ( src[0] == '%' && hexdigit(src[1]) >= 0 && hexdigit(src[2]) >= 0 ) *dst++ = hexdigit(src[1]) * 16 + hexdigit(src[2]), src += 2; else *dst++ = *src; } *dst = '\0'; } void doitwith ( const char* filename, const char* src ) { static const char* parser [] = { "/A_Tx", "/A/Tx", "/A_C_0x", "/C_n A_Tx", "/A/C_n Tx", "/A/C#N_n Tx", "/A_C_n Tx", "/C/n A_Tx", "/C/N_n A_Tx", "/A/C N_0x", "/A/C_0x", }; size_t i; int no = 0; int idx = -1; char tmp [6] [1024]; char* buff [6] = { tmp[0], tmp[1], tmp[2], tmp[3], tmp[4], tmp[5] }; printf (" »%s«\n", src ); for ( i = 0; i < sizeof(parser)/sizeof(*parser); i++ ) { if ( 0 == parse ( buff, src, parser[i] ) ) { no++; idx = i; printf ("Artist = »%s«\n", tmp[0]); printf ("CD = »%s%s«\n", tmp[1], tmp[3]); printf ("Title = »%s«\n", tmp[2]); printf ("No# = »%s«\n", tmp[4]); printf ("Extent = »%s«\n", tmp[5]); } printf ("\n"); } if ( no != 1 ) { printf ("%u matches\a\n\n", no ), sleep (2); } { char merge [1024]; parse ( buff, src, parser[idx] ); sprintf (merge,"%s%s", tmp[1], tmp[3]); tag ( filename, tmp[0], merge, tmp[2], atoi(tmp[4])); } printf ("\n"); } int Cdecl main ( int argc, char** argv ) { char buff1 [32768]; char buff2 [32768]; char buff3 [32768]; getcwd ( buff1, sizeof(buff1) ); while ( *++argv ) { spaceconverting ( buff3, *argv ); if (**argv == PATH_SEP) sprintf ( buff2, "%s", buff3 ); else if (buff3[0] == '.' && buff3[1] == PATH_SEP) sprintf ( buff2, "%s%c%s", buff1, PATH_SEP, buff3+2 ); else sprintf ( buff2, "%s%c%s", buff1, PATH_SEP, buff3 ); doitwith ( *argv, buff2 ); } return 0; } /* end of tagger.c */