/* textfunc.c - Handles most console I/O and interface tasks Copyright (C) 2000-2006 Cedric Tefft This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *************************************************************************** This program is based in part on MP3Info 0.5 by Ricardo Cerqueira */ #include "mp3info.h" char *layer_text[] = { "I", "II", "III" }; /* * Name of this one is quite obvious... */ void CenterText(int line, char *text) { mvprintw(line,(COLS/2)-((int)strlen(text)/2),text); } /* Convert hex digit to integer */ int xtoi(char *string) { char chr=toupper(string[0]); if(chr > '9') return (int) (chr - 'A' + 10); else return (int) (chr - '0'); } /* * Another one with an obvious name :-) */ void display_help() { printf("%s %s\n\nUSAGE:\n\n",VERSION,COPYRIGHT); printf("\tmp3info [ -h | -G ]\n"\ "\n\tmp3info [-x] [-F] [-r a|m|v] [-p FORMAT_STRING] file(s)\n"\ "\n\tmp3info [-d] file(s)\n"\ "\n\tmp3info [-i] [-t title] [-a artist] [-l album] [-y year]\n"\ "\t\t[-c comment] [-n track] [-g genre] file(s)\n"\ "\nOPTIONS\n"\ "\t-a artist\tSpecify ID3 artist name\n"\ "\t-c comment\tSpecify ID3 comment\n"\ "\t-g genre\tSpecify ID3 genre (use -G for genre list)\n"\ "\t-l album\tSpecify ID3 album name\n"\ "\t-n track\tSpecify ID3 v1.1 track number\n"\ "\t-t title\tSpecify ID3 track title\n"\ "\t-y year\t\tSpecify ID3 copyright year\n\n"\ "\t-G\t\tDisplay valid genres\n"\ "\t-h\t\tDisplay this help page\n"\ "\t-x\t\tDisplay technical attributes of the MP3 file\n"\ "\t-r a|m|v\tReport bit rate of (VBR) files as:\n"\ "\t\ta - Average bit rate (float)\n"\ "\t\tm - Median bit rate (integer)\n"\ "\t\tv - Simply use the word 'Variable' (string) [default]\n\n"\ "\t-i\t\tEdit ID3 tag interactively\n"\ "\t-d\t\tDelete ID3 tag (if one exists)\n"\ "\t-f\t\tForce processing if file is not a standard MP3\n"\ "\t-F\t\tFull Scan (see man page for details)\n"\ "\n\n\t-p \"FORMAT_STRING\" Print FORMAT_STRING with substitutions\n"\ "\n\t\tConversion Specifiers\n\n"\ "\t\t%%f\tFilename without the path (string)\n"\ "\t\t%%F\tFilename with the path (string)\n"\ "\t\t%%k\tFile size in KB (integer)\n"\ "\n\t\t%%a\tArtist (string)\n"\ "\t\t%%c\tComment (string)\n"\ "\t\t%%g\tMusical genre (string)\n"\ "\t\t%%G\tMusical genre (integer)\n"\ "\t\t%%l\tAlbum name (string)\n"\ "\t\t%%n\tTrack (integer)\n"\ "\t\t%%t\tTrack Title (string)\n"\ "\t\t%%y\tYear (string)\n"\ "\n\t\t%%C\tCopyright flag (string)\n"\ "\t\t%%e\tEmphasis (string)\n"\ "\t\t%%E\tCRC Error protection (string)\n"\ "\t\t%%L\tMPEG Layer (string)\n"\ "\t\t%%O\tOriginal material flag (string)\n"\ "\t\t%%o\tStereo/mono mode (string)\n"\ "\t\t%%p\tPadding (string)\n"\ "\t\t%%v\tMPEG Version (float)\n"\ "\n\t\t%%u\tNumber of good audio frames (integer)\n"\ "\t\t%%b\tNumber of corrupt audio frames (integer)\n"\ "\t\t%%Q\tSampling frequency in Hz (integer)\n"\ "\t\t%%q\tSampling frequency in KHz (integer)\n"\ "\t\t%%r\tBit Rate in KB/s (see also '-r')\n"\ "\n\t\t%%m\tPlaying time: minutes only (integer)\n"\ "\t\t%%s\tPlaying time: seconds only (integer)\n"\ "\t\t%%S\tTotal playing time in seconds (integer)\n"\ "\n\t\t%%%%\tA single percent sign\n"\ "\n\t\tEscape Sequences\n\n"\ "\t\t\\n\tNewline\n"\ "\t\t\\t\tHorizontal tab\n"\ "\t\t\\v\tVertical tab\n"\ "\t\t\\b\tBackspace\n"\ "\t\t\\r\tCarriage Return\n"\ "\t\t\\f\tForm Feed\n"\ "\t\t\\a\tAudible Alert (terminal bell)\n"\ "\t\t\\xhh\tAny arbitrary character specified by the\n"\ "\t\t\thexidecimal number hh\n"\ "\t\t\\ooo\tAny arbitrary character specified by the\n"\ "\t\t\toctal number ooo\n"\ "\t\t\\\\\tA single backslash character\n\n"\ "This help screen is only a summary of command-line switches\n"\ "See the man page for complete documentation.\n\n"); } void display_genres(int alphagenreindex[],char *typegenre[]) { int i,j,index; printf("Extended MP3 ID3 Genres\n=======================\n"); for(i=0;i MAXGENRE) { num_genre=256; } return num_genre; } void text_genre(unsigned char *genre,char *buffer) { int genre_num = (int) genre[0]; if(genre_num <= MAXGENRE) { sprintf(buffer,"%s",typegenre[genre_num]); } else if(genre_num < 255) { sprintf(buffer,"(UNKNOWN) [%d]",genre_num); } else { buffer[0]='\0'; } } void determine_tasks (char *format_string,int *want_id3,int *scantype, int *fullscan_vbr,int vbr_report) { char *format=format_string; char *percent; while((percent=strchr(format,'%'))) { percent++; while(*percent && (percent[0] != '%' && !isalpha(*percent))) percent++; switch (percent[0]) { case 't': case 'a': case 'l': case 'y': case 'c': case 'n': case 'g': case 'G': *want_id3=1; break; case 'm': case 's': case 'u': case 'S': *fullscan_vbr=1; case 'r': if(vbr_report != VBR_VARIABLE) *fullscan_vbr=1; case 'q': case 'Q': case 'e': case 'E': case 'C': case 'O': case 'v': case 'L': case 'p': case 'o': if(*scantype != SCAN_FULL) *scantype=SCAN_QUICK; break; case 'b': *scantype=SCAN_FULL; break; } format=percent+1; } } void format_output (char *format_string,mp3info *mp3, int vbr_report) { char genre[40]=""; char mod[1000],*percent,*pos,*code; char *format=format_string; int modlen; while((percent=strchr(format,'%'))) { *percent=0; printf(format); *percent='%'; code=percent+1; while(*code && (code[0] != '%' && !isalpha(*code))) code++; if(*code) { modlen=code-percent+1; if(modlen > 1000) { printf("Format modifier beginning at position %d too long!\n",(int)(percent-format)); exit(5); } strncpy(mod,percent,modlen); mod[modlen]=0; mod[modlen-1]='s'; switch (*code) { case 't': printf(mod,mp3->id3.title); break; case 'f': pos = (pos=strrchr(mp3->filename,'/')) ? pos+1 : mp3->filename; printf(mod,pos); break; case 'F': printf(mod,mp3->filename); break; case 'a': printf(mod,mp3->id3.artist); break; case 'l': printf(mod,mp3->id3.album); break; case 'k': mod[modlen-1] = 'd'; printf(mod,mp3->datasize / 1024); break; case 'y': printf(mod,mp3->id3.year); break; case 'c': printf(mod,mp3->id3.comment); break; case 'n': if(mp3->id3_isvalid && mp3->id3.track[0]) { mod[modlen-1]='d'; printf(mod, (int) mp3->id3.track[0]); } break; case 'g': if(mp3->id3_isvalid) { text_genre(mp3->id3.genre,genre); printf(mod,genre); } break; case 'G': if(mp3->id3_isvalid) { mod[modlen-1]='d'; printf(mod,(int) mp3->id3.genre[0]); } break; case 'r': if(mp3->header_isvalid) { if(mp3->vbr && (vbr_report == VBR_VARIABLE)) printf(mod,"Variable"); else if(vbr_report == VBR_AVERAGE) { mod[modlen-1]='f'; printf(mod,mp3->vbr_average); } else { mod[modlen-1]='d'; printf(mod,header_bitrate(&mp3->header)); } } break; case 'q': if(mp3->header_isvalid) { mod[modlen-1]='d'; printf(mod,header_frequency(&mp3->header)/1000); } break; case 'Q': if(mp3->header_isvalid) { mod[modlen-1]='d'; printf(mod,header_frequency(&mp3->header)); } break; case 'e': if(mp3->header_isvalid) { printf(mod,header_emphasis(&mp3->header)); } break; case 'E': if(mp3->header_isvalid) { printf(mod,!mp3->header.crc ? "Yes" : "No"); } break; case 'C': if(mp3->header_isvalid) { printf(mod,mp3->header.copyright ? "Yes" : "No"); } break; case 'O': if(mp3->header_isvalid) { printf(mod,mp3->header.original ? "Yes" : "No"); } break; case 'm': if(mp3->header_isvalid) { mod[modlen-1]='d'; printf(mod,mp3->seconds / 60); } break; case 's': if(mp3->header_isvalid) { mod[modlen-1]='d'; printf(mod,mp3->seconds % 60); } break; case 'S': if(mp3->header_isvalid) { mod[modlen-1]='d'; printf(mod,mp3->seconds); } break; case 'v': if(mp3->header_isvalid) { mod[modlen-1]='f'; printf(mod,mp3->header.version ? ((mp3->header.version==2) ? 2.5 : 1.0) : 2.0); } break; case 'L': if(mp3->header_isvalid) { printf(mod,layer_text[header_layer(&mp3->header)-1]); } break; case 'o': if(mp3->header_isvalid) { printf(mod,header_mode(&mp3->header)); } break; case 'p': if(mp3->header_isvalid) { printf(mod,mp3->header.padding ? "Yes" : "No"); } break; case 'u': if(mp3->header_isvalid) { mod[modlen-1]='d'; printf(mod,mp3->frames); } break; case 'b': if(mp3->header_isvalid) { mod[modlen-1]='d'; printf(mod,mp3->badframes); } break; case '%': printf("%%"); break; default: printf("%%%c",*(code=percent+1)); break; } format=code+1; } } printf(format); } void translate_escapes (char *string) { char *read=string; char *write=string; int val; while(*read) { if(*read == '\\') { read++; switch (*read) { case 'n': *(write++)='\n'; read++; break; case 't': *(write++)='\t'; read++; break; case 'v': *(write++)='\v'; read++; break; case 'b': *(write++)='\b'; read++; break; case 'r': *(write++)='\r'; read++; break; case 'f': *(write++)='\f'; read++; break; case 'a': *(write++)='\a'; read++; break; case 'X': case 'x': read++; /* HEX */ val=0; if(isxdigit(*read)) val=xtoi(read++); if(isxdigit(*read)) val=(val*16) + xtoi(read++); *(write++)=(val % 256); default: if(*read <= '7' && *read >= '0') { /* octal */ val=xtoi(read++); if(*read <= '7' && *read >= '0') val=(val*8) + xtoi(read++); if(*read <= '7' && *read >= '0') val=(val*8) + xtoi(read++); *(write++)=(val % 256); } else { *(write++)=*(read++); break; } } } else { *write++=*read++; } } *write=0; }