static void mad_close(input_object *obj) { struct mad_local_data *data; if (!obj) return; data = (struct mad_local_data *)obj->local_data; if (data) { if (data->mad_fd) reader_close(data->mad_fd); if (data->mad_init) { mad_synth_finish (&data->synth); mad_frame_finish (&data->frame); mad_stream_finish(&data->stream); data->mad_init = 0; } if (data->frames) { free(data->frames); } free(obj->local_data); obj->local_data = NULL; } }
/*-------------------------------------------------------------------------*/ static int output_tree (void) /* Output the collected dependencies in tree form into the Depfile. * Return 0 on success, RETURN_WARN on a mild error, RETURN_ERROR on a * severe error. */ { int rc; char * pFile; /* Name of file to create */ Node * pNode; pFile = sDepfile; assert(pFile); rc = RETURN_OK; do { if (!pStack) { /* Initialise stack */ pStack = malloc(sizeof(*pStack)); if (!pStack) { printf("%s: Out of memory\n", aPgmName); rc = RETURN_ERROR; break; } memset(pStack, 0, sizeof(*pStack)); } /* Open files */ if (reader_openrw(NULL, pFile)) { perror(aPgmName); printf("%s: Can't write '%s'\n", aPgmName, pFile); rc = RETURN_ERROR; break; } if (bVerbose) { printf(" creating '%s'\r", pFile); fflush(stdout); } /* Walk and output the dependencies and users of the * skeleton sources. */ nodes_initwalk(); while (rc != RETURN_ERROR && NULL != (pNode = nodes_inorder()) ) { if (!(pNode->flags & (NODE_IGNORE)) && (pNode->flags & (NODE_SOURCE|NODE_AVOID)) == NODE_SOURCE && (!IS_SELECT_MODE || (pNode->flags & (NODE_SELECT|NODE_ISELECT))) && !((pNode->flags & NODE_NOTFND) && bIgnoreMiss) ) { rc = output_node_tree(pNode, FALSE, IS_SELECT_MODE); if (!rc) rc = output_node_tree(pNode, TRUE, IS_SELECT_MODE); if (!rc && reader_writen("\n", 1)) rc = RETURN_ERROR; } } /* Walk and output the dependencies and users of the * non-skeleton sources */ nodes_initwalk(); while (rc != RETURN_ERROR && NULL != (pNode = nodes_inorder()) ) { if (!(pNode->flags & (NODE_IGNORE|NODE_SOURCE)) && (!IS_SELECT_MODE || (pNode->flags & (NODE_SELECT|NODE_ISELECT))) && !((pNode->flags & NODE_NOTFND) && bIgnoreMiss) ) { rc = output_node_tree(pNode, FALSE, IS_SELECT_MODE); if (!rc) rc = output_node_tree(pNode, TRUE, IS_SELECT_MODE); if (!rc && reader_writen("\n", 1)) rc = RETURN_ERROR; } } if (rc == RETURN_ERROR) { int i = errno; if (bVerbose) printf("%-78s\r", ""); errno = i; perror(aPgmName); printf("%s: Error writing '%s'.\n", aPgmName, pFile); rc = RETURN_ERROR; break; } if (reader_writeflush()) { int i = errno; if (bVerbose) printf("%-78s\r", ""); errno = i; perror(aPgmName); printf("%s: Error writing '%s'.\n", aPgmName, sDepfile); rc = RETURN_ERROR; break; } /* Finish up */ if (bVerbose) printf("%-78s\r", ""); if (reader_close()) { perror(aPgmName); printf("%s: Error writing '%s'.\n", aPgmName, pFile); rc = RETURN_ERROR; break; } } while(0); while (pStack) { StackNode * pTop; pTop = pStack; pStack = pStack->pNext; free(pTop); } /* Error cleanup */ if (rc == RETURN_ERROR) { reader_close(); remove(pFile); } if (bVerbose && rc != RETURN_ERROR) printf("%-78s\r", ""); return rc; }
/*-------------------------------------------------------------------------*/ 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 output (int bAsMake) /* Output the collected dependencies into the Makefile (bAsMake is TRUE) * resp. into the Depfile (bAsMake is FALSE). * Return 0 on success, RETURN_WARN on a mild error, RETURN_ERROR on a * severe error. */ { int rc; char * pBackup; /* Name of the Makefilebackup */ char * pFile; /* Name of file to create */ Node * pNode; pBackup = NULL; pFile = bAsMake ? sMake : sDepfile; assert(pFile); /* Rename old Makefile if necessary */ if (bAsMake && bMakeExists) { pBackup = (char *)malloc(strlen(sMake)+5); strcpy(pBackup, sMake); strcat(pBackup, ".bak"); remove(pBackup); if (rename(sMake, pBackup)) { perror(aPgmName); printf("%s: Can't rename '%s' to '%s'.\n", aPgmName, sMake, pBackup); free(pBackup); return RETURN_ERROR; } } rc = RETURN_OK; do { char * pTagline; /* Open files */ if (reader_openrw(pBackup, pFile)) { perror(aPgmName); printf("%s: Can't write '%s'\n", aPgmName, pFile); rc = RETURN_ERROR; break; } if (bVerbose) { printf(" %s '%s'\r", (bMakeExists && bAsMake) ? "updating" : "creating", pFile); fflush(stdout); } /* Copy the Makefile up to the tagline */ pTagline = IS_SELECT_MODE ? "# --- DO NOT MODIFY THIS LINE -- SELECTED AUTO-DEPENDS FOLLOW ---\n" : "# --- DO NOT MODIFY THIS LINE -- AUTO-DEPENDS FOLLOW ---\n"; if (bAsMake && reader_copymake(pTagline)) { int i = errno; if (bVerbose) printf("%-78s\r", ""); errno = i; perror(aPgmName); printf("%s: Error copying '%s' to '%s'.\n", aPgmName, pBackup, sMake); rc = RETURN_ERROR; break; } /* Walk and output the dependencies and users. * First all the files specified as root. */ nodes_initwalk(); while (rc != RETURN_ERROR && NULL != (pNode = nodes_inorder()) ) { if ((pNode->flags & (NODE_SOURCE|NODE_AVOID|NODE_NOTFND)) == NODE_SOURCE) rc = output_node_flat(pNode, bAsMake, IS_SELECT_MODE); } /* while (treewalk */ /* Second (if wanted), all the files not specified as root. */ if (RETURN_OK == rc && !bAsMake) { nodes_initwalk(); while (rc != RETURN_ERROR && NULL != (pNode = nodes_inorder()) ) { if ((pNode->flags & (NODE_SOURCE|NODE_AVOID)) != NODE_SOURCE && !(pNode->flags & NODE_NOTFND) ) rc = output_node_flat(pNode, bAsMake, IS_SELECT_MODE); } /* while (treewalk */ } if (rc == RETURN_ERROR) { int i = errno; if (bVerbose) printf("%-78s\r", ""); errno = i; perror(aPgmName); printf("%s: Error writing '%s'.\n", aPgmName, pFile); rc = RETURN_ERROR; break; } pTagline = IS_SELECT_MODE ? "# --- DO NOT MODIFY THIS LINE -- SELECTED AUTO-DEPENDS PRECEDE ---\n" : "# --- DO NOT MODIFY THIS LINE -- AUTO-DEPENDS PRECEDE ---\n"; if (bAsMake && reader_copymake2(pTagline)) { int i = errno; if (bVerbose) printf("%-78s\r", ""); errno = i; perror(aPgmName); printf("%s: Error copying '%s' to '%s'.\n", aPgmName, pBackup, sMake); rc = RETURN_ERROR; break; } else if (!bAsMake && reader_writeflush()) { int i = errno; if (bVerbose) printf("%-78s\r", ""); errno = i; perror(aPgmName); printf("%s: Error writing '%s'.\n", aPgmName, sDepfile); rc = RETURN_ERROR; break; } /* Finish up */ if (bVerbose) printf("%-78s\r", ""); if (reader_close()) { perror(aPgmName); printf("%s: Error writing '%s'.\n", aPgmName, pFile); rc = RETURN_ERROR; break; } if (bAsMake && bMakeExists && chmod(sMake, aMakeStat.st_mode)) { /* perror(aPgmName); */ printf("%s: Warning: Can't update mode of '%s'.\n", aPgmName, sMake); rc = RETURN_WARN; } if (pBackup && remove(pBackup)) { perror(aPgmName); printf("%s: Warning: Can't remove backup '%s'.\n", aPgmName, pBackup); rc = RETURN_WARN; break; } } while(0); /* Error cleanup */ if (rc == RETURN_ERROR) { reader_close(); remove(pFile); if (pBackup && rename(pBackup, sMake)) { perror(aPgmName); printf("%s: Can't restore '%s' from backup '%s'\n", aPgmName, sMake, pBackup); } } if (bVerbose && rc != RETURN_ERROR) printf("%-78s\r", ""); if (pBackup) free(pBackup); return rc; }
/* 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); }
// 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; }
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; } }