/* * Mp3Splt -- Utility for mp3/ogg splitting without decoding * * Copyright (c) 2002-2005 M. Trotta - * * http://mp3splt.sourceforge.net * * 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., 59 Temple Place, Suite 330, Boston, MA 02111, USA. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include #include #include #ifndef NO_OGG #include #include #include #endif #include "mp3.h" #include "ogg.h" #include "splt.h" #include "mp3splt.h" #include "cddb.h" #if defined(__BEOS__) && !defined (HAS_GETPASS) #warning Faking getpass() !!! char *getpass(char *p) { char *ret; ret = malloc(30); if (!ret) return NULL; puts(p); fgets(ret,30,stdin); return ret; } #endif #if defined(__BEOS__) && (IPPROTO_UDP==1) /* net_server has a weird order for IPPROTO_ */ #else #define closesocket close #endif const char alphabet [] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; /* * Base64 Algorithm: Base64.java v. 1.3.6 by Robert Harder * Ported and optimized for C by Matteo Trotta */ char *encode3to4 (unsigned char *source, int srcoffset, int num, char *destination, int destoffset) { int inbuff=(num>0?(source[srcoffset]<<16):0)|(num>1?(source[srcoffset+1]<<8):0)|(num>2?(source[srcoffset+2]):0); switch(num) { case 3: destination[destoffset] = alphabet[(inbuff>>18)]; destination[destoffset+1] = alphabet[(inbuff>>12)&0x3f]; destination[destoffset+2] = alphabet[(inbuff>>6)&0x3f]; destination[destoffset+3] = alphabet[(inbuff)&0x3f]; return destination; case 2: destination[destoffset] = alphabet[(inbuff>>18)]; destination[destoffset+1] = alphabet[(inbuff>>12)&0x3f]; destination[destoffset+2] = alphabet[(inbuff>>6)&0x3f]; destination[destoffset+3] = '='; return destination; case 1: destination[destoffset] = alphabet[(inbuff>>18)]; destination[destoffset+1] = alphabet[(inbuff>>12)&0x3f]; destination[destoffset+2] = '='; destination[destoffset+3] = '='; return destination; default: return destination; } } char *b64 (unsigned char *source, int len) { char *out; int d, e=0; d = ((len*4/3)+((len%3)>0?4:0)); if ((out = malloc(d+1))==NULL) { perror("malloc"); exit(1); } memset(out, 0x00, d+1); for(d=0;d<(len-2);d+=3,e+=4) out = encode3to4(source, d, 3, out, e); if(did.album, 30)==NULL) return -1; } else { if (tracks > 0) if (get_cue_value(line, state->fn[tracks], 255)==NULL) return -1; } break; case 3: if (tracks==-1) { if (get_cue_value(line, state->id.artist, 30)==NULL) return -1; } else { if (tracks>0) if (get_cue_value(line, state->performer[tracks], 127)==NULL) return -1; } break; case 4: line[strlen(line)-1]='\0'; ptr += 9; if ((dot = strchr(ptr, ':'))==NULL) return -1; ptr[dot-ptr] = ptr[dot-ptr+3] = '.'; cleanstring(ptr); if (tracks>0) { float seconds = c_seconds(ptr); if (seconds==-1) return -1; state->splitpoints[tracks-1] = floorf(seconds); seconds = (seconds - state->splitpoints[tracks-1])*4/3; state->splitpoints[tracks-1] += seconds; check=1; } break; default: break; } } if (!check) tracks--; if (tracks>0) state->splitpoints[tracks] = (float) -1.f; // End of file fclose(file_input); return tracks; } int get_cddb_splitpoints (unsigned char *file, splt_state *state) { FILE *file_input; char line[512]; char prev[10]; char *number, *c; int tracks = 0, i, j; if (!(file_input=fopen(file, "r"))) { perror(file); exit(1); } fseek (file_input, 0, SEEK_SET); do { if ((fgets(line, 512, file_input))==NULL) return -1; number = strstr(line, "Track frame offset"); } while (number == NULL); memset(prev, 0, 10); do { if ((fgets(line, 512, file_input))==NULL) return -1; line[strlen(line)-1] = '\0'; i = 0; while ((isdigit(line[i])==0) && (line[i]!='\0')) { i++; number = line + i; } if (number == (line + strlen(line))) break; else state->splitpoints[tracks++] = (float) atof (number); } while (tracks=0; i--) { state->splitpoints[i] -= state->splitpoints[0]; state->splitpoints[i] /= 75; } state->splitpoints[tracks] = (float) -1.f; // End of file j=0; do { char temp[10]; memset(temp, 0, 10); if ((fgets(line, 512, file_input))==NULL) return -1; line[strlen(line)-1] = '\0'; if (strlen(line)>0) if (line[strlen(line)-1]=='\r') line[strlen(line)-1]='\0'; if (j==0) { if (strstr(line, "DTITLE")==NULL) continue; } else if (strstr(line, "TTITLE")==NULL) continue; if ((number=strchr(line, '='))==NULL) return -1; if (j>0) { int len = number-line; if (len>10) len = 10; strncpy(temp, line, len); if ((c=strchr(number, '/'))!=NULL) number = c + 1; number = cleanstring (number); } if (strlen(++number)>255) number[255]='\0'; if ((j>0)&&(strstr(number, "Data")!=NULL) && (strstr(number, "Track")!=NULL)) { state->splitpoints[j-1]=state->splitpoints[j]; tracks -= 1; } else { if ((j>0)&&(strcmp(temp, prev)==0)) strncat(state->fn[j-1], number, 255-strlen(state->fn[j-1])); else strncpy(state->fn[j++], number, 255); } strncpy(prev, temp, 10); } while (j<=tracks); while ((fgets(line, 512, file_input))!=NULL) { line[strlen(line)-1] = '\0'; if (strlen(line)>0) if (line[strlen(line)-1]=='\r') line[strlen(line)-1]='\0'; if (strstr(line, "EXTD")==NULL) continue; else { if ((number=strchr(line, '='))==NULL) break; else { if ((c=strstr(number, "YEAR"))!=NULL) strncpy(state->id.year, c+6, 4); if ((c=strstr(number, "ID3G"))!=NULL) { strncpy(line, c+6, 3); state->id.genre= (unsigned char) atoi(line); } break; } } } i=0; while ((state->fn[0][i]!='/') && (state->fn[0][i]!='\0')&&(i<30)) { state->id.artist[i] = state->fn[0][i]; i++; } state->id.artist[i-1]='\0'; cleanstring(state->id.artist); j=0; i += 2; do state->id.album[j++]=state->fn[0][i++]; while ((state->fn[0][i]!='\0')&&(j<30)); fclose(file_input); return tracks; } int find_cd (char *buf, int size, cd_state *state) { char *c, *add; int i; if (size<30) return 0; // 30 is a safe value for preventing buffer exceed add = buf+size; buf = strstr(buf, "cat="); if (buf==NULL) return 0; else { if (state->foundcd==0) fprintf (stdout, "List of found cd:\n"); do { i=0; buf += 4; if ((c=strchr(buf, '&'))==NULL) return -1; if (c==buf) continue; memset(state->discs[state->foundcd].category, 0x00, 20); strncpy(state->discs[state->foundcd].category, buf, c - buf); buf=c+4; memset(state->discs[state->foundcd].discid, 0x00, 9); strncpy(state->discs[state->foundcd].discid, buf, DISCIDLEN); buf = buf + DISCIDLEN + 2; if ((c=strchr(buf, '<'))==NULL) return -1; else if (c == buf) { if ((buf=strchr(buf, '>'))==NULL) return -1; buf++; if ((c=strchr(buf, '<'))==NULL) return -1; i=-1; } if (i==-1) fprintf (stdout, " |\\=>"); fprintf (stdout, "%3d) ", state->foundcd); if (i==-1) fprintf (stdout, "Revision: "); while ((buffoundcd+1)%22)==0) { char junk[18]; fprintf (stdout, "\n-- 'q' to select cd, Enter for more: "); fgets(junk, 16, stdin); if (junk[0]=='q') { state->foundcd++; return -2; } } else fprintf(stdout, "\n"); state->foundcd++; } while ((buf<(add-30)) && (state->foundcdh_addr)) ->s_addr; host.sin_port=htons(dest.port); if((fd=socket(AF_INET, SOCK_STREAM, 0))==-1) { perror("socket"); exit(1); } if ((connect(fd, (void *)&host, sizeof(host)))==-1) { perror("connect"); exit(1); } if (dest.proxy) { sprintf(message,"GET http://www.freedb.org"SEARCH" "PROXYDLG, junk); if (dest.auth!=NULL) sprintf (message, "%s"AUTH"%s\n", message, dest.auth); strncat(message, "\n", 1); } else sprintf(message,"GET "SEARCH"\n", junk); if((send(fd, message, strlen(message), 0))==-1) { perror("send"); exit(1); } fprintf (stderr, "Host contacted. Waiting for answer...\n"); memset(buffer, 0x00, BUFFERSIZE); if ((cdstate = (cd_state *) malloc (sizeof(cd_state)))==NULL) { perror("malloc"); exit(1); } cdstate->foundcd = 0; do { tot=0; c = buffer; do { i = recv(fd, c, BUFFERSIZE-(c-buffer)-1, 0); if (i==-1) break; tot += i; buffer[tot]='\0'; c += i; } while ((i>0)&&(tot"))==NULL)); tot = find_cd(buffer, tot, cdstate); if (tot==-1) continue; if (tot==-2) break; } while ((i>0)&&(e==NULL)&&(cdstate->foundcdfoundcd<=0) { if (dest.proxy) { if (strstr(buffer, "HTTP/1.0")!=NULL) { if ((c = strchr (buffer, '\n'))!=NULL) buffer[c-buffer]='\0'; fprintf (stderr, "Proxy Reply: %s\n", buffer); } } if (cdstate->foundcd==0) return -1; if (cdstate->foundcd==-1) return -2; } if (cdstate->foundcd==MAXCD) fprintf (stderr, "\nMax cd number reached, this search may be too generic.\n"); fprintf (stdout, "\n"); do { i=0; fprintf (stdout, "Select cd #: "); fgets(message, 254, stdin); message[strlen(message)-1]='\0'; tot=0; if (message[tot]=='\0') i=-1; while(message[tot]!='\0') if (isdigit(message[tot++])==0) { fprintf (stdout, "Please "); i=-1; break; } if (i!=-1) i = atoi (message); } while ((i>=cdstate->foundcd) || (i<0)); state->id.genre = getgenre(cdstate->discs[i].category); if (dest.proxy) { sprintf(message, "GET "FREEDBHTTP"cmd=cddb+read+%s+%s&hello=nouser+mp3splt.net+"NAME"+"VER"&proto=5 "PROXYDLG, cdstate->discs[i].category, cdstate->discs[i].discid); if (dest.auth!=NULL) { sprintf (message, "%s"AUTH"%s\n", message, dest.auth); memset(dest.auth, 0x00, strlen(dest.auth)); free(dest.auth); } strncat(message, "\n", 1); } else { sprintf(message, "CDDB READ %s %s\n", cdstate->discs[i].category, cdstate->discs[i].discid); host.sin_port=htons(PORT2); } fprintf (stderr, "\nContacting "FREEDB" to query selected cd...\n"); if((fd=socket(AF_INET, SOCK_STREAM, 0))==-1) { perror("socket"); exit(1); } if ((connect(fd, (void *)&host, sizeof(host)))==-1) { perror("connect"); exit(1); } if (!dest.proxy) { i=recv(fd, buffer, BUFFERSIZE-1, 0); buffer[i]='\0'; if (strncmp(buffer,"201",3)!=0) return -4; if((send(fd, HELLO, strlen(HELLO), 0))==-1) { perror("send"); exit(1); } i=recv(fd, buffer, BUFFERSIZE-1, 0); buffer[i]='\0'; if (strncmp(buffer,"200",3)!=0) return -4; } if((send(fd, message, strlen(message), 0))==-1) { perror("send"); exit(1); } fprintf (stderr, "Host contacted. Waiting for answer...\n"); memset(buffer, 0x00, BUFFERSIZE); c = buffer; tot=0; do { i = recv(fd, c, BUFFERSIZE-(c-buffer)-1, 0); if (i==-1) break; tot += i; buffer[tot]='\0'; c += i; } while ((i>0)&&(tot