1/* 2 * $Id: mp3-scanner.c,v 1.1 2009-06-30 02:31:08 steven Exp $ 3 * Implementation file for mp3 scanner and monitor 4 * 5 * Ironically, this now scans file types other than mp3 files, 6 * but the name is the same for historical purposes, not to mention 7 * the fact that sf.net makes it virtually impossible to manage a cvs 8 * root reasonably. Perhaps one day soon they will move to subversion. 9 * 10 * /me crosses his fingers 11 * 12 * Copyright (C) 2003 Ron Pedde (ron@pedde.com) 13 * 14 * This program is free software; you can redistribute it and/or modify 15 * it under the terms of the GNU General Public License as published by 16 * the Free Software Foundation; either version 2 of the License, or 17 * (at your option) any later version. 18 * 19 * This program is distributed in the hope that it will be useful, 20 * but WITHOUT ANY WARRANTY; without even the implied warranty of 21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 * GNU General Public License for more details. 23 * 24 * You should have received a copy of the GNU General Public License 25 * along with this program; if not, write to the Free Software 26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 27 */ 28 29#ifdef HAVE_CONFIG_H 30# include "config.h" 31#endif 32 33#define _POSIX_PTHREAD_SEMANTICS 34#include <ctype.h> 35#include <errno.h> 36#include <fcntl.h> 37#include <id3tag.h> 38#include <limits.h> 39#include <restart.h> 40#include <stdio.h> 41#include <stdlib.h> 42#include <string.h> 43 44#include <netinet/in.h> /* htons and friends */ 45#include <sys/stat.h> 46#include <dirent.h> /* why here? For osx 10.2, of course! */ 47 48#include "daapd.h" 49#include "db-memory.h" 50#include "err.h" 51#include "mp3-scanner.h" 52#include "playlist.h" 53 54#ifndef HAVE_STRCASESTR 55# include "strcasestr.h" 56#endif 57 58/* 59 * Typedefs 60 */ 61 62/** 63 * Struct to keep info about the information gleaned from 64 * the mp3 frame header. 65 */ 66typedef struct tag_scan_frameinfo { 67 int layer; /**< 1, 2, or 3, representing Layer I, II, and III */ 68 int bitrate; /**< Bitrate in kbps (128, 64, etc) */ 69 int samplerate; /**< Samplerate (e.g. 44100) */ 70 int stereo; /**< Any kind of stereo.. joint, dual mono, etc */ 71 72 int frame_length; /**< Frame length in bytes - calculated */ 73 int crc_protected; /**< Is the frame crc protected? */ 74 int samples_per_frame; /**< Samples per frame - calculated field */ 75 int padding; /**< Whether or not there is a padding sample */ 76 int xing_offset; /**< Where the xing header should be relative to end of hdr */ 77 int number_of_frames; /**< Number of frames in the song */ 78 79 int frame_offset; /**< Where this frame was found */ 80 81 double version; /**< MPEG version (e.g. 2.0, 2.5, 1.0) */ 82 83 int is_valid; 84} SCAN_FRAMEINFO; 85 86 87typedef struct tag_scan_id3header { 88 unsigned char id[3]; 89 unsigned char version[2]; 90 unsigned char flags; 91 unsigned char size[4]; 92} __attribute((packed)) SCAN_ID3HEADER; 93 94#define MAYBEFREE(a) { if((a)) free((a)); }; 95 96/* 97 * Globals 98 */ 99int scan_br_table[5][16] = { 100 { 0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,0 }, /* MPEG1, Layer 1 */ 101 { 0,32,48,56,64,80,96,112,128,160,192,224,256,320,384,0 }, /* MPEG1, Layer 2 */ 102 { 0,32,40,48,56,64,80,96,112,128,160,192,224,256,320,0 }, /* MPEG1, Layer 3 */ 103 { 0,32,48,56,64,80,96,112,128,144,160,176,192,224,256,0 }, /* MPEG2/2.5, Layer 1 */ 104 { 0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,0 } /* MPEG2/2.5, Layer 2/3 */ 105}; 106 107int scan_sample_table[3][4] = { 108 { 44100, 48000, 32000, 0 }, /* MPEG 1 */ 109 { 22050, 24000, 16000, 0 }, /* MPEG 2 */ 110 { 11025, 12000, 8000, 0 } /* MPEG 2.5 */ 111}; 112 113 114 115int scan_mode_foreground=1; 116 117char *scan_winamp_genre[] = { 118 "Blues", // 0 119 "Classic Rock", 120 "Country", 121 "Dance", 122 "Disco", 123 "Funk", // 5 124 "Grunge", 125 "Hip-Hop", 126 "Jazz", 127 "Metal", 128 "New Age", // 10 129 "Oldies", 130 "Other", 131 "Pop", 132 "R&B", 133 "Rap", // 15 134 "Reggae", 135 "Rock", 136 "Techno", 137 "Industrial", 138 "Alternative", // 20 139 "Ska", 140 "Death Metal", 141 "Pranks", 142 "Soundtrack", 143 "Euro-Techno", // 25 144 "Ambient", 145 "Trip-Hop", 146 "Vocal", 147 "Jazz+Funk", 148 "Fusion", // 30 149 "Trance", 150 "Classical", 151 "Instrumental", 152 "Acid", 153 "House", // 35 154 "Game", 155 "Sound Clip", 156 "Gospel", 157 "Noise", 158 "AlternRock", // 40 159 "Bass", 160 "Soul", 161 "Punk", 162 "Space", 163 "Meditative", // 45 164 "Instrumental Pop", 165 "Instrumental Rock", 166 "Ethnic", 167 "Gothic", 168 "Darkwave", // 50 169 "Techno-Industrial", 170 "Electronic", 171 "Pop-Folk", 172 "Eurodance", 173 "Dream", // 55 174 "Southern Rock", 175 "Comedy", 176 "Cult", 177 "Gangsta", 178 "Top 40", // 60 179 "Christian Rap", 180 "Pop/Funk", 181 "Jungle", 182 "Native American", 183 "Cabaret", // 65 184 "New Wave", 185 "Psychadelic", 186 "Rave", 187 "Showtunes", 188 "Trailer", // 70 189 "Lo-Fi", 190 "Tribal", 191 "Acid Punk", 192 "Acid Jazz", 193 "Polka", // 75 194 "Retro", 195 "Musical", 196 "Rock & Roll", 197 "Hard Rock", 198 "Folk", // 80 199 "Folk/Rock", 200 "National folk", 201 "Swing", 202 "Fast-fusion", 203 "Bebob", // 85 204 "Latin", 205 "Revival", 206 "Celtic", 207 "Bluegrass", 208 "Avantgarde", // 90 209 "Gothic Rock", 210 "Progressive Rock", 211 "Psychedelic Rock", 212 "Symphonic Rock", 213 "Slow Rock", // 95 214 "Big Band", 215 "Chorus", 216 "Easy Listening", 217 "Acoustic", 218 "Humour", // 100 219 "Speech", 220 "Chanson", 221 "Opera", 222 "Chamber Music", 223 "Sonata", // 105 224 "Symphony", 225 "Booty Bass", 226 "Primus", 227 "Porn Groove", 228 "Satire", // 110 229 "Slow Jam", 230 "Club", 231 "Tango", 232 "Samba", 233 "Folklore", // 115 234 "Ballad", 235 "Powder Ballad", 236 "Rhythmic Soul", 237 "Freestyle", 238 "Duet", // 120 239 "Punk Rock", 240 "Drum Solo", 241 "A Capella", 242 "Euro-House", 243 "Dance Hall", // 125 244 "Goa", 245 "Drum & Bass", 246 "Club House", 247 "Hardcore", 248 "Terror", // 130 249 "Indie", 250 "BritPop", 251 "NegerPunk", 252 "Polsk Punk", 253 "Beat", // 135 254 "Christian Gangsta", 255 "Heavy Metal", 256 "Black Metal", 257 "Crossover", 258 "Contemporary C", // 140 259 "Christian Rock", 260 "Merengue", 261 "Salsa", 262 "Thrash Metal", 263 "Anime", // 145 264 "JPop", 265 "SynthPop", 266 "Unknown" 267}; 268 269#define WINAMP_GENRE_UNKNOWN 148 270 271 272/* 273 * Forwards 274 */ 275static int scan_path(char *path); 276static int scan_gettags(char *file, MP3FILE *pmp3); 277static int scan_get_mp3tags(char *file, MP3FILE *pmp3); 278static int scan_get_aactags(char *file, MP3FILE *pmp3); 279static int scan_get_nultags(char *file, MP3FILE *pmp3) { return 0; }; 280static int scan_get_fileinfo(char *file, MP3FILE *pmp3); 281static int scan_get_mp3fileinfo(char *file, MP3FILE *pmp3); 282static int scan_get_aacfileinfo(char *file, MP3FILE *pmp3); 283static int scan_get_nulfileinfo(char *file, MP3FILE *pmp3) { return 0; }; 284static int scan_get_urlfileinfo(char *file, MP3FILE *pmp3); 285 286static int scan_freetags(MP3FILE *pmp3); 287static void scan_static_playlist(char *path, struct dirent *pde, struct stat *psb); 288static void scan_music_file(char *path, struct dirent *pde, struct stat *psb); 289 290static int scan_decode_mp3_frame(unsigned char *frame, SCAN_FRAMEINFO *pfi); 291static time_t mac_to_unix_time(int t); 292 293#ifdef OGGVORBIS 294extern int scan_get_oggfileinfo(char *filename, MP3FILE *pmp3); 295#endif 296 297/* 298 * Typedefs 299 */ 300 301typedef struct { 302 char* suffix; 303 int (*tags)(char* file, MP3FILE* pmp3); 304 int (*files)(char* file, MP3FILE* pmp3); 305} taghandler; 306 307static taghandler taghandlers[] = { 308 { "aac", scan_get_aactags, scan_get_aacfileinfo }, 309 { "mp4", scan_get_aactags, scan_get_aacfileinfo }, 310 { "m4a", scan_get_aactags, scan_get_aacfileinfo }, 311 { "m4p", scan_get_aactags, scan_get_aacfileinfo }, 312 { "mp3", scan_get_mp3tags, scan_get_mp3fileinfo }, 313 { "url", scan_get_nultags, scan_get_urlfileinfo }, 314#ifdef OGGVORBIS 315 { "ogg", scan_get_nultags, scan_get_oggfileinfo }, 316#endif 317 { NULL, 0 } 318}; 319 320 321/** 322 * Convert mac time to unix time (different epochs) 323 * 324 * param t time since mac epoch 325 */ 326time_t mac_to_unix_time(int t) { 327 struct timeval tv; 328 struct timezone tz; 329 330 gettimeofday(&tv, &tz); 331 332 return (t - (365L * 66L * 24L * 60L * 60L + 17L * 60L * 60L * 24L) + 333 (tz.tz_minuteswest * 60)); 334} 335 336/* 337 * scan_init 338 * 339 * This assumes the database is already initialized. 340 * 341 * Ideally, this would check to see if the database is empty. 342 * If it is, it sets the database into bulk-import mode, and scans 343 * the MP3 directory. 344 * 345 * If not empty, it would start a background monitor thread 346 * and update files on a file-by-file basis 347 */ 348 349int scan_init(char *path) { 350 int err; 351 352 scan_mode_foreground=0; 353 if(db_is_empty()) { 354 scan_mode_foreground=1; 355 } 356 357 if(db_start_initial_update()) 358 return -1; 359 360 DPRINTF(E_DBG,L_SCAN,"%s scanning for MP3s in %s\n", 361 scan_mode_foreground ? "Foreground" : "Background", 362 path); 363 364 err=scan_path(path); 365 366 if(db_end_initial_update()) 367 return -1; 368 369 scan_mode_foreground=0; 370 371 return err; 372} 373 374int 375is_dir(const char *path) 376{ 377 struct stat stat_buf; 378 379 if (!stat(path, &stat_buf)) 380 return S_ISDIR(stat_buf.st_mode); 381 else 382 return 0; 383} 384 385int 386is_sys_dir(const char *dirname) 387{ 388 char *MS_System_folder[] = {"SYSTEM VOLUME INFORMATION", "RECYCLER", "RECYCLED", "$RECYCLE.BIN", "asusware", NULL}; 389 char *Linux_System_folder[] = {"lost+found", NULL}; 390 int i; 391 392 for (i = 0; MS_System_folder[i] != NULL; ++i) { 393 if (!strcasecmp(dirname, MS_System_folder[i])) 394 return 1; 395 } 396 397 for (i = 0; Linux_System_folder[i] != NULL; ++i) { 398 if (!strcasecmp(dirname, Linux_System_folder[i])) 399 return 1; 400 } 401 402 return 0; 403} 404 405/* 406 * scan_path 407 * 408 * Do a brute force scan of a path, finding all the MP3 files there 409 */ 410int scan_path(char *path) { 411 DIR *current_dir; 412 char de[sizeof(struct dirent) + MAXNAMLEN + 1]; /* overcommit for solaris */ 413 struct dirent *pde; 414 int err; 415 char mp3_path[PATH_MAX]; 416 struct stat sb; 417 int modified_time; 418 419 if((current_dir=opendir(path)) == NULL) { 420 return -1; 421 } 422 423 while(1) { 424 if(config.stop) { 425 DPRINTF(E_WARN,L_SCAN,"Stop detected. Aborting scan of %s.\n",path); 426 closedir(current_dir); 427 return 0; 428 } 429 430 pde=(struct dirent *)&de; 431 432 err=readdir_r(current_dir,(struct dirent *)de,&pde); 433 if(err == -1) { 434 DPRINTF(E_DBG,L_SCAN,"Error on readdir_r: %s\n",strerror(errno)); 435 err=errno; 436 closedir(current_dir); 437 errno=err; 438 return -1; 439 } 440 441 if(!pde) 442 break; 443 444 if(pde->d_name[0] == '.') /* skip hidden and directories */ 445 continue; 446 447 snprintf(mp3_path,PATH_MAX,"%s/%s",path,pde->d_name); 448 449 if (is_dir(mp3_path) && is_sys_dir(pde->d_name)) 450 continue; 451 452 DPRINTF(E_DBG,L_SCAN,"Found %s\n",mp3_path); 453 if(stat(mp3_path,&sb)) { 454 DPRINTF(E_WARN,L_SCAN,"Error statting: %s\n",strerror(errno)); 455 } else { 456 if(sb.st_mode & S_IFDIR) { /* dir -- recurse */ 457 DPRINTF(E_DBG,L_SCAN,"Found dir %s... recursing\n",pde->d_name); 458 scan_path(mp3_path); 459 } else { 460 /* process the file */ 461 if(strlen(pde->d_name) > 4) { 462 if((strcasecmp(".m3u",(char*)&pde->d_name[strlen(pde->d_name) - 4]) == 0) && 463 config.process_m3u){ 464 /* we found an m3u file */ 465 scan_static_playlist(path, pde, &sb); 466 } else if (strcasestr(config.extensions, 467 (char*)&pde->d_name[strlen(pde->d_name) - 4])) { 468 469 /* only scan if it's been changed, or empty db */ 470 modified_time=sb.st_mtime; 471 DPRINTF(E_DBG,L_SCAN,"FS Mod time: %d\n",modified_time); 472 DPRINTF(E_DBG,L_SCAN,"DB Mod time: %d\n",db_last_modified(sb.st_ino)); 473 if((scan_mode_foreground) || 474 !db_exists(sb.st_ino) || 475 db_last_modified(sb.st_ino) < modified_time) { 476 scan_music_file(path,pde,&sb); 477 } else { 478 DPRINTF(E_DBG,L_SCAN,"Skipping file... not modified\n"); 479 } 480 } 481 } 482 } 483 } 484 } 485 486 closedir(current_dir); 487 return 0; 488} 489 490/* 491 * scan_static_playlist 492 * 493 * Scan a file as a static playlist 494 */ 495void scan_static_playlist(char *path, struct dirent *pde, struct stat *psb) { 496 char playlist_path[PATH_MAX]; 497 char m3u_path[PATH_MAX]; 498 char linebuffer[PATH_MAX]; 499 int fd; 500 int playlistid; 501 struct stat sb; 502 503 DPRINTF(E_WARN,L_SCAN|L_PL,"Processing static playlist: %s\n",pde->d_name); 504 505 /* see if we should update it */ 506 if(db_playlist_last_modified(psb->st_ino) == psb->st_mtime) 507 return; 508 509 db_delete_playlist(psb->st_ino); 510 511 strcpy(m3u_path,pde->d_name); 512 snprintf(playlist_path,sizeof(playlist_path),"%s/%s",path,pde->d_name); 513 m3u_path[strlen(pde->d_name) - 4] = '\0'; 514 playlistid=psb->st_ino; 515 fd=open(playlist_path,O_RDONLY); 516 if(fd != -1) { 517 db_add_playlist(playlistid,m3u_path,psb->st_mtime,0); 518 DPRINTF(E_INF,L_SCAN|L_PL,"Added playlist as id %d\n",playlistid); 519 520 memset(linebuffer,0x00,sizeof(linebuffer)); 521 while(readline(fd,linebuffer,sizeof(linebuffer)) > 0) { 522 while((linebuffer[strlen(linebuffer)-1] == '\n') || 523 (linebuffer[strlen(linebuffer)-1] == '\r')) /* windows? */ 524 linebuffer[strlen(linebuffer)-1] = '\0'; 525 526 if((linebuffer[0] == ';') || (linebuffer[0] == '#')) 527 continue; 528 529 /* FIXME - should chomp trailing comments */ 530 531 /* otherwise, assume it is a path */ 532 if(linebuffer[0] == '/') { 533 strcpy(m3u_path,linebuffer); 534 } else { 535 snprintf(m3u_path,sizeof(m3u_path),"%s/%s",path,linebuffer); 536 } 537 538 DPRINTF(E_DBG,L_SCAN|L_PL,"Checking %s\n",m3u_path); 539 540 /* might be valid, might not... */ 541 if(!stat(m3u_path,&sb)) { 542 /* FIXME: check to see if valid inode! */ 543 db_add_playlist_song(playlistid,sb.st_ino); 544 } else { 545 DPRINTF(E_WARN,L_SCAN|L_PL,"Playlist entry %s bad: %s\n", 546 m3u_path,strerror(errno)); 547 } 548 } 549 close(fd); 550 } 551 552 DPRINTF(E_WARN,L_SCAN|L_PL,"Done processing playlist\n"); 553} 554 555/* 556 * scan_music_file 557 * 558 * scan a particular file as a music file 559 */ 560void scan_music_file(char *path, struct dirent *pde, struct stat *psb) { 561 MP3FILE mp3file; 562 char mp3_path[PATH_MAX]; 563 564 snprintf(mp3_path,sizeof(mp3_path),"%s/%s",path,pde->d_name); 565 566 /* we found an mp3 file */ 567 DPRINTF(E_INF,L_SCAN,"Found music file: %s\n",pde->d_name); 568 569 memset((void*)&mp3file,0,sizeof(mp3file)); 570 mp3file.path=mp3_path; 571 mp3file.fname=pde->d_name; 572 if(strlen(pde->d_name) > 4) 573 mp3file.type=strdup(strrchr(pde->d_name, '.') + 1); 574 575 /* FIXME: assumes that st_ino is a u_int_32 576 DWB: also assumes that the library is contained entirely within 577 one file system 578 */ 579 mp3file.id=psb->st_ino; 580 581 /* Do the tag lookup here */ 582 if(!scan_gettags(mp3file.path,&mp3file) && 583 !scan_get_fileinfo(mp3file.path,&mp3file)) { 584 make_composite_tags(&mp3file); 585 /* fill in the time_added. I'm not sure of the logic in this. 586 My thinking is to use time created, but what is that? Best 587 guess would be earliest of st_mtime and st_ctime... 588 */ 589 mp3file.time_added=psb->st_mtime; 590 if(psb->st_ctime < mp3file.time_added) 591 mp3file.time_added=psb->st_ctime; 592 mp3file.time_modified=psb->st_mtime; 593 594 DPRINTF(E_DBG,L_SCAN," Date Added: %d\n",mp3file.time_added); 595 596 db_add(&mp3file); 597 pl_eval(&mp3file); /* FIXME: move to db_add? */ 598 } else { 599 DPRINTF(E_WARN,L_SCAN,"Skipping %s - scan_gettags failed\n",pde->d_name); 600 } 601 602 scan_freetags(&mp3file); 603} 604 605/* 606 * scan_aac_findatom 607 * 608 * Find an AAC atom 609 */ 610long scan_aac_findatom(FILE *fin, long max_offset, char *which_atom, int *atom_size) { 611 long current_offset=0; 612 int size; 613 char atom[4]; 614 615 while(current_offset < max_offset) { 616 if(fread((void*)&size,1,sizeof(int),fin) != sizeof(int)) 617 return -1; 618 619 size=ntohl(size); 620 621 if(size <= 7) /* something not right */ 622 return -1; 623 624 if(fread(atom,1,4,fin) != 4) 625 return -1; 626 627 if(strncasecmp(atom,which_atom,4) == 0) { 628 *atom_size=size; 629 return current_offset; 630 } 631 632 fseek(fin,size-8,SEEK_CUR); 633 current_offset+=size; 634 } 635 636 return -1; 637} 638 639/* 640 * scan_get_aactags 641 * 642 * Get tags from an AAC (m4a) file 643 */ 644int scan_get_aactags(char *file, MP3FILE *pmp3) { 645 FILE *fin; 646 long atom_offset; 647 int atom_length; 648 649 long current_offset=0; 650 int current_size; 651 char current_atom[4]; 652 char *current_data; 653 unsigned short us_data; 654 int genre; 655 int len; 656 657 if(!(fin=fopen(file,"rb"))) { 658 DPRINTF(E_INF,L_SCAN,"Cannot open file %s for reading\n",file); 659 return -1; 660 } 661 662 fseek(fin,0,SEEK_SET); 663 664 atom_offset = aac_drilltoatom(fin, "moov:udta:meta:ilst", &atom_length); 665 if(atom_offset != -1) { 666 /* found the tag section - need to walk through now */ 667 668 while(current_offset < atom_length) { 669 if(fread((void*)¤t_size,1,sizeof(int),fin) != sizeof(int)) 670 break; 671 672 current_size=ntohl(current_size); 673 674 if(current_size <= 7) /* something not right */ 675 break; 676 677 if(fread(current_atom,1,4,fin) != 4) 678 break; 679 680 len=current_size-7; /* for ill-formed too-short tags */ 681 if(len < 22) 682 len=22; 683 684 current_data=(char*)malloc(len); /* extra byte */ 685 memset(current_data,0x00,len); 686 687 if(fread(current_data,1,current_size-8,fin) != current_size-8) 688 break; 689 690 if(!memcmp(current_atom,"\xA9" "nam",4)) { /* Song name */ 691 pmp3->title=strdup((char*)¤t_data[16]); 692 } else if(!memcmp(current_atom,"\xA9" "ART",4)) { 693 pmp3->artist=strdup((char*)¤t_data[16]); 694 } else if(!memcmp(current_atom,"\xA9" "alb",4)) { 695 pmp3->album=strdup((char*)¤t_data[16]); 696 } else if(!memcmp(current_atom,"\xA9" "cmt",4)) { 697 pmp3->comment=strdup((char*)¤t_data[16]); 698 } else if(!memcmp(current_atom,"\xA9" "wrt",4)) { 699 pmp3->composer=strdup((char*)¤t_data[16]); 700 } else if(!memcmp(current_atom,"\xA9" "grp",4)) { 701 pmp3->grouping=strdup((char*)¤t_data[16]); 702 } else if(!memcmp(current_atom,"\xA9" "gen",4)) { 703 /* can this be a winamp genre??? */ 704 pmp3->genre=strdup((char*)¤t_data[16]); 705 } else if(!memcmp(current_atom,"tmpo",4)) { 706 us_data=*((unsigned short *)¤t_data[16]); 707 us_data=ntohs(us_data); 708 pmp3->bpm=us_data; 709 } else if(!memcmp(current_atom,"trkn",4)) { 710 us_data=*((unsigned short *)¤t_data[18]); 711 us_data=ntohs(us_data); 712 713 pmp3->track=us_data; 714 715 us_data=*((unsigned short *)¤t_data[20]); 716 us_data=ntohs(us_data); 717 718 pmp3->total_tracks=us_data; 719 } else if(!memcmp(current_atom,"disk",4)) { 720 us_data=*((unsigned short *)¤t_data[18]); 721 us_data=ntohs(us_data); 722 723 pmp3->disc=us_data; 724 725 us_data=*((unsigned short *)¤t_data[20]); 726 us_data=ntohs(us_data); 727 728 pmp3->total_discs=us_data; 729 } else if(!memcmp(current_atom,"\xA9" "day",4)) { 730 pmp3->year=atoi((char*)¤t_data[16]); 731 } else if(!memcmp(current_atom,"gnre",4)) { 732 genre=(int)(*((char*)¤t_data[17])); 733 genre--; 734 735 if((genre < 0) || (genre > WINAMP_GENRE_UNKNOWN)) 736 genre=WINAMP_GENRE_UNKNOWN; 737 738 pmp3->genre=strdup(scan_winamp_genre[genre]); 739 } else if (!memcmp(current_atom, "cpil", 4)) { 740 pmp3->compilation = current_data[16]; 741 } 742 743 free(current_data); 744 current_offset+=current_size; 745 } 746 } 747 748 fclose(fin); 749 return 0; /* we'll return as much as we got. */ 750} 751 752 753/* 754 * scan_gettags 755 * 756 * Scan an mp3 file for id3 tags using libid3tag 757 */ 758int scan_gettags(char *file, MP3FILE *pmp3) { 759 taghandler *hdl; 760 761 /* dispatch to appropriate tag handler */ 762 for(hdl = taghandlers ; hdl->suffix ; ++hdl) 763 if(!strcasecmp(hdl->suffix, pmp3->type)) 764 break; 765 766 if(hdl->tags) 767 return hdl->tags(file, pmp3); 768 769 /* maybe this is an extension that we've manually 770 * specified in the config file, but don't know how 771 * to extract tags from. Ogg, maybe. 772 */ 773 774 return 0; 775} 776 777 778int scan_get_mp3tags(char *file, MP3FILE *pmp3) { 779 struct id3_file *pid3file; 780 struct id3_tag *pid3tag; 781 struct id3_frame *pid3frame; 782 int err; 783 int index; 784 int used; 785 unsigned char *utf8_text; 786 int genre=WINAMP_GENRE_UNKNOWN; 787 int have_utf8; 788 int have_text; 789 id3_ucs4_t const *native_text; 790 char *tmp; 791 int got_numeric_genre; 792 793 if(strcasecmp(pmp3->type,"mp3")) /* can't get tags for non-mp3 */ 794 return 0; 795 796 pid3file=id3_file_open(file,ID3_FILE_MODE_READONLY); 797 if(!pid3file) { 798 DPRINTF(E_WARN,L_SCAN,"Cannot open %s\n",file); 799 return -1; 800 } 801 802 pid3tag=id3_file_tag(pid3file); 803 804 if(!pid3tag) { 805 err=errno; 806 id3_file_close(pid3file); 807 errno=err; 808 DPRINTF(E_WARN,L_SCAN,"Cannot get ID3 tag for %s\n",file); 809 return -1; 810 } 811 812 index=0; 813 while((pid3frame=id3_tag_findframe(pid3tag,"",index))) { 814 used=0; 815 utf8_text=NULL; 816 native_text=NULL; 817 have_utf8=0; 818 have_text=0; 819 820 if(!strcmp(pid3frame->id,"YTCP")) { /* for id3v2.2 */ 821 pmp3->compilation = 1; 822 DPRINTF(E_DBG,L_SCAN,"Compilation: %d\n", pmp3->compilation); 823 } 824 825 if(((pid3frame->id[0] == 'T')||(strcmp(pid3frame->id,"COMM")==0)) && 826 (id3_field_getnstrings(&pid3frame->fields[1]))) 827 have_text=1; 828 829 if(have_text) { 830 native_text=id3_field_getstrings(&pid3frame->fields[1],0); 831 832 if(native_text) { 833 have_utf8=1; 834 utf8_text=id3_ucs4_utf8duplicate(native_text); 835 MEMNOTIFY(utf8_text); 836 837 if(!strcmp(pid3frame->id,"TIT2")) { /* Title */ 838 used=1; 839 pmp3->title = utf8_text; 840 DPRINTF(E_DBG,L_SCAN," Title: %s\n",utf8_text); 841 } else if(!strcmp(pid3frame->id,"TPE1")) { 842 used=1; 843 pmp3->artist = utf8_text; 844 DPRINTF(E_DBG,L_SCAN," Artist: %s\n",utf8_text); 845 } else if(!strcmp(pid3frame->id,"TALB")) { 846 used=1; 847 pmp3->album = utf8_text; 848 DPRINTF(E_DBG,L_SCAN," Album: %s\n",utf8_text); 849 } else if(!strcmp(pid3frame->id,"TCOM")) { 850 used=1; 851 pmp3->composer = utf8_text; 852 DPRINTF(E_DBG,L_SCAN," Composer: %s\n",utf8_text); 853 } else if(!strcmp(pid3frame->id,"TIT1")) { 854 used=1; 855 pmp3->grouping = utf8_text; 856 DPRINTF(E_DBG,L_SCAN," Grouping: %s\n",utf8_text); 857 } else if(!strcmp(pid3frame->id,"TPE2")) { 858 used=1; 859 pmp3->orchestra = utf8_text; 860 DPRINTF(E_DBG,L_SCAN," Orchestra: %s\n",utf8_text); 861 } else if(!strcmp(pid3frame->id,"TPE3")) { 862 used=1; 863 pmp3->conductor = utf8_text; 864 DPRINTF(E_DBG,L_SCAN," Conductor: %s\n",utf8_text); 865 } else if(!strcmp(pid3frame->id,"TCON")) { 866 used=1; 867 pmp3->genre = utf8_text; 868 got_numeric_genre=0; 869 DPRINTF(E_DBG,L_SCAN," Genre: %s\n",utf8_text); 870 if(pmp3->genre) { 871 if(!strlen(pmp3->genre)) { 872 genre=WINAMP_GENRE_UNKNOWN; 873 got_numeric_genre=1; 874 } else if (isdigit(pmp3->genre[0])) { 875 genre=atoi(pmp3->genre); 876 got_numeric_genre=1; 877 } else if ((pmp3->genre[0] == '(') && (isdigit(pmp3->genre[1]))) { 878 genre=atoi((char*)&pmp3->genre[1]); 879 got_numeric_genre=1; 880 } 881 882 if(got_numeric_genre) { 883 if((genre < 0) || (genre > WINAMP_GENRE_UNKNOWN)) 884 genre=WINAMP_GENRE_UNKNOWN; 885 free(pmp3->genre); 886 pmp3->genre=strdup(scan_winamp_genre[genre]); 887 } 888 } 889 } else if(!strcmp(pid3frame->id,"COMM")) { 890 used=1; 891 pmp3->comment = utf8_text; 892 DPRINTF(E_DBG,L_SCAN," Comment: %s\n",pmp3->comment); 893 } else if(!strcmp(pid3frame->id,"TPOS")) { 894 tmp=(char*)utf8_text; 895 strsep(&tmp,"/"); 896 if(tmp) { 897 pmp3->total_discs=atoi(tmp); 898 } 899 pmp3->disc=atoi((char*)utf8_text); 900 DPRINTF(E_DBG,L_SCAN," Disc %d of %d\n",pmp3->disc,pmp3->total_discs); 901 } else if(!strcmp(pid3frame->id,"TRCK")) { 902 tmp=(char*)utf8_text; 903 strsep(&tmp,"/"); 904 if(tmp) { 905 pmp3->total_tracks=atoi(tmp); 906 } 907 pmp3->track=atoi((char*)utf8_text); 908 DPRINTF(E_DBG,L_SCAN," Track %d of %d\n",pmp3->track,pmp3->total_tracks); 909 } else if(!strcmp(pid3frame->id,"TDRC")) { 910 pmp3->year = atoi(utf8_text); 911 DPRINTF(E_DBG,L_SCAN," Year: %d\n",pmp3->year); 912 } else if(!strcmp(pid3frame->id,"TLEN")) { 913 pmp3->song_length = atoi(utf8_text); /* now in ms */ 914 DPRINTF(E_DBG,L_SCAN," Length: %d\n", pmp3->song_length); 915 } else if(!strcmp(pid3frame->id,"TBPM")) { 916 pmp3->bpm = atoi(utf8_text); 917 DPRINTF(E_DBG,L_SCAN,"BPM: %d\n", pmp3->bpm); 918 } else if(!strcmp(pid3frame->id,"TCMP")) { /* for id3v2.3 */ 919 pmp3->compilation = (char)atoi(utf8_text); 920 DPRINTF(E_DBG,L_SCAN,"Compilation: %d\n", pmp3->compilation); 921 } 922 } 923 } 924 925 /* can check for non-text tags here */ 926 if((!used) && (have_utf8) && (utf8_text)) 927 free(utf8_text); 928 929 /* v2 COMM tags are a bit different than v1 */ 930 if((!strcmp(pid3frame->id,"COMM")) && (pid3frame->nfields == 4)) { 931 /* Make sure it isn't a application-specific comment... 932 * This currently includes the following: 933 * 934 * iTunes_CDDB_IDs 935 * iTunNORM 936 * 937 * If other apps stuff crap into comment fields, then we'll ignore them 938 * here. 939 */ 940 native_text=id3_field_getstring(&pid3frame->fields[2]); 941 if(native_text) { 942 utf8_text=id3_ucs4_utf8duplicate(native_text); 943 if((utf8_text) && (strncasecmp(utf8_text,"iTun",4) != 0)) { 944 /* it's a real comment */ 945 if(utf8_text) 946 free(utf8_text); 947 948 native_text=id3_field_getfullstring(&pid3frame->fields[3]); 949 if(native_text) { 950 if(pmp3->comment) 951 free(pmp3->comment); 952 utf8_text=id3_ucs4_utf8duplicate(native_text); 953 if(utf8_text) { 954 pmp3->comment=utf8_text; 955 MEMNOTIFY(pmp3->comment); 956 } 957 } 958 } else { 959 if(utf8_text) 960 free(utf8_text); 961 } 962 } 963 } 964 965 index++; 966 } 967 968 id3_file_close(pid3file); 969 DPRINTF(E_DBG,L_SCAN,"Got id3 tag successfully\n"); 970 return 0; 971} 972 973/* 974 * scan_freetags 975 * 976 * Free up the tags that were dynamically allocated 977 */ 978int scan_freetags(MP3FILE *pmp3) { 979 MAYBEFREE(pmp3->title); 980 MAYBEFREE(pmp3->artist); 981 MAYBEFREE(pmp3->album); 982 MAYBEFREE(pmp3->genre); 983 MAYBEFREE(pmp3->comment); 984 MAYBEFREE(pmp3->type); 985 MAYBEFREE(pmp3->composer); 986 MAYBEFREE(pmp3->orchestra); 987 MAYBEFREE(pmp3->conductor); 988 MAYBEFREE(pmp3->grouping); 989 MAYBEFREE(pmp3->description); 990 991 return 0; 992} 993 994 995/* 996 * scan_get_fileinfo 997 * 998 * Dispatch to actual file info handlers 999 */ 1000int scan_get_fileinfo(char *file, MP3FILE *pmp3) { 1001 FILE *infile; 1002 off_t file_size; 1003 1004 taghandler *hdl; 1005 1006 /* dispatch to appropriate tag handler */ 1007 for(hdl = taghandlers ; hdl->suffix ; ++hdl) 1008 if(!strcmp(hdl->suffix, pmp3->type)) 1009 break; 1010 1011 if(hdl->files) 1012 return hdl->files(file, pmp3); 1013 1014 /* a file we don't know anything about... ogg or aiff maybe */ 1015 if(!(infile=fopen(file,"rb"))) { 1016 DPRINTF(E_WARN,L_SCAN,"Could not open %s for reading\n",file); 1017 return -1; 1018 } 1019 1020 /* we can at least get this */ 1021 fseek(infile,0,SEEK_END); 1022 file_size=ftell(infile); 1023 fseek(infile,0,SEEK_SET); 1024 1025 pmp3->file_size=file_size; 1026 1027 fclose(infile); 1028 return 0; 1029} 1030 1031/* 1032 * aac_drilltoatom 1033 * 1034 * Returns the offset of the atom specified by the given path or -1 if 1035 * not found. atom_path is a colon separated list of atoms specifying 1036 * a path from parent node to the target node. All paths must be specified 1037 * from the root. 1038 */ 1039off_t aac_drilltoatom(FILE *aac_fp, char *atom_path, unsigned int *atom_length) 1040{ 1041 long atom_offset; 1042 off_t file_size; 1043 char *cur_p, *end_p; 1044 char atom_name[5]; 1045 1046 fseek(aac_fp, 0, SEEK_END); 1047 file_size = ftell(aac_fp); 1048 rewind(aac_fp); 1049 1050 end_p = atom_path; 1051 while (*end_p != '\0') 1052 { 1053 end_p++; 1054 } 1055 atom_name[4] = '\0'; 1056 cur_p = atom_path; 1057 1058 while (cur_p != NULL) 1059 { 1060 if ((end_p - cur_p) < 4) 1061 { 1062 return -1; 1063 } 1064 strncpy(atom_name, cur_p, 4); 1065 atom_offset = scan_aac_findatom(aac_fp, file_size, atom_name, atom_length); 1066 if (atom_offset == -1) 1067 { 1068 return -1; 1069 } 1070 DPRINTF(E_DBG,L_SCAN,"Found %s atom at off %ld.\n", atom_name, ftell(aac_fp) - 8); 1071 cur_p = strchr(cur_p, ':'); 1072 if (cur_p != NULL) 1073 { 1074 cur_p++; 1075 1076 /* PENDING: Hack to deal with atoms that have extra data in addition 1077 to having child atoms. This should be dealt in a better fashion 1078 than this (table with skip offsets or an actual real mp4 parser.) */ 1079 if (!strcmp(atom_name, "meta")) { 1080 fseek(aac_fp, 4, SEEK_CUR); 1081 } else if (!strcmp(atom_name, "stsd")) { 1082 fseek(aac_fp, 8, SEEK_CUR); 1083 } else if (!strcmp(atom_name, "mp4a")) { 1084 fseek(aac_fp, 28, SEEK_CUR); 1085 } 1086 } 1087 } 1088 1089 return ftell(aac_fp) - 8; 1090} 1091 1092/* 1093 * scan_get_urlfileinfo 1094 * 1095 * Get info from a "url" file -- a media stream file 1096 */ 1097int scan_get_urlfileinfo(char *file, MP3FILE *pmp3) { 1098 FILE *infile; 1099 char *head, *tail; 1100 char linebuffer[256]; 1101 1102 DPRINTF(E_DBG,L_SCAN,"Getting URL file info\n"); 1103 1104 if(!(infile=fopen(file,"rb"))) { 1105 DPRINTF(E_WARN,L_SCAN,"Could not open %s for reading\n",file); 1106 return -1; 1107 } 1108 1109 fgets(linebuffer,sizeof(linebuffer),infile); 1110 while((linebuffer[strlen(linebuffer)-1] == '\n') || 1111 (linebuffer[strlen(linebuffer)-1] == '\r')) { 1112 linebuffer[strlen(linebuffer)-1] = '\0'; 1113 } 1114 1115 head=linebuffer; 1116 tail=strchr(head,','); 1117 if(!tail) { 1118 DPRINTF(E_LOG,L_SCAN,"Badly formatted .url file - must be bitrate,descr,url\n"); 1119 fclose(infile); 1120 return -1; 1121 } 1122 1123 pmp3->bitrate=atoi(head); 1124 head=++tail; 1125 tail=strchr(head,','); 1126 if(!tail) { 1127 DPRINTF(E_LOG,L_SCAN,"Badly formatted .url file - must be bitrate,descr,url\n"); 1128 fclose(infile); 1129 return -1; 1130 } 1131 1132 *tail++='\0'; 1133 1134 pmp3->title=strdup(head); 1135 pmp3->url=strdup(tail); 1136 fclose(infile); 1137 1138 DPRINTF(E_DBG,L_SCAN," Title: %s\n",pmp3->title); 1139 DPRINTF(E_DBG,L_SCAN," Bitrate: %d\n",pmp3->bitrate); 1140 DPRINTF(E_DBG,L_SCAN," URL: %s\n",pmp3->url); 1141 1142 return 0; 1143} 1144 1145/* 1146 * scan_get_aacfileinfo 1147 * 1148 * Get info from the actual aac headers 1149 */ 1150int scan_get_aacfileinfo(char *file, MP3FILE *pmp3) { 1151 FILE *infile; 1152 long atom_offset; 1153 int atom_length; 1154 int sample_size; 1155 int samples; 1156 unsigned int bit_rate; 1157 off_t file_size; 1158 int ms; 1159 unsigned char buffer[2]; 1160 int time = 0; 1161 1162 DPRINTF(E_DBG,L_SCAN,"Getting AAC file info\n"); 1163 1164 if(!(infile=fopen(file,"rb"))) { 1165 DPRINTF(E_WARN,L_SCAN,"Could not open %s for reading\n",file); 1166 return -1; 1167 } 1168 1169 fseek(infile,0,SEEK_END); 1170 file_size=ftell(infile); 1171 fseek(infile,0,SEEK_SET); 1172 1173 pmp3->file_size=file_size; 1174 1175 /* now, hunt for the mvhd atom */ 1176 atom_offset = aac_drilltoatom(infile, "moov:mvhd", &atom_length); 1177 if(atom_offset != -1) { 1178 fseek(infile, 4, SEEK_CUR); 1179 fread((void *)&time, sizeof(int), 1, infile); 1180 time = ntohl(time); 1181 pmp3->time_added = mac_to_unix_time(time); 1182 1183 fread((void *)&time, sizeof(int), 1, infile); 1184 time = ntohl(time); 1185 pmp3->time_modified = mac_to_unix_time(time); 1186 fread((void*)&sample_size,1,sizeof(int),infile); 1187 fread((void*)&samples,1,sizeof(int),infile); 1188 1189 sample_size=ntohl(sample_size); 1190 samples=ntohl(samples); 1191 1192 /* avoid overflowing on large sample_sizes (90000) */ 1193 ms=1000; 1194 while((ms > 9) && (!(sample_size % 10))) { 1195 sample_size /= 10; 1196 ms /= 10; 1197 } 1198 1199 /* DWB: use ms time instead of sec */ 1200 pmp3->song_length=(int)((samples * ms) / sample_size); 1201 1202 DPRINTF(E_DBG,L_SCAN,"Song length: %d seconds\n", pmp3->song_length / 1000); 1203 } 1204 1205 pmp3->bitrate = 0; 1206 1207 /* Get the sample rate from the 'mp4a' atom (timescale). This is also 1208 found in the 'mdhd' atom which is a bit closer but we need to 1209 navigate to the 'mp4a' atom anyways to get to the 'esds' atom. */ 1210 atom_offset = aac_drilltoatom(infile, "moov:trak:mdia:minf:stbl:stsd:mp4a", &atom_length); 1211 if (atom_offset != -1) { 1212 fseek(infile, atom_offset + 32, SEEK_SET); 1213 1214 /* Timescale here seems to be 2 bytes here (the 2 bytes before it are 1215 "reserved") though the timescale in the 'mdhd' atom is 4. Not sure how 1216 this is dealt with when sample rate goes higher than 64K. */ 1217 fread(buffer, sizeof(unsigned char), 2, infile); 1218 1219 pmp3->samplerate = (buffer[0] << 8) | (buffer[1]); 1220 1221 /* Seek to end of atom. */ 1222 fseek(infile, 2, SEEK_CUR); 1223 1224 /* Get the bit rate from the 'esds' atom. We are already positioned 1225 in the parent atom so just scan ahead. */ 1226 atom_offset = scan_aac_findatom(infile, atom_length - (ftell(infile) - atom_offset), "esds", &atom_length); 1227 1228 if (atom_offset != -1) { 1229 fseek(infile, atom_offset + 22, SEEK_CUR); 1230 1231 fread((void *)&bit_rate, sizeof(unsigned int), 1, infile); 1232 1233 pmp3->bitrate = ntohl(bit_rate) / 1000; 1234 } else { 1235 DPRINTF(E_DBG,L_SCAN, "Could not find 'esds' atom to determine bit rate.\n"); 1236 } 1237 1238 } else { 1239 DPRINTF(E_DBG,L_SCAN, "Could not find 'mp4a' atom to determine sample rate.\n"); 1240 } 1241 1242 /* Fallback if we can't find the info in the atoms. */ 1243 if (pmp3->bitrate == 0) { 1244 /* calculate bitrate from song length... Kinda cheesy */ 1245 DPRINTF(E_DBG,L_SCAN, "Could not find 'esds' atom. Calculating bit rate.\n"); 1246 1247 atom_offset=aac_drilltoatom(infile,"mdat",&atom_length); 1248 1249 if ((atom_offset != -1) && (pmp3->song_length)) { 1250 pmp3->bitrate = atom_length / ((pmp3->song_length / 1000) * 128); 1251 } 1252 1253 } 1254 1255 fclose(infile); 1256 return 0; 1257} 1258 1259 1260/** 1261 * Decode an mp3 frame header. Determine layer, bitrate, 1262 * samplerate, etc, and fill in the passed structure. 1263 * 1264 * @param frame 4 byte mp3 frame header 1265 * @param pfi pointer to an allocated SCAN_FRAMEINFO struct 1266 * @return 0 on success (valid frame), -1 otherwise 1267 */ 1268int scan_decode_mp3_frame(unsigned char *frame, SCAN_FRAMEINFO *pfi) { 1269 int ver; 1270 int layer_index; 1271 int sample_index; 1272 int bitrate_index; 1273 int samplerate_index; 1274 1275 if((frame[0] != 0xFF) || (frame[1] < 224)) { 1276 pfi->is_valid=0; 1277 return -1; 1278 } 1279 1280 ver=(frame[1] & 0x18) >> 3; 1281 pfi->layer = 4 - ((frame[1] & 0x6) >> 1); 1282 1283 layer_index=-1; 1284 sample_index=-1; 1285 1286 switch(ver) { 1287 case 0: 1288 pfi->version = 2.5; 1289 sample_index=2; 1290 if(pfi->layer == 1) 1291 layer_index = 3; 1292 if((pfi->layer == 2) || (pfi->layer == 3)) 1293 layer_index = 4; 1294 break; 1295 case 2: 1296 pfi->version = 2.0; 1297 sample_index=1; 1298 if(pfi->layer == 1) 1299 layer_index=3; 1300 if((pfi->layer == 2) || (pfi->layer == 3)) 1301 layer_index=4; 1302 break; 1303 case 3: 1304 pfi->version = 1.0; 1305 sample_index=0; 1306 if(pfi->layer == 1) 1307 layer_index = 0; 1308 if(pfi->layer == 2) 1309 layer_index = 1; 1310 if(pfi->layer == 3) 1311 layer_index = 2; 1312 break; 1313 } 1314 1315 if((layer_index < 0) || (layer_index > 4)) { 1316 pfi->is_valid=0; 1317 return -1; 1318 } 1319 1320 if((sample_index < 0) || (sample_index > 2)) { 1321 pfi->is_valid=0; 1322 return -1; 1323 } 1324 1325 if(pfi->layer==1) pfi->samples_per_frame=384; 1326 if(pfi->layer==2) pfi->samples_per_frame=1152; 1327 if(pfi->layer==3) { 1328 if(pfi->version == 1.0) { 1329 pfi->samples_per_frame=1152; 1330 } else { 1331 pfi->samples_per_frame=576; 1332 } 1333 } 1334 1335 bitrate_index=(frame[2] & 0xF0) >> 4; 1336 samplerate_index=(frame[2] & 0x0C) >> 2; 1337 1338 if((bitrate_index == 0xF) || (bitrate_index==0x0)) { 1339 pfi->is_valid=0; 1340 return -1; 1341 } 1342 1343 if(samplerate_index == 3) { 1344 pfi->is_valid=0; 1345 return -1; 1346 } 1347 1348 pfi->bitrate = scan_br_table[layer_index][bitrate_index]; 1349 pfi->samplerate = scan_sample_table[sample_index][samplerate_index]; 1350 1351 if((frame[3] & 0xC0 >> 6) == 3) 1352 pfi->stereo = 0; 1353 else 1354 pfi->stereo = 1; 1355 1356 if(frame[2] & 0x02) { /* Padding bit set */ 1357 pfi->padding=1; 1358 } else { 1359 pfi->padding=0; 1360 } 1361 1362 if(pfi->version == 1.0) { 1363 if(pfi->stereo) { 1364 pfi->xing_offset=32; 1365 } else { 1366 pfi->xing_offset=17; 1367 } 1368 } else { 1369 if(pfi->stereo) { 1370 pfi->xing_offset=17; 1371 } else { 1372 pfi->xing_offset=9; 1373 } 1374 } 1375 1376 pfi->crc_protected=(frame[1] & 0xFE); 1377 1378 if(pfi->layer == 1) { 1379 pfi->frame_length = (12 * pfi->bitrate * 1000 / pfi->samplerate + pfi->padding) * 4; 1380 } else { 1381 pfi->frame_length = 144 * pfi->bitrate * 1000 / pfi->samplerate + pfi->padding; 1382 } 1383 1384 if((pfi->frame_length > 2880) || (pfi->frame_length <= 0)) { 1385 pfi->is_valid=0; 1386 return -1; 1387 } 1388 1389 pfi->is_valid=1; 1390 return 0; 1391} 1392 1393/** 1394 * Scan 10 frames from the middle of the file and determine an 1395 * average bitrate from that. It might not be as accurate as a full 1396 * frame count, but it's probably Close Enough (tm) 1397 * 1398 * @param infile file to scan for average bitrate 1399 * @param pfi pointer to frame info struct to put the bitrate into 1400 */ 1401void scan_get_average_bitrate(FILE *infile, SCAN_FRAMEINFO *pfi) { 1402 off_t file_size; 1403 unsigned char frame_buffer[2900]; 1404 unsigned char header[4]; 1405 int index=0; 1406 int found=0; 1407 off_t pos; 1408 SCAN_FRAMEINFO fi; 1409 int frame_count=0; 1410 int bitrate_total=0; 1411 1412 DPRINTF(E_DBG,L_SCAN,"Starting averaging bitrate\n"); 1413 1414 fseek(infile,0,SEEK_END); 1415 file_size=ftell(infile); 1416 1417 pos=file_size/2; 1418 1419 /* now, find the first frame */ 1420 fseek(infile,pos,SEEK_SET); 1421 if(fread(frame_buffer,1,sizeof(frame_buffer),infile) != sizeof(frame_buffer)) 1422 return; 1423 1424 while(!found) { 1425 while((frame_buffer[index] != 0xFF) && (index < (sizeof(frame_buffer)-4))) 1426 index++; 1427 1428 if(index >= (sizeof(frame_buffer)-4)) { /* largest mp3 frame is 2880 bytes */ 1429 DPRINTF(E_DBG,L_SCAN,"Could not find frame... quitting\n"); 1430 return; 1431 } 1432 1433 if(!scan_decode_mp3_frame(&frame_buffer[index],&fi)) { 1434 /* see if next frame is valid */ 1435 fseek(infile,pos + index + fi.frame_length,SEEK_SET); 1436 if(fread(header,1,sizeof(header),infile) != sizeof(header)) { 1437 DPRINTF(E_DBG,L_SCAN,"Could not read frame header\n"); 1438 return; 1439 } 1440 1441 if(!scan_decode_mp3_frame(header,&fi)) 1442 found=1; 1443 } 1444 1445 if(!found) 1446 index++; 1447 } 1448 1449 pos += index; 1450 1451 /* found first frame. Let's move */ 1452 while(frame_count < 10) { 1453 fseek(infile,pos,SEEK_SET); 1454 if(fread(header,1,sizeof(header),infile) != sizeof(header)) { 1455 DPRINTF(E_DBG,L_SCAN,"Could not read frame header\n"); 1456 return; 1457 } 1458 if(scan_decode_mp3_frame(header,&fi)) { 1459 DPRINTF(E_DBG,L_SCAN,"Invalid frame header while averaging\n"); 1460 return; 1461 } 1462 1463 bitrate_total += fi.bitrate; 1464 frame_count++; 1465 pos += fi.frame_length; 1466 } 1467 1468 DPRINTF(E_DBG,L_SCAN,"Old bitrate: %d\n",pfi->bitrate); 1469 pfi->bitrate = bitrate_total/frame_count; 1470 DPRINTF(E_DBG,L_SCAN,"New bitrate: %d\n",pfi->bitrate); 1471 1472 return; 1473} 1474 1475/** 1476 * do a full frame-by-frame scan of the file, counting frames 1477 * as we go to try and get a more accurate song length estimate. 1478 * If the song turns out to be CBR, then we'll not set the frame 1479 * length. Instead we'll use the file size estimate, since it is 1480 * more consistent with iTunes. 1481 * 1482 * @param infile file to scan for frame count 1483 * @param pfi pointer to frame info struct to put framecount into 1484 */ 1485void scan_get_frame_count(FILE *infile, SCAN_FRAMEINFO *pfi) { 1486 int pos; 1487 int frames=0; 1488 unsigned char frame_buffer[4]; 1489 SCAN_FRAMEINFO fi; 1490 off_t file_size; 1491 int err=0; 1492 int cbr=1; 1493 int last_bitrate=0; 1494 1495 DPRINTF(E_DBG,L_SCAN,"Starting frame count\n"); 1496 1497 fseek(infile,0,SEEK_END); 1498 file_size=ftell(infile); 1499 1500 pos=pfi->frame_offset; 1501 1502 while(1) { 1503 err=1; 1504 DPRINTF(E_SPAM,L_SCAN,"Seeking to %d\n",pos); 1505 1506 fseek(infile,pos,SEEK_SET); 1507 if(fread(frame_buffer,1,sizeof(frame_buffer),infile) == sizeof(frame_buffer)) { 1508 /* check for valid frame */ 1509 if(!scan_decode_mp3_frame(frame_buffer,&fi)) { 1510 frames++; 1511 pos += fi.frame_length; 1512 err=0; 1513 1514 if((last_bitrate) && (fi.bitrate != last_bitrate)) 1515 cbr=0; 1516 last_bitrate=fi.bitrate; 1517 1518 /* no point in brute scan of a cbr file... */ 1519 if(cbr && (frames > 100)) { 1520 DPRINTF(E_DBG,L_SCAN,"File appears to be CBR... quitting frame count\n"); 1521 return; 1522 } 1523 } 1524 } 1525 1526 if(err) { 1527 if(pos > (file_size - 4096)) { /* probably good enough */ 1528 pfi->number_of_frames=frames; 1529 DPRINTF(E_DBG,L_SCAN,"Estimated frame count: %d\n",frames); 1530 return; 1531 } else { 1532 DPRINTF(E_DBG,L_SCAN,"Frame count aborted on error. Pos=%d, Count=%d\n", 1533 pos, frames); 1534 return; 1535 } 1536 } 1537 } 1538} 1539 1540 1541/** 1542 * Get information from the file headers itself -- like 1543 * song length, bit rate, etc. 1544 * 1545 * @param file File to get info for 1546 * @param pmp3 where to put the found information 1547 */ 1548int scan_get_mp3fileinfo(char *file, MP3FILE *pmp3) { 1549 FILE *infile; 1550 SCAN_ID3HEADER *pid3; 1551 SCAN_FRAMEINFO fi; 1552 unsigned int size=0; 1553 off_t fp_size=0; 1554 off_t file_size; 1555 unsigned char buffer[1024]; 1556 int index; 1557 1558 int xing_flags; 1559 int found; 1560 1561 int first_check; 1562 char frame_buffer[4]; 1563 1564 if(!(infile=fopen(file,"rb"))) { 1565 DPRINTF(E_WARN,L_SCAN,"Could not open %s for reading\n",file); 1566 return -1; 1567 } 1568 1569 memset((void*)&fi,0x00,sizeof(fi)); 1570 1571 fseek(infile,0,SEEK_END); 1572 file_size=ftell(infile); 1573 fseek(infile,0,SEEK_SET); 1574 1575 pmp3->file_size=file_size; 1576 1577 if(fread(buffer,1,sizeof(buffer),infile) != sizeof(buffer)) { 1578 if(ferror(infile)) { 1579 DPRINTF(E_LOG,L_SCAN,"Error reading: %s\n",strerror(errno)); 1580 } else { 1581 DPRINTF(E_LOG,L_SCAN,"Short file: %s\n",file); 1582 } 1583 fclose(infile); 1584 return -1; 1585 } 1586 1587 pid3=(SCAN_ID3HEADER*)buffer; 1588 1589 found=0; 1590 fp_size=0; 1591 1592 if(strncmp(pid3->id,"ID3",3)==0) { 1593 /* found an ID3 header... */ 1594 DPRINTF(E_DBG,L_SCAN,"Found ID3 header\n"); 1595 size = (pid3->size[0] << 21 | pid3->size[1] << 14 | 1596 pid3->size[2] << 7 | pid3->size[3]); 1597 fp_size=size + sizeof(SCAN_ID3HEADER); 1598 first_check=1; 1599 DPRINTF(E_DBG,L_SCAN,"Header length: %d\n",size); 1600 } 1601 1602 index = 0; 1603 1604 /* Here we start the brute-force header seeking. Sure wish there 1605 * weren't so many crappy mp3 files out there 1606 */ 1607 1608 while(!found) { 1609 fseek(infile,fp_size,SEEK_SET); 1610 DPRINTF(E_DBG,L_SCAN,"Reading in new block at %d\n",(int)fp_size); 1611 if(fread(buffer,1,sizeof(buffer),infile) < sizeof(buffer)) { 1612 DPRINTF(E_LOG,L_SCAN,"Short read: %s\n",file); 1613 fclose(infile); 1614 return 0; 1615 } 1616 1617 index=0; 1618 while(!found) { 1619 while((buffer[index] != 0xFF) && (index < (sizeof(buffer)-50))) 1620 index++; 1621 1622 if((first_check) && (index)) { 1623 fp_size=0; 1624 DPRINTF(E_DBG,L_SCAN,"Bad header... dropping back for full frame search\n"); 1625 first_check=0; 1626 break; 1627 } 1628 1629 if(index > sizeof(buffer) - 50) { 1630 fp_size += index; 1631 DPRINTF(E_DBG,L_SCAN,"Block exhausted\n"); 1632 break; 1633 } 1634 1635 if(!scan_decode_mp3_frame(&buffer[index],&fi)) { 1636 DPRINTF(E_DBG,L_SCAN,"valid header at %d\n",index); 1637 if(strncasecmp((char*)&buffer[index+fi.xing_offset+4],"XING",4) == 0) { 1638 /* no need to check further... if there is a xing header there, 1639 * this is definately a valid frame */ 1640 found=1; 1641 fp_size += index; 1642 } else { 1643 /* No Xing... check for next frame */ 1644 DPRINTF(E_DBG,L_SCAN,"Found valid frame at %04x\n",(int)fp_size+index); 1645 DPRINTF(E_DBG,L_SCAN,"Checking at %04x\n",(int)fp_size+index+fi.frame_length); 1646 fseek(infile,fp_size + index + fi.frame_length,SEEK_SET); 1647 if(fread(frame_buffer,1,sizeof(frame_buffer),infile) == sizeof(frame_buffer)) { 1648 if(!scan_decode_mp3_frame(frame_buffer,&fi)) { 1649 found=1; 1650 fp_size += index; 1651 } 1652 } else { 1653 DPRINTF(E_LOG,L_SCAN,"Could not read frame header: %s\n",file); 1654 fclose(infile); 1655 return 0; 1656 } 1657 1658 if(!found) { 1659 DPRINTF(E_DBG,L_SCAN,"Didn't pan out.\n"); 1660 } 1661 } 1662 } 1663 1664 if(!found) { 1665 index++; 1666 if (first_check) { 1667 /* if the header info was wrong about where the data started, 1668 * then start a brute-force scan from the beginning of the file. 1669 * don't want to just scan forward, because we might have already 1670 * missed the xing header 1671 */ 1672 DPRINTF(E_DBG,L_SCAN,"Bad header... dropping back for full frame search\n"); 1673 first_check=0; 1674 fp_size=0; 1675 break; 1676 } 1677 } 1678 } 1679 } 1680 1681 file_size -= fp_size; 1682 fi.frame_offset=fp_size; 1683 1684 if(scan_decode_mp3_frame(&buffer[index],&fi)) { 1685 fclose(infile); 1686 DPRINTF(E_LOG,L_SCAN,"Could not find sync frame: %s\n",file); 1687 DPRINTF(E_LOG,L_SCAN,"If this is a valid mp3 file that plays in " 1688 "other applications, please email me at rpedde@users.sourceforge.net " 1689 "and tell me you got this error. Thanks"); 1690 return 0; 1691 } 1692 1693 DPRINTF(E_DBG,L_SCAN," MPEG Version: %0.1g\n",fi.version); 1694 DPRINTF(E_DBG,L_SCAN," Layer: %d\n",fi.layer); 1695 DPRINTF(E_DBG,L_SCAN," Sample Rate: %d\n",fi.samplerate); 1696 DPRINTF(E_DBG,L_SCAN," Bit Rate: %d\n",fi.bitrate); 1697 1698 /* now check for an XING header */ 1699 if(strncasecmp((char*)&buffer[index+fi.xing_offset+4],"XING",4) == 0) { 1700 DPRINTF(E_DBG,L_SCAN,"Found Xing header\n"); 1701 xing_flags=*((int*)&buffer[index+fi.xing_offset+4+4]); 1702 xing_flags=ntohs(xing_flags); 1703 1704 DPRINTF(E_DBG,L_SCAN,"Xing Flags: %02X\n",xing_flags); 1705 1706 if(xing_flags & 0x1) { 1707 /* Frames field is valid... */ 1708 fi.number_of_frames=*((int*)&buffer[index+fi.xing_offset+4+8]); 1709 fi.number_of_frames=ntohs(fi.number_of_frames); 1710 } 1711 } 1712 1713 if((config.scan_type != 0) && 1714 (fi.number_of_frames == 0) && 1715 (!pmp3->song_length)) { 1716 /* We have no good estimate of song time, and we want more 1717 * aggressive scanning */ 1718 DPRINTF(E_DBG,L_SCAN,"Starting aggressive file length scan\n"); 1719 if(config.scan_type == 1) { 1720 /* get average bitrate */ 1721 scan_get_average_bitrate(infile, &fi); 1722 } else { 1723 /* get full frame count */ 1724 scan_get_frame_count(infile, &fi); 1725 } 1726 } 1727 1728 pmp3->bitrate=fi.bitrate; 1729 pmp3->samplerate=fi.samplerate; 1730 1731 /* guesstimate the file length */ 1732 if(!pmp3->song_length) { /* could have gotten it from the tag */ 1733 /* DWB: use ms time instead of seconds, use doubles to 1734 avoid overflow */ 1735 if(!fi.number_of_frames) { /* not vbr */ 1736 pmp3->song_length = (int) ((double) file_size * 8. / 1737 (double) fi.bitrate); 1738 1739 } else { 1740 pmp3->song_length = (int) ((double)(fi.number_of_frames*fi.samples_per_frame*1000.)/ 1741 (double) fi.samplerate); 1742 } 1743 1744 } 1745 DPRINTF(E_DBG,L_SCAN," Song Length: %d\n",pmp3->song_length); 1746 1747 fclose(infile); 1748 return 0; 1749} 1750 1751/** 1752 * Manually build tags. Set artist to computer/orchestra 1753 * if there is already no artist. Perhaps this could be 1754 * done better, but I'm not sure what else to do here. 1755 * 1756 * @param song MP3FILE of the file to build composite tags for 1757 */ 1758void make_composite_tags(MP3FILE *song) 1759{ 1760 int len; 1761 char fdescr[50]; 1762 1763 len=0; 1764 1765 if(!song->artist && (song->orchestra || song->conductor)) { 1766 if(song->orchestra) 1767 len += strlen(song->orchestra); 1768 if(song->conductor) 1769 len += strlen(song->conductor); 1770 1771 len += 3; 1772 1773 song->artist=(char*)calloc(len, 1); 1774 if(song->artist) { 1775 if(song->orchestra) 1776 strcat(song->artist,song->orchestra); 1777 1778 if(song->orchestra && song->conductor) 1779 strcat(song->artist," - "); 1780 1781 if(song->conductor) 1782 strcat(song->artist,song->conductor); 1783 } 1784 } 1785 1786 sprintf(fdescr,"%s audio file",song->type); 1787 song->description = strdup(fdescr); 1788 1789 if(song->url) { 1790 song->description = strdup("Playlist URL"); 1791 song->data_kind=1; 1792 /* bit of a hack for the roku soundbridge - type *has* to be pls */ 1793 if(song->type) 1794 free(song->type); 1795 song->type = strdup("pls"); 1796 } else { 1797 song->data_kind=0; 1798 } 1799 1800 if(!song->title) 1801 song->title = strdup(song->fname); 1802 1803 /* Ogg used to be set as an item_kind of 4. Dunno why */ 1804 song->item_kind = 2; 1805} 1806