/*-------------------------------------------------------------------------*/ static int readfiles (void) /* Read and analyse all files. * If a file can't be read, print a message. * Return 0 if all went well, RETURN_WARN if one of the files could not be * found, RETURN_ERROR if one of the files could not be read properly. */ { int rc; /* Return value */ Node * pNode; /* Node of the file under examination */ int srcRead; /* Number of source files read */ const char * pName; /* Includefile name returned by reader */ rc = 0; srcRead = 0; while (NULL != (pNode = nodes_todo()) ) { int bSystem; /* TRUE if it's a <> include */ if (pNode->flags & NODE_NOTFND) continue; if (!reader_open(pNode->pName)) { rc = readerror(pNode, rc, FALSE); continue; } /* If (can't open pNode->pName) */ if (bVerbose) { printf(" reading %-65s\r", pNode->pName); fflush(stdout); } while (NULL != (pName = reader_get(&bSystem)) ) { int index; /* index into aIncl[] */ Node * pChild; /* Node of included file, NULL if not found */ Node * pChFirst; /* First 'direct' child node */ for (index = -1, pChild = NULL, pChFirst = NULL ; !pChild && index < iInclSize ; index++) { char aName[FILENAME_MAX+1]; char * pCName; /* aName[] cleaned up */ char * pCBase; /* Namepart in *pCName */ /* Don't look for system includes in non-system directories. */ if (index >= 0 && bSplitPath && bSystem && !aIncl[index].bSysPath) continue; aName[FILENAME_MAX] = '\0'; if (index < 0) { /* Special case: look directly for the filename. * If bSplitPath is given, or if the filename is absolute, * use it unchanged. Else, use the path of the including * file as anchor. */ if (bSplitPath || '/' == *pName) strcpy(aName, pName); else { size_t oFilename; oFilename = (unsigned)(pNode->pBase - pNode->pName); strncpy(aName, pNode->pName, oFilename); strcpy(aName+oFilename, pName); } } else { /* Standard case: build the pathname from the include * pathname. */ strcpy(aName, aIncl[index].pPath); strcat(aName, pName); } /* Cleanup the filename and check if it is listed in * the tree */ pCName = util_getpath(aName, &pCBase); if (!pCName) { if (bVerbose) printf("%-78s\r", ""); reader_close(); exit_nomem(" (readfiles: 1. util_getpath)"); } pChild = nodes_findadd(pCName, TRUE); if (pChild->flags & NODE_NEW) { /* New file: check if it exists and set up the * node properly */ struct stat aStat; pChild->pName = pCName; pChild->pBase = pCBase; if (index >= 0) { pChild->pPath = util_getpath(pName, NULL); pChild->iInclude = index; } else if (pNode->iInclude < 0 || pNode->flags & NODE_SOURCE) { pChild->pPath = util_getpath(pCName, NULL); pChild->iInclude = -1; } else { strcpy(aName, pNode->pPath); strcat(aName, pName); pChild->pPath = util_getpath(aName, NULL); pChild->iInclude = pNode->iInclude; } if (!pChild->pPath) { if (bVerbose) printf("%-78s\r", ""); reader_close(); exit_nomem(" (readfiles: 2. util_getpath)"); } pChild->flags = (short)(bSystem ? NODE_SYSTEM : 0); /* It's ok to not find <>-includes - they just don't have * to appear in the output then. */ if (stat(pCName, &aStat)) pChild->flags |= NODE_NOTFND | (bSystem ? NODE_IGNORE : 0); } /* The pChFirst is needed if the include can't be found * so we can keep track from where it is included. */ if (index < 0) pChFirst = pChild; /* Test if the file for pChild exists. */ if (pChild->flags & NODE_NOTFND) { /* Make sure that the file is listed in the warnings * if appropriate. */ if (index >= 0) pChild->flags |= NODE_IGNORE; else if ((pChild->flags & NODE_IGNORE) && !bSystem) pChild->flags ^= NODE_IGNORE; pChild = NULL; } /* For absolute pNames, only index -1 is tried */ if ('/' == *pName) break; } /* for (index = -1..iInclSize) */ assert(pChFirst != NULL); if (pChild ? nodes_depend(pChild, pNode) : nodes_depend(pChFirst, pNode)) { if (bVerbose) printf("%-78s\r", ""); reader_close(); exit_nomem(" (readfiles: nodes_depend)"); } } /* while(get pName from file */ if (bVerbose) printf("%-78s\r", ""); if (!reader_eof() || reader_close()) { perror(aPgmName); printf("%s: Error reading '%s'\n", aPgmName, pNode->pName); rc = RETURN_ERROR; } else if (pNode->flags & NODE_SOURCE) { srcRead++; } } /* while (nodes_todo()) */ if (!srcRead) { printf("%s: No source file read.\n", aPgmName); rc = RETURN_ERROR; } /* Walk tree and print all include files not found */ nodes_initwalk(); while (rc != RETURN_ERROR && NULL != (pNode = nodes_inorder()) ) { if ((pNode->flags & (NODE_NOTFND|NODE_IGNORE)) == NODE_NOTFND) { if (pNode->pUsers) rc = readerror(pNode, rc, TRUE); else pNode->flags |= NODE_IGNORE; } } if (bVerbose) fflush(stdout); return rc; }
static int mad_open(input_object *obj, const char *path) { struct mad_local_data *data; char *p; int mode; if (!obj) return 0; obj->local_data = malloc(sizeof(struct mad_local_data)); if (!obj->local_data) { puts("failed to allocate local data"); return 0; } data = (struct mad_local_data *)obj->local_data; memset(data, 0, sizeof(struct mad_local_data)); if ((data->mad_fd = reader_open(path, &reader_status, obj)) == NULL) { fprintf(stderr, "mad_open(obj, %s) failed\n", path); free(obj->local_data); obj->local_data = NULL; return 0; } obj->flags = 0; if (strncasecmp(path, "http://", 7) == 0) { obj->flags |= P_STREAMBASED; strcpy(data->sinfo.status, "Prebuffering"); } else { obj->flags |= P_FILEBASED; } if (!reader_seekable(data->mad_fd)) { data->seekable = 0; } else { obj->flags |= P_SEEK; obj->flags |= P_PERFECTSEEK; data->seekable = 1; } obj->flags |= P_REENTRANT; mad_init_decoder(data); memset(&data->xing, 0, sizeof(struct xing)); xing_init (&data->xing); data->mad_init = 1; fill_buffer(data, -1); //alsaplayer_error("initial bytes_avail = %d", data->bytes_avail); if (obj->flags & P_PERFECTSEEK) { data->offset = find_initial_frame(data->mad_map, data->bytes_avail < STREAM_BUFFER_SIZE ? data->bytes_avail : STREAM_BUFFER_SIZE); } else { data->offset = 0; } data->highest_frame = 0; if (data->offset < 0) { //fprintf(stderr, "mad_open() couldn't find valid MPEG header\n"); data->offset = 0; } //alsaplayer_error("data->offset = %d", data->offset); if (data->offset > data->bytes_avail) { data->seekable = 1; //alsaplayer_error("Need to refill buffer (data->offset = %d)", data->offset); fill_buffer(data, 0); mad_stream_buffer(&data->stream, data->mad_map, data->bytes_avail); } else { mad_stream_buffer(&data->stream, data->mad_map + data->offset, data->bytes_avail - data->offset); data->bytes_avail -= data->offset; } first_frame: if ((mad_header_decode(&data->frame.header, &data->stream) == -1)) { switch (data->stream.error) { case MAD_ERROR_BUFLEN: return 0; case MAD_ERROR_LOSTSYNC: case MAD_ERROR_BADEMPHASIS: case MAD_ERROR_BADBITRATE: case MAD_ERROR_BADLAYER: case MAD_ERROR_BADSAMPLERATE: //alsaplayer_error("Error %x (frame %d)", data->stream.error, data->current_frame); data->bytes_avail-=(data->stream.next_frame - data->stream.this_frame); goto first_frame; break; case MAD_ERROR_BADBITALLOC: return 0; case MAD_ERROR_BADCRC: alsaplayer_error("MAD_ERROR_BADCRC: %s", error_str(data->stream.error, data->str)); case MAD_ERROR_BADBIGVALUES: case MAD_ERROR_BADDATAPTR: break; default: alsaplayer_error("ERROR: %s", error_str(data->stream.error, data->str)); alsaplayer_error("No valid frame found at start (pos: %d, error: 0x%x --> %x %x %x %x) (%s)", data->offset, data->stream.error, data->stream.this_frame[0], data->stream.this_frame[1], data->stream.this_frame[2], data->stream.this_frame[3],path); return 0; } } mad_frame_decode(&data->frame, &data->stream); /* alsaplayer_error("xing parsing...%x %x %x %x (%x %d)", data->stream.this_frame[0], data->stream.this_frame[1], data->stream.this_frame[2], data->stream.this_frame[3], data->stream.anc_ptr, data->stream.anc_bitlen); */ if (xing_parse(&data->xing, data->stream.anc_ptr, data->stream.anc_bitlen) == 0) { // We use the xing data later on } mode = (data->frame.header.mode == MAD_MODE_SINGLE_CHANNEL) ? 1 : 2; data->samplerate = data->frame.header.samplerate; data->bitrate = data->frame.header.bitrate; mad_synth_frame (&data->synth, &data->frame); { struct mad_pcm *pcm = &data->synth.pcm; obj->nr_channels = pcm->channels; //alsaplayer_error("nr_channels = %d", obj->nr_channels); } //alsaplayer_error("Initial: %d, %d, %d", data->samplerate, data->bitrate, obj->nr_channels); /* Calculate some values */ data->bytes_avail = data->stream.bufend - data->stream.next_frame; { int64_t time; int64_t samples; int64_t frames; long oldpos = reader_tell(data->mad_fd); reader_seek(data->mad_fd, 0, SEEK_END); data->filesize = reader_tell(data->mad_fd); data->filesize -= data->offset; reader_seek(data->mad_fd, oldpos, SEEK_SET); if (data->bitrate) time = (data->filesize * 8) / (data->bitrate); else time = 0; samples = 32 * MAD_NSBSAMPLES(&data->frame.header); obj->frame_size = (int) samples << 2; /* Assume 16-bit stereo */ frames = data->samplerate * (time+1) / samples; if (data->xing.flags & XING_FRAMES) { obj->nr_frames = data->xing.frames; } else { obj->nr_frames = (int) frames; } obj->nr_tracks = 1; } /* Determine if nr_frames makes sense */ if (!(obj->flags & P_SEEK) && (obj->flags & P_STREAMBASED)) { obj->nr_frames = -1; } /* Allocate frame index */ if (!data->seekable || obj->nr_frames > 1000000 || (data->frames = (ssize_t *)malloc((obj->nr_frames + FRAME_RESERVE) * sizeof(ssize_t))) == NULL) { data->seekable = 0; // Given really } else { data->seekable = 1; data->frames[0] = 0; } data->mad_init = 1; p = strrchr(path, '/'); if (p) { strcpy(data->filename, ++p); } else { strcpy(data->filename, path); } strcpy(data->path, path); data->parse_id3 = prefs_get_bool(ap_prefs, "mad", "parse_id3", 1); return 1; }
// Returns: // E_PL_SUCCESS on success, // E_PL_DUBIOUS if file doesn't appear to be in a known format, // E_PL_BAD if file definitely isn't in a known format. // If "force" is true, will try to load anyway instead of returning E_PL_DUBIOUS enum plist_result Playlist::Load(std::string const &uri, unsigned position, bool force) { int pls = 0; // Check extension if(!force) { if(!is_playlist(uri.c_str())) return E_PL_DUBIOUS; } // Open Playlist reader_type *f = reader_open (uri.c_str(), NULL, NULL); if (!f) return E_PL_BAD; // Base part of m3u uri, might need it later std::string base = uri; std::string::size_type i = base.rfind('/'); if (i != std::string::npos) base.erase(i); base += '/'; // Read the file char path[READBUFSIZE + 1]; memset(path, 0,READBUFSIZE); std::vector<std::string> newfiles; // Give up if too many failures (so we don't wait for almost ever if // someone tries clicking on an mp3 file...) // However, if its just that some of the files don't exist anymore, // don't give up. unsigned successes = 0; unsigned failures = 0; while(failures < MAXLOADFAILURES || failures < successes) { char *s, *p; if (!reader_readline (f, path, READBUFSIZE)) break; std::string newfile; if (*path == '#') { // Comment... skip it for now continue; } else if ((s=strstr(path, "File"))) { p = strstr(s, "="); if (p) { p++; // Make sure there are no trailing EOL's if ((s = strstr(p, "\r"))) *s = '\0'; if ((s = strstr(p, "\n"))) *s = '\0'; //alsaplayer_error("URI: %s", p); newfile = std::string(p); } else { continue; } } else if (pls && (strncasecmp(path, "Title", 5) == 0 || strncasecmp(path, "Length", 6) == 0)) { /* Ignore title/length lines */ continue; } else if (*path=='/') { newfile = std::string(path); /* These 2 */ } else if (reader_can_handle (path)) { newfile = std::string(path); /* Should be one */ } else if (*path == '\0') { // No path failures++; continue; } else { // This is probably realtive URI or not supported URI type. newfile = base + std::string(path); } // Test result if (!reader_can_handle (newfile.c_str())) continue; // Add this file newfiles.push_back(newfile); successes++; } // Entire file should be loaded /* if (!reader_eof(f)) { reader_close (f); return E_PL_BAD; } */ reader_close (f); // Do the insert Insert(newfiles, position); return E_PL_SUCCESS; }
/* Trying to fill info from id3 tagged file */ static void parse_id3 (const char *path, stream_info *info) { void *fd; unsigned char buf [2024]; unsigned char g; /* Open stream */ fd = reader_open (path, NULL, NULL); if (!fd) return; /* --------------------------------------------------- */ /* Trying to load id3v2 tags */ if (reader_read (buf, 10, fd) != 10) { reader_close (fd); return; } if (memcmp(buf, "ID3", 3) == 0) { /* Parse id3v2 tags */ /* Header */ unsigned char major_version = buf [3]; int f_unsynchronization = buf [5] & (1<<7); int f_extended_header = buf [5] & (1<<6); int f_experimental = buf [5] & (1<<5); int header_size = from_synchsafe4 (buf + 6); int name_size = buf [3] == 2 ? 3 : 4; int ext_size = 0; if (f_extended_header) { // alsaplayer_error ("FIXME: Extended header found in mp3." // "Please contact alsaplayer team.\n" // "Filename: %s", path); // reader_close (fd); // return; ext_size = 1; //stupid but should do } if (f_unsynchronization) { alsaplayer_error ("FIXME: f_unsynchronization is set." "Please contact alsaplayer team.\n" "Filename: %s", path); reader_close (fd); return; } if (f_experimental) { alsaplayer_error ("FIXME: f_experimental is set." "Please contact alsaplayer team.\n" "Filename: %s", path); reader_close (fd); return; } if (ext_size) { char b[4]; if (reader_read (b, 4, fd) != 4) { reader_close(fd); return; } if (major_version == 2) ext_size = from_synchsafe3 (b); else ext_size = from_synchsafe4 (b); if (reader_seek (fd, ext_size - 4, SEEK_CUR) < 0) { reader_close (fd); return; } } /* -- -- read frames -- -- */ while (reader_tell (fd) <= header_size + 10) { unsigned int size; /* Get name of this frame */ if (reader_read (buf, name_size, fd) != (unsigned)name_size) { reader_close (fd); return; } if (buf [0] == '\0') break; if (buf [0] < 'A') break; if (buf [0] > 'Z') break; /* Get size */ if (major_version == 2) { char sb [3]; if (reader_read (sb, 3, fd) != 3) { reader_close (fd); return; } size = from_synchsafe3 (sb); } else { char sb [4]; if (reader_read (sb, 4, fd) != 4) { reader_close (fd); return; } size = from_synchsafe4 (sb); } /* skip frame flags */ // if (reader_seek (fd, 1, SEEK_CUR) == -1) { // reader_close (fd); // return; // } int start = 0; // read them char b[2]; if (reader_read (b, 2, fd) != 2) { reader_close (fd); return; } else { if (b[1] & (1 << 6)) { // printf ("Grouping added\n"); start++; } if (b[1] & (1 << 3)) { // printf ("Compression added\n"); } if (b[1] & (1 << 2)) { // printf ("Encryption added\n"); } if (b[1] & (1 << 1)) { // printf ("Unsynch added\n"); } if (b[1] & (1 << 0)) { // printf ("Length added\n"); start+=4; } } if (size>=1024) { /* I will not support such long tags... * Only if someone ask for it... * not now... */ if (reader_seek (fd, size, SEEK_CUR) == -1) { reader_close (fd); return; } continue; } /* read info */ if (reader_read (buf + name_size, size, fd) != size) { reader_close (fd); return; } /* !!! Ok. There we have frame name and data. */ /* Lets use it. */ if (name_size == 4) { if (memcmp (buf, "TIT2", 4)==0) fill_from_id3v2 (info->title, buf + name_size + start, sizeof (info->title), size - start); else if (memcmp (buf, "TPE1", 4)==0) fill_from_id3v2 (info->artist, buf + name_size + start, sizeof (info->artist), size - start); else if (memcmp (buf, "TALB", 4)==0) fill_from_id3v2 (info->album, buf + name_size + start, sizeof (info->album), size - start); else if (memcmp (buf, "TYER", 4)==0) fill_from_id3v2 (info->year, buf + name_size + start, sizeof (info->year), size - start); else if (memcmp (buf, "COMM", 4)==0) fill_from_id3v2 (info->comment, buf + name_size + start, sizeof (info->comment), size - start); else if (memcmp (buf, "TRCK", 4)==0) fill_from_id3v2 (info->track, buf + name_size + start, sizeof (info->track), size - start); else if (memcmp (buf, "TCON", 4)==0) { /* Genre */ /* TODO: Optimize duplicated code */ unsigned int gindex; if (sscanf (buf + name_size + start +1, "(%u)", &gindex)==1) { if (gindex==255) *info->genre = '\0'; else if (sizeof (genres)/sizeof(char*) <= gindex) snprintf (info->genre, sizeof (info->genre), "(%u)", gindex); else snprintf (info->genre, sizeof (info->genre), "%s", genres[gindex]); } else fill_from_id3v2 (info->genre, buf + name_size + start, sizeof (info->genre), size - start); } } /* end of 'if name_size == 4' */ } /* end of frames read */ /* end parsing */ reader_close (fd); return; } /* end of id3v2 parsing */ /* --------------------------------------------------- */ /* Trying to load id3v1 tags */ if (reader_seek (fd, -128, SEEK_END) == -1) { reader_close (fd); return; } if (reader_read (buf, 128, fd) != 128) { reader_close (fd); return; } if (memcmp(buf, "TAG", 3) == 0) { /* ID3v1 frame found */ /* title */ strncpy (info->title, buf + 3, 30); rstrip (info->title); /* artist */ strncpy (info->artist, buf + 33, 30); rstrip (info->artist); /* album */ strncpy (info->album, buf + 63, 30); rstrip (info->album); /* year */ strncpy (info->year, buf + 93, 4); rstrip (info->year); /* comment */ strncpy (info->comment, buf + 97, 28); rstrip (info->comment); /* track number */ if (buf [125] == '\0') snprintf (info->track, sizeof (info->track), "%u", buf [126]); /* genre */ g = buf [127]; if (g==255) *info->genre = '\0'; else if (sizeof (genres)/sizeof(char*) <= g) snprintf (info->genre, sizeof (info->genre), "(%u)", g); else snprintf (info->genre, sizeof (info->genre), "%s", genres[g]); } /* end of id3v1 parsing */ reader_close (fd); }
static int flac_open (input_object * obj, const char * name) { if (!obj) return 0; if (!name) return 0; reader_type * rdr = reader_open (name, NULL, NULL); if (!rdr) { alsaplayer_error ("flac_open: reader_open failed"); return 0; } obj->flags = 0; Flac::FlacStream * f = 0; try { if (Flac::FlacStream::isFlacStream (name)) { if (reader_seekable (rdr)) { f = new Flac::FlacSeekableStream (name, rdr); obj->flags |= P_SEEK | P_PERFECTSEEK; } else f = new Flac::FlacStream (name, rdr); } #ifdef HAVE_LIBOGGFLC else { f = new Flac::OggFlacStream (name, rdr); } #endif } catch (...) { alsaplayer_error ("flac_open: unable to allocate memory for plugin."); delete f; reader_close (rdr); return 0; } if (f && f->open ()) { obj->block_size = f->engine ()->apBlockSize (); // attach a song info tag if (Flac::FlacTag::hasTag (f->name ())) { Flac::FlacTag * t = Flac::FlacTag::newTag (f->name ()); f->setTag (t); } if (strncasecmp (name, "http://", 7) == 0) obj->flags |= P_STREAMBASED; else obj->flags |= P_FILEBASED; obj->nr_channels = f->engine ()->apChannels (); obj->flags |= P_REENTRANT; obj->nr_blocks = f->engine ()->apBlocks (); obj->nr_tracks = 1; obj->ready = 1; obj->local_data = (void *) f; return 1; } else { alsaplayer_error ("flac_open: unable to open flac stream or " "unsupported flac stream (%s)", name); delete f; obj->block_size = 0; obj->nr_channels = 0; obj->flags = 0; obj->nr_blocks = 0; obj->nr_tracks = 0; obj->ready = 0; obj->local_data = 0; return 0; } }