int test_whence(const char* path, int scan_before) { int err = MPG123_OK; mpg123_handle* mh = NULL; off_t length, pos; mh = mpg123_new(NULL, &err ); if(mh == NULL) return -1; err = mpg123_open(mh, path ); if(err != MPG123_OK) return -1; if(scan_before) mpg123_scan(mh); pos = mpg123_seek( mh, 0, SEEK_END); if(pos < 0){ error1("seek failed: %s", mpg123_strerror(mh)); return -1; } pos = mpg123_tell(mh); length = mpg123_length(mh); /* Later: Read samples and compare different whence values with identical seek positions. */ mpg123_close(mh); mpg123_delete(mh); fprintf(stdout, "length %"OFF_P" vs. pos %"OFF_P"\n", length, pos); return (pos == length) ? 0 : -1; }
int in_mp3_getinfo(void *m, track_t *track) { #if 0 int meta; mpg123_id3v2 *v2; mpg123_id3v1 *v1; v1 = NULL; v2 = NULL; /* move those to some global string db */ info->artist = "Unknown Artist"; info->title = "Unknown Title"; mpg123_scan(m); meta = mpg123_meta_check(m); /* XXX - generalize this, toooooooo ugly */ if ((meta & MPG123_ID3) && (mpg123_id3(m, &v1, &v2) == MPG123_OK)) { if (v1 != NULL) { info->artist = (char *)malloc(31); strncpy(info->artist, v1->artist, 30); if (info->artist[30]) { info->artist = realloc(info->artist, 31); assert(info->artist != NULL); info->artist[31] = '\0'; } info->title = (char *)malloc(31); strncpy(info->title, v1->title, 30); if (info->title[30]) { info->title = realloc(info->title, 31); assert(info->title != NULL); info->title[31] = '\0'; } } if (v2 != NULL) { if (v2->artist != NULL) { info->artist = (char *)malloc(v2->artist->size + 2); strncpy(info->artist, v2->artist->p, v2->artist->size); if (info->artist[v2->artist->size]) { info->artist[v2->artist->size + 1] = '\0'; } } if (v2->title != NULL) { info->title = (char *)malloc(v2->title->size + 2); strncpy(info->title, v2->title->p, v2->title->size); if (info->title[v2->title->size]) { info->title[v2->title->size + 1] = '\0'; } } } } #endif return REPLAY_ERR; }
bool MP3InputStream::initialize(FilePtr file) { m_file = file; m_seekable = m_file->seek(0, File::END); m_file->seek(0, File::BEGIN); m_eof = false; mh = mpg123_new(NULL,NULL); if (mpg123_open_feed(mh) != MPG123_OK) { return false; } m_input_position = 0; m_input_length = 0; m_decode_buffer = new u8[4608]; // as I have no reason to set a specific value, I used the one from MPaudec if (!m_decode_buffer) return false; m_first_frame = true; if (m_seekable) { // Scan the file to determine the length. mpg123_scan(mh); } // this should fill in the audio format if it isn't set already return decodeFrame(); }
void input_mpg123::read_metadata() { mpg123_scan(handle); int meta = mpg123_meta_check(handle); if (!(meta & MPG123_ID3)) { return; } mpg123_id3v1 *v1; mpg123_id3v2 *v2; if (mpg123_id3(handle, &v1, &v2) != MPG123_OK) { return; } if (v2) { title = decode_string<unc::utf8>(v2->title); artist = decode_string<unc::utf8>(v2->artist); album = decode_string<unc::utf8>(v2->album); year = decode_string<unc::utf8>(v2->year); return; } if (v1) { title = decode_byte_string<unc::latin1>(v1->title); artist = decode_byte_string<unc::latin1>(v1->artist); album = decode_byte_string<unc::latin1>(v1->album); year = decode_byte_string<unc::latin1>(v1->year); return; } }
int main(int argc, char **argv) { mpg123_handle *m; int i; if(argc < 2) { fprintf(stderr, "\nI will give you the estimated and exact sample lengths of MPEG audio files.\n"); fprintf(stderr, "\nUsage: %s <mpeg audio file list>\n\n", argv[0]); return -1; } mpg123_init(); m = mpg123_new(NULL, NULL); mpg123_param(m, MPG123_RESYNC_LIMIT, -1, 0); /* New in library version 0.0.1 . */ for(i = 1; i < argc; ++i) { off_t a, b; mpg123_open(m, argv[i]); a = mpg123_length(m); mpg123_scan(m); b = mpg123_length(m); mpg123_close(m); printf("File %i: estimated %li vs. scanned %li\n", i, (long)a, (long)b); } mpg123_delete(m); mpg123_exit(); return 0; }
AudioSourceMpg123::AudioSourceMpg123(const char* filename) : AudioSource(filename) { rate_ = 0; channelCount_ = 0; sampleCount_ = 0; int err = MPG123_OK; mpg123_handle* mh = mpg123_new(NULL, &err); if (mh == NULL || err != MPG123_OK) return; /* if (mpg123_open(mh, filename) != MPG123_OK) { mpg123_delete(mh); return; } */ G_FILE* file = g_fopen(filename, "rb"); if (file == NULL) { mpg123_delete(mh); return; } mpg123_replace_reader_handle(mh, mpg123read, mpg123lseek, mpg123cleanup); if (mpg123_open_handle(mh, file) != MPG123_OK) { mpg123_delete(mh); return; } int channels = 0, encoding = 0; long rate = 0; if (mpg123_getformat(mh, &rate, &channels, &encoding) != MPG123_OK) { mpg123_delete(mh); return; } // Signed 16 is the default output format anyways (encoding == MPG123_ENC_SIGNED_16); // it would actually by only different if we forced it. // Ensure that this output format will not change (it could, when we allow it). mpg123_format_none(mh); mpg123_format(mh, rate, channels, encoding); rate_ = rate; channelCount_ = channels; mpg123_scan(mh); sampleCount_ = mpg123_length(mh); mpg123_close(mh); mpg123_delete(mh); }
VALUE rb_mpg123_length(VALUE self) { /* * mpg123_length() only returns an estimated duration * if the song hasn't previously been scanned. * This can be incorrect if, for example, the song is corrupted * and cannot be played after a certain point. * Run mpg123_scan() first to get an accurate length reading. */ mpg123_scan(DATA_PTR(self)); return INT2FIX(mpg123_length(DATA_PTR(self))); }
bool Mp3::openFromFile(const std::string& filename) { stop(); if (myBuffer) delete [] myBuffer; if(myHandle) mpg123_close(myHandle); mpg123_param(myHandle, MPG123_RESYNC_LIMIT, -1, 0); #ifndef DEBUG mpg123_param(myHandle, MPG123_ADD_FLAGS, 32 , 0); #endif if (mpg123_open(myHandle, filename.c_str()) != MPG123_OK) { std::cerr << mpg123_strerror(myHandle) << std::endl; return false; } //This should improve myDuration calculation, but generates frankenstein streams¿? //Warning: Real sample count 9505152 differs from given gapless sample count -1152. Frankenstein stream if(mpg123_scan(myHandle) != MPG123_OK) { std::cerr << "Failed when scanning " << std::endl; return false; } long rate = 0; int channels = 0, encoding = 0; if (mpg123_getformat(myHandle, &rate, &channels, &encoding) != MPG123_OK) { std::cerr << "Failed to get format information for 464480e9ee6eb73bc2b768d7e3d7865aa432fc34quot;" << filename << "464480e9ee6eb73bc2b768d7e3d7865aa432fc34quot;" << std::endl; return false; } myDuration = sf::Time(sf::milliseconds(1 + 1000*mpg123_length(myHandle)/rate)); myBufferSize = mpg123_outblock(myHandle); myBuffer = new unsigned char[myBufferSize]; if (!myBuffer) { std::cerr << "Failed to reserve memory for decoding one frame for 464480e9ee6eb73bc2b768d7e3d7865aa432fc34quot;" << filename << "464480e9ee6eb73bc2b768d7e3d7865aa432fc34quot;" << std::endl; return false; } sf::SoundStream::initialize(channels, rate); return true; }
static bool is_mp3(FILE *fp, struct file_type **ft) { mpg123_init(); int err; mpg123_handle *mh = mpg123_new(NULL, &err); if (mh == NULL) { fprintf(stderr, "Could not create mpg123 handle: %s\n", mpg123_plain_strerror(err)); return false; } long pos = ftell(fp); if (mpg123_open_fd(mh, fileno(fp)) != MPG123_OK) { fseek(fp, pos, SEEK_SET); return false; } mpg123_scan(mh); struct mpg123_frameinfo fi; mpg123_info(mh, &fi); if (mpg123_format(mh, fi.rate, MPG123_STEREO, MPG123_ENC_SIGNED_16) != MPG123_OK) { fseek(fp, pos, SEEK_SET); return false; } off_t length = mpg123_length(mh); struct mp3_format *fmt = calloc(sizeof(*fmt), 1); *ft = &fmt->ft; fmt->mh = mh; fmt->tpf = mpg123_tpf(mh); fmt->ft.channels = 2; fmt->ft.position = 0; fmt->ft.length = (length + (fi.rate / 2)) / fi.rate; fmt->ft.sample_rate = fi.rate; fmt->ft.sample_size = 2; fmt->ft.sample_type = ST_SIGNED_INTEGER_LE; fmt->ft.bitrate = (double)fi.abr_rate; return true; }
int main(int argc, char **argv) { int err; int ret = 0; mpg123_handle *mh; mpg123_id3v2 *id3; if(argc < 2) { printf("Gimme a MPEG file name...\n"); return 0; } mpg123_init(); mh = mpg123_new(NULL, &err); if(err != MPG123_OK) goto badend; mpg123_param(mh, MPG123_ADD_FLAGS, MPG123_PLAIN_ID3TEXT, 0.); err = mpg123_open(mh, argv[1]); if(err != MPG123_OK) goto badend; err = mpg123_scan(mh); if(err != MPG123_OK) goto badend; err = mpg123_id3(mh, NULL, &id3); if(err != MPG123_OK) goto badend; if(id3 == NULL) { error("No ID3 data found."); goto badend; } print_field("artist", id3->artist); print_field("title", id3->title); print_field("album", id3->album); print_field("comment", id3->comment); goto end; badend: ret = -1; end: mpg123_delete(mh); mpg123_exit(); return ret; }
double Mpg123Decoder::getDuration() { // Only calculate the duration if we haven't done so already. if (duration == -2.0) { mpg123_scan(handle); off_t length = mpg123_length(handle); if (length == MPG123_ERR || length < 0) duration = -1.0; else duration = (double) length / (double) sampleRate; } return duration; }
int collect(struct seeko *so) { off_t pos_count = 0; off_t length; int err = MPG123_OK; size_t posi = 0; mpg123_scan(m); length = mpg123_length(m); printf("Estimated length: %"OFF_P"\n", (off_p)length); /* Compute the interesting positions */ fix_positions(so, length); /* Default format is always 16bit int, rate does not matter. Let's just get the channel count and not bother. */ while(err == MPG123_OK) { short buff[1024]; /* choosing a non-divider of mpeg frame size on purpose */ size_t got = 0; off_t buffsamples; err = mpg123_read(m, (unsigned char*)buff, 1024*sizeof(short), &got); buffsamples = got/(channels*sizeof(short)); while(so->position[posi] < pos_count+buffsamples) { size_t i = (so->position[posi]-pos_count)*channels; printf("got sample %"SIZE_P" (%"OFF_P")\n", (size_p)posi, (off_p)so->position[posi]); so->left[posi] = buff[i]; if(channels == 2) so->right[posi] = buff[i+1]; if(++posi >= samples) break; } if(posi >= samples) break; pos_count += buffsamples; } if(err != MPG123_DONE && err != MPG123_OK) { printf("An error occured (not done)?: %s\n", mpg123_strerror(m)); return -1; } return 0; }
int main(int argc, char **argv) { int i, result; mpg123_handle* m; #if defined(WANT_WIN32_UNICODE) win32_cmdline_utf8(&argc,&argv); #endif progname = argv[0]; while ((result = getlopt(argc, argv, opts))) switch (result) { case GLO_UNKNOWN: fprintf (stderr, "%s: Unknown option \"%s\".\n", progname, loptarg); usage(1); case GLO_NOARG: fprintf (stderr, "%s: Missing argument for option \"%s\".\n", progname, loptarg); usage(1); } #ifdef WIN32 fprintf(stderr, "WARNING: This tool is not yet adapted to run on Windows (file I/O, unicode arguments)!\n"); #endif if(loptind >= argc) usage(1); mpg123_init(); m = mpg123_new(NULL, NULL); mpg123_param(m, MPG123_ADD_FLAGS, MPG123_PICTURE, 0.); for(i=loptind; i < argc; ++i) { mpg123_id3v1 *v1; mpg123_id3v2 *v2; int meta; if(mpg123_open(m, argv[i]) != MPG123_OK) { fprintf(stderr, "Cannot open %s: %s\n", argv[i], mpg123_strerror(m)); continue; } mpg123_scan(m); meta = mpg123_meta_check(m); if(meta & MPG123_ID3 && mpg123_id3(m, &v1, &v2) == MPG123_OK) { printf("FILE: %s\n", argv[i]); printf("\n==== ID3v1 ====\n"); if(v1 != NULL) print_v1(v1); printf("\n==== ID3v2 ====\n"); if(v2 != NULL) print_v2(v2); printf("\n==== ID3v2 Raw frames ====\n"); if(v2 != NULL) { print_raw_v2(v2); if(param.store_pics) store_pictures(argv[i], v2); } } else printf("Nothing found for %s.\n", argv[i]); mpg123_close(m); } mpg123_delete(m); mpg123_exit(); if(errors) error1("Encountered %i errors along the way.", errors); return errors != 0; #if defined(WANT_WIN32_UNICODE) win32_cmdline_utf8_free(argc,argv); #endif }
bool DecoderMPG123::initialize() { if (input()->isSequential ()) //for streams only { TagExtractor extractor(input()); if(!extractor.id3v2tag().isEmpty()) addMetaData(extractor.id3v2tag()); } int err = mpg123_init(); if(err != MPG123_OK) { qWarning("DecoderMPG123: basic setup goes wrong: %s", mpg123_plain_strerror(err)); return false; } int channels = 0; if(!(m_handle = mpg123_new(0, &err))) { qWarning("DecoderMPG123: basic setup goes wrong: %s", mpg123_plain_strerror(err)); return false; } mpg123_param (m_handle, MPG123_ADD_FLAGS, MPG123_SEEKBUFFER | MPG123_FUZZY, 0); if((err = mpg123_replace_reader_handle(m_handle, mpg123_read_cb, mpg123_seek_cb, 0)) != MPG123_OK) { qWarning("DecoderMPG123: mpg123 error: %s", mpg123_plain_strerror(err)); cleanup(m_handle); m_handle = 0; return false; } setMPG123Format(MPG123_ENC_FLOAT_32); if((err = mpg123_open_handle(m_handle, this)) != MPG123_OK) { qWarning("DecoderMPG123: mpg123 error: %s", mpg123_plain_strerror(err)); cleanup(m_handle); m_handle = 0; return false; } if((err = mpg123_getformat(m_handle, &m_rate, &channels, &m_mpg123_encoding)) != MPG123_OK) { qWarning("DecoderMPG123: mpg123 error: %s", mpg123_plain_strerror(err)); cleanup(m_handle); m_handle = 0; return false; } //check format if(m_mpg123_encoding != MPG123_ENC_FLOAT_32) { cleanup(m_handle); qWarning("DecoderMPG123: bad encoding: 0x%x!\n", m_mpg123_encoding); m_handle = 0; return false; } if(!input()->isSequential()) { if((err = mpg123_scan(m_handle)) != MPG123_OK) qWarning("DecoderMPG123: mpg123 error: %s", mpg123_plain_strerror(err)); //duration m_totalTime = (qint64) mpg123_length(m_handle) * 1000 / m_rate; } else m_totalTime = 0; configure(m_rate, channels, Qmmp::PCM_FLOAT); return true; }
int control_generic (mpg123_handle *fr) { struct timeval tv; fd_set fds; int n; /* ThOr */ char alive = 1; char silent = 0; /* responses to stderr for frontends needing audio data from stdout */ if (param.remote_err) outstream = stderr; else outstream = stdout; #ifndef WIN32 setlinebuf(outstream); #else /* perhaps just use setvbuf as it's C89 */ /* fprintf(outstream, "You are on Win32 and want to use the control interface... tough luck: We need a replacement for select on STDIN first.\n"); return 0; setvbuf(outstream, (char*)NULL, _IOLBF, 0); */ #endif /* the command behaviour is different, so is the ID */ /* now also with version for command availability */ fprintf(outstream, "@R MPG123 (ThOr) v8\n"); #ifdef FIFO if(param.fifo) { if(param.fifo[0] == 0) { error("You wanted an empty FIFO name??"); return 1; } #ifndef WANT_WIN32_FIFO unlink(param.fifo); if(mkfifo(param.fifo, 0666) == -1) { error2("Failed to create FIFO at %s (%s)", param.fifo, strerror(errno)); return 1; } debug("going to open named pipe ... blocking until someone gives command"); #endif /* WANT_WIN32_FIFO */ #ifdef WANT_WIN32_FIFO control_file = win32_fifo_mkfifo(param.fifo); #else control_file = open(param.fifo,O_RDONLY); #endif /* WANT_WIN32_FIFO */ debug("opened"); } #endif while (alive) { tv.tv_sec = 0; tv.tv_usec = 0; FD_ZERO(&fds); FD_SET(control_file, &fds); /* play frame if no command needs to be processed */ if (mode == MODE_PLAYING) { #ifdef WANT_WIN32_FIFO n = win32_fifo_read_peek(&tv); #else n = select(32, &fds, NULL, NULL, &tv); #endif if (n == 0) { if (!play_frame()) { /* When the track ended, user may want to keep it open (to seek back), so there is a decision between stopping and pausing at the end. */ if(param.keep_open) { mode = MODE_PAUSED; /* Hm, buffer should be stopped already, shouldn't it? */ if(param.usebuffer) out123_pause(ao); generic_sendmsg("P 1"); } else { mode = MODE_STOPPED; close_track(); generic_sendmsg("P 0"); } continue; } if (init) { print_remote_header(fr); init = 0; } if(silent == 0) { generic_sendstat(fr); if(mpg123_meta_check(fr) & MPG123_NEW_ICY) { char *meta; if(mpg123_icy(fr, &meta) == MPG123_OK) generic_sendmsg("I ICY-META: %s", meta != NULL ? meta : "<nil>"); } } } } else { /* wait for command */ while (1) { #ifdef WANT_WIN32_FIFO n = win32_fifo_read_peek(NULL); #else n = select(32, &fds, NULL, NULL, NULL); #endif if (n > 0) break; } } /* on error */ if (n < 0) { fprintf(stderr, "Error waiting for command: %s\n", strerror(errno)); return 1; } /* read & process commands */ if (n > 0) { short int len = 1; /* length of buffer */ char *cmd, *arg; /* variables for parsing, */ char *comstr = NULL; /* gcc thinks that this could be used uninitialited... */ char buf[REMOTE_BUFFER_SIZE]; short int counter; char *next_comstr = buf; /* have it initialized for first command */ /* read as much as possible, maybe multiple commands */ /* When there is nothing to read (EOF) or even an error, it is the end */ #ifdef WANT_WIN32_FIFO len = win32_fifo_read(buf,REMOTE_BUFFER_SIZE); #else len = read(control_file, buf, REMOTE_BUFFER_SIZE); #endif if(len < 1) { #ifdef FIFO if(len == 0 && param.fifo) { debug("fifo ended... reopening"); #ifdef WANT_WIN32_FIFO win32_fifo_mkfifo(param.fifo); #else close(control_file); control_file = open(param.fifo,O_RDONLY|O_NONBLOCK); #endif if(control_file < 0) { error1("open of fifo failed... %s", strerror(errno)); break; } continue; } #endif if(len < 0) error1("command read error: %s", strerror(errno)); break; } debug1("read %i bytes of commands", len); /* one command on a line - separation by \n -> C strings in a row */ for(counter = 0; counter < len; ++counter) { /* line end is command end */ if( (buf[counter] == '\n') || (buf[counter] == '\r') ) { debug1("line end at counter=%i", counter); buf[counter] = 0; /* now it's a properly ending C string */ comstr = next_comstr; /* skip the additional line ender of \r\n or \n\r */ if( (counter < (len - 1)) && ((buf[counter+1] == '\n') || (buf[counter+1] == '\r')) ) buf[++counter] = 0; /* next "real" char is first of next command */ next_comstr = buf + counter+1; /* directly process the command now */ debug1("interpreting command: %s", comstr); if(strlen(comstr) == 0) continue; /* PAUSE */ if (!strcasecmp(comstr, "P") || !strcasecmp(comstr, "PAUSE")) { if(mode != MODE_STOPPED) { if (mode == MODE_PLAYING) { mode = MODE_PAUSED; out123_pause(ao); generic_sendmsg("P 1"); } else { mode = MODE_PLAYING; out123_continue(ao); generic_sendmsg("P 2"); } } else generic_sendmsg("P 0"); continue; } /* STOP */ if (!strcasecmp(comstr, "S") || !strcasecmp(comstr, "STOP")) { if (mode != MODE_STOPPED) { /* Do we want to drop here? */ out123_drop(ao); out123_stop(ao); close_track(); mode = MODE_STOPPED; generic_sendmsg("P 0"); } else generic_sendmsg("P 0"); continue; } /* SILENCE */ if(!strcasecmp(comstr, "SILENCE")) { silent = 1; generic_sendmsg("silence"); continue; } if(!strcasecmp(comstr, "T") || !strcasecmp(comstr, "TAG")) { generic_sendalltag(fr); continue; } if(!strcasecmp(comstr, "SCAN")) { if(mode != MODE_STOPPED) { if(mpg123_scan(fr) == MPG123_OK) generic_sendmsg("SCAN done"); else generic_sendmsg("E %s", mpg123_strerror(fr)); } else generic_sendmsg("E No track loaded!"); continue; } if(!strcasecmp(comstr, "SAMPLE")) { off_t pos = mpg123_tell(fr); off_t len = mpg123_length(fr); /* I need to have portable printf specifiers that do not truncate the type... more autoconf... */ if(len < 0) generic_sendmsg("E %s", mpg123_strerror(fr)); else generic_sendmsg("SAMPLE %li %li", (long)pos, (long)len); continue; } if(!strcasecmp(comstr, "FORMAT")) { long rate; int ch; int ret = mpg123_getformat(fr, &rate, &ch, NULL); /* I need to have portable printf specifiers that do not truncate the type... more autoconf... */ if(ret < 0) generic_sendmsg("E %s", mpg123_strerror(fr)); else generic_sendmsg("FORMAT %li %i", rate, ch); continue; } if(!strcasecmp(comstr, "SHOWEQ")) { int i; generic_sendmsg("SHOWEQ {"); for(i=0; i<32; ++i) { generic_sendmsg("SHOWEQ %i : %i : %f", MPG123_LEFT, i, mpg123_geteq(fr, MPG123_LEFT, i)); generic_sendmsg("SHOWEQ %i : %i : %f", MPG123_RIGHT, i, mpg123_geteq(fr, MPG123_RIGHT, i)); } generic_sendmsg("SHOWEQ }"); continue; } if(!strcasecmp(comstr, "STATE")) { long val; generic_sendmsg("STATE {"); /* Get some state information bits and display them. */ if(mpg123_getstate(fr, MPG123_ACCURATE, &val, NULL) == MPG123_OK) generic_sendmsg("STATE accurate %li", val); generic_sendmsg("STATE }"); continue; } /* QUIT */ if (!strcasecmp(comstr, "Q") || !strcasecmp(comstr, "QUIT")) { alive = FALSE; continue; } /* some HELP */ if (!strcasecmp(comstr, "H") || !strcasecmp(comstr, "HELP")) { generic_sendmsg("H {"); generic_sendmsg("H HELP/H: command listing (LONG/SHORT forms), command case insensitve"); generic_sendmsg("H LOAD/L <trackname>: load and start playing resource <trackname>"); generic_sendmsg("H LOADPAUSED/LP <trackname>: load but do not start playing resource <trackname>"); generic_sendmsg("H LOADLIST/LL <entry> <url>: load a playlist from given <url>, and display its entries, optionally load and play one of these specificed by the integer <entry> (<0: just list, 0: play last track, >0:play track with that position in list)"); generic_sendmsg("H PAUSE/P: pause playback"); generic_sendmsg("H STOP/S: stop playback (closes file)"); generic_sendmsg("H JUMP/J <frame>|<+offset>|<-offset>|<[+|-]seconds>s: jump to mpeg frame <frame> or change position by offset, same in seconds if number followed by \"s\""); generic_sendmsg("H VOLUME/V <percent>: set volume in % (0..100...); float value"); generic_sendmsg("H RVA off|(mix|radio)|(album|audiophile): set rva mode"); generic_sendmsg("H EQ/E <channel> <band> <value>: set equalizer value for frequency band 0 to 31 on channel %i (left) or %i (right) or %i (both)", MPG123_LEFT, MPG123_RIGHT, MPG123_LR); generic_sendmsg("H EQFILE <filename>: load EQ settings from a file"); generic_sendmsg("H SHOWEQ: show all equalizer settings (as <channel> <band> <value> lines in a SHOWEQ block (like TAG))"); generic_sendmsg("H SEEK/K <sample>|<+offset>|<-offset>: jump to output sample position <samples> or change position by offset"); generic_sendmsg("H SCAN: scan through the file, building seek index"); generic_sendmsg("H SAMPLE: print out the sample position and total number of samples"); generic_sendmsg("H FORMAT: print out sampling rate in Hz and channel count"); generic_sendmsg("H SEQ <bass> <mid> <treble>: simple eq setting..."); generic_sendmsg("H PITCH <[+|-]value>: adjust playback speed (+0.01 is 1 %% faster)"); generic_sendmsg("H SILENCE: be silent during playback (meaning silence in text form)"); generic_sendmsg("H STATE: Print auxiliary state info in several lines (just try it to see what info is there)."); generic_sendmsg("H TAG/T: Print all available (ID3) tag info, for ID3v2 that gives output of all collected text fields, using the ID3v2.3/4 4-character names. NOTE: ID3v2 data will be deleted on non-forward seeks."); generic_sendmsg("H The output is multiple lines, begin marked by \"@T {\", end by \"@T }\"."); generic_sendmsg("H ID3v1 data is like in the @I info lines (see below), just with \"@T\" in front."); generic_sendmsg("H An ID3v2 data field is introduced via ([ ... ] means optional):"); generic_sendmsg("H @T ID3v2.<NAME>[ [lang(<LANG>)] desc(<description>)]:"); generic_sendmsg("H The lines of data follow with \"=\" prefixed:"); generic_sendmsg("H @T =<one line of content in UTF-8 encoding>"); generic_sendmsg("H meaning of the @S stream info:"); generic_sendmsg("H %s", remote_header_help); generic_sendmsg("H The @I lines after loading a track give some ID3 info, the format:"); generic_sendmsg("H @I ID3:artist album year comment genretext"); generic_sendmsg("H where artist,album and comment are exactly 30 characters each, year is 4 characters, genre text unspecified."); generic_sendmsg("H You will encounter \"@I ID3.genre:<number>\" and \"@I ID3.track:<number>\"."); generic_sendmsg("H Then, there is an excerpt of ID3v2 info in the structure"); generic_sendmsg("H @I ID3v2.title:Blabla bla Bla"); generic_sendmsg("H for every line of the \"title\" data field. Likewise for other fields (author, album, etc)."); generic_sendmsg("H }"); continue; } /* commands with arguments */ cmd = NULL; arg = NULL; cmd = strtok(comstr," \t"); /* get the main command */ arg = strtok(NULL,""); /* get the args */ if (cmd && strlen(cmd) && arg && strlen(arg)) { #ifndef NO_EQUALIZER /* Simple EQ: SEQ <BASS> <MID> <TREBLE> */ if (!strcasecmp(cmd, "SEQ")) { double b,m,t; int cn; if(sscanf(arg, "%lf %lf %lf", &b, &m, &t) == 3) { /* Consider adding mpg123_seq()... but also, on could define a nicer courve for that. */ if ((t >= 0) && (t <= 3)) for(cn=0; cn < 1; ++cn) mpg123_eq(fr, MPG123_LEFT|MPG123_RIGHT, cn, b); if ((m >= 0) && (m <= 3)) for(cn=1; cn < 2; ++cn) mpg123_eq(fr, MPG123_LEFT|MPG123_RIGHT, cn, m); if ((b >= 0) && (b <= 3)) for(cn=2; cn < 32; ++cn) mpg123_eq(fr, MPG123_LEFT|MPG123_RIGHT, cn, t); generic_sendmsg("bass: %f mid: %f treble: %f", b, m, t); } else generic_sendmsg("E invalid arguments for SEQ: %s", arg); continue; } /* Equalizer control :) (JMG) */ if (!strcasecmp(cmd, "E") || !strcasecmp(cmd, "EQ")) { double e; /* ThOr: equalizer is of type real... whatever that is */ int c, v; /*generic_sendmsg("%s",updown);*/ if(sscanf(arg, "%i %i %lf", &c, &v, &e) == 3) { if(mpg123_eq(fr, c, v, e) == MPG123_OK) generic_sendmsg("%i : %i : %f", c, v, e); else generic_sendmsg("E failed to set eq: %s", mpg123_strerror(fr)); } else generic_sendmsg("E invalid arguments for EQ: %s", arg); continue; } if(!strcasecmp(cmd, "EQFILE")) { equalfile = arg; if(load_equalizer(fr) == 0) generic_sendmsg("EQFILE done"); else generic_sendmsg("E failed to parse given eq file"); continue; } #endif /* SEEK to a sample offset */ if(!strcasecmp(cmd, "K") || !strcasecmp(cmd, "SEEK")) { off_t soff; off_t oldpos; off_t newpos; char *spos = arg; int whence = SEEK_SET; if(mode == MODE_STOPPED) { generic_sendmsg("E No track loaded!"); continue; } oldpos = mpg123_tell(fr); soff = (off_t) atobigint(spos); if(spos[0] == '-' || spos[0] == '+') whence = SEEK_CUR; if(0 > (soff = mpg123_seek(fr, soff, whence))) { generic_sendmsg("E Error while seeking: %s", mpg123_strerror(fr)); mpg123_seek(fr, 0, SEEK_SET); } out123_drop(ao); newpos = mpg123_tell(fr); if(newpos <= oldpos) mpg123_meta_free(fr); generic_sendmsg("K %"OFF_P, (off_p)newpos); continue; } /* JUMP */ if (!strcasecmp(cmd, "J") || !strcasecmp(cmd, "JUMP")) { char *spos; off_t offset; off_t oldpos; double secs; spos = arg; if(mode == MODE_STOPPED) { generic_sendmsg("E No track loaded!"); continue; } oldpos = framenum; if(spos[strlen(spos)-1] == 's' && sscanf(arg, "%lf", &secs) == 1) offset = mpg123_timeframe(fr, secs); else offset = atol(spos); /* totally replaced that stuff - it never fully worked a bit usure about why +pos -> spos+1 earlier... */ if (spos[0] == '-' || spos[0] == '+') offset += framenum; if(0 > (framenum = mpg123_seek_frame(fr, offset, SEEK_SET))) { generic_sendmsg("E Error while seeking"); mpg123_seek_frame(fr, 0, SEEK_SET); } out123_drop(ao); if(framenum <= oldpos) mpg123_meta_free(fr); generic_sendmsg("J %d", framenum); continue; } /* VOLUME in percent */ if(!strcasecmp(cmd, "V") || !strcasecmp(cmd, "VOLUME")) { double v; mpg123_volume(fr, atof(arg)/100); mpg123_getvolume(fr, &v, NULL, NULL); /* Necessary? */ generic_sendmsg("V %f%%", v * 100); continue; } /* PITCH (playback speed) in percent */ if(!strcasecmp(cmd, "PITCH")) { double p; if(sscanf(arg, "%lf", &p) == 1) { set_pitch(fr, ao, p); generic_sendmsg("PITCH %f", param.pitch); } else generic_sendmsg("E invalid arguments for PITCH: %s", arg); continue; } /* RVA mode */ if(!strcasecmp(cmd, "RVA")) { if(!strcasecmp(arg, "off")) param.rva = MPG123_RVA_OFF; else if(!strcasecmp(arg, "mix") || !strcasecmp(arg, "radio")) param.rva = MPG123_RVA_MIX; else if(!strcasecmp(arg, "album") || !strcasecmp(arg, "audiophile")) param.rva = MPG123_RVA_ALBUM; mpg123_volume_change(fr, 0.); generic_sendmsg("RVA %s", rva_name[param.rva]); continue; } /* LOAD - actually play */ if (!strcasecmp(cmd, "L") || !strcasecmp(cmd, "LOAD")) { generic_load(fr, arg, MODE_PLAYING); continue; } if (!strcasecmp(cmd, "LL") || !strcasecmp(cmd, "LOADLIST")) { generic_loadlist(fr, arg); continue; } /* LOADPAUSED */ if (!strcasecmp(cmd, "LP") || !strcasecmp(cmd, "LOADPAUSED")) { generic_load(fr, arg, MODE_PAUSED); continue; } /* no command matched */ generic_sendmsg("E Unknown command: %s", cmd); /* unknown command */ } /* end commands with arguments */ else generic_sendmsg("E Unknown command or no arguments: %s", comstr); /* unknown command */ } /* end of single command processing */ } /* end of scanning the command buffer */ /* when last command had no \n... should I discard it? Ideally, I should remember the part and wait for next read() to get the rest up to a \n. But that can go to infinity. Too long commands too quickly are just bad. Cannot/Won't change that. So, discard the unfinished command and have fingers crossed that the rest of this unfinished one qualifies as "unknown". */ if(buf[len-1] != 0) { char lasti = buf[len-1]; buf[len-1] = 0; generic_sendmsg("E Unfinished command: %s%c", comstr, lasti); } } /* end command reading & processing */ } /* end main (alive) loop */ debug("going to end"); /* quit gracefully */ debug("closing control"); #ifdef FIFO #if WANT_WIN32_FIFO win32_fifo_close(); #else close(control_file); /* be it FIFO or STDIN */ if(param.fifo) unlink(param.fifo); #endif /* WANT_WIN32_FIFO */ #endif debug("control_generic returning"); return 0; }
JNIEXPORT jlong JNICALL Java_com_axelby_mp3decoders_MPG123_openFile (JNIEnv *env, jclass c, jstring filename) { int err = MPG123_OK; mpg123_handle *mh = mpg123_new(NULL, &err); if (err != MPG123_OK) { printerr("mpg123_new", err); return 0; } if (mh == NULL) { __android_log_write(ANDROID_LOG_INFO, "podax-jni", "mpg123_handle is NULL"); return 0; } MP3File* mp3 = mp3file_init(mh); const char* fileString = (*env)->GetStringUTFChars(env, filename, NULL); err = mpg123_open(mh, fileString); if (err != MPG123_OK) { printerr("mpg123_open", err); (*env)->ReleaseStringUTFChars(env, filename, fileString); mp3file_delete(mp3); return err; } // in podax, remove next line and uncomment block mpg123_scan(mh); /* char* index_fn = calloc(1, strlen(fileString) + 6 + 1); strcpy(index_fn, fileString); // remove last path (Podcasts/) char* lastSlash = strrchr(index_fn, '/'); char* lastDir = strstr(index_fn, "/Podcasts/"); memmove(lastDir, lastSlash, index_fn + strlen(index_fn) - lastSlash + 1); strcat(index_fn, ".index"); (*env)->ReleaseStringUTFChars(env, filename, fileString); // save / restore index for fast seeking size_t idx_fill; off_t idx_step; off_t* idx_offsets; FILE* index_file = fopen(index_fn, "rb"); if (index_file != NULL) { fread(&idx_fill, sizeof(size_t), 1, index_file); fread(&idx_step, sizeof(off_t), 1, index_file); idx_offsets = malloc(idx_fill * sizeof(off_t)); fread(idx_offsets, sizeof(off_t), idx_fill, index_file); fclose(index_file); mpg123_set_index(mh, idx_offsets, idx_step, idx_fill); } else { mpg123_scan(mh); mpg123_index(mh, &idx_offsets, &idx_step, &idx_fill); index_file = fopen(index_fn, "wb"); fwrite(&idx_fill, sizeof(size_t), 1, index_file); fwrite(&idx_step, sizeof(off_t), 1, index_file); fwrite(idx_offsets, sizeof(off_t), idx_fill, index_file); fclose(index_file); } free(index_fn); */ // determine format and length mp3file_determineStats(mp3); return (jlong)mp3; }
static float* readaudio_mp3(const char *filename,long *sr, const float nbsecs, unsigned int *buflen) { mpg123_handle *m; int ret; if (mpg123_init() != MPG123_OK || ((m = mpg123_new(NULL,&ret)) == NULL)|| \ mpg123_open(m, filename) != MPG123_OK) { fprintf(stderr,"unable to init mpg\n"); return NULL; } /*turn off logging */ mpg123_param(m, MPG123_ADD_FLAGS, MPG123_QUIET, 0); off_t totalsamples; mpg123_scan(m); totalsamples = mpg123_length(m); int meta = mpg123_meta_check(m); int channels, encoding; if (mpg123_getformat(m, sr, &channels, &encoding) != MPG123_OK) { fprintf(stderr,"unable to get format\n"); return NULL; } mpg123_format_none(m); mpg123_format(m, *sr, channels, encoding); size_t decbuflen = mpg123_outblock(m); unsigned char *decbuf = (unsigned char*)malloc(decbuflen); if (decbuf == NULL) { printf("mem alloc error\n"); return NULL; } unsigned int nbsamples = (nbsecs <= 0) ? totalsamples : nbsecs*(*sr); nbsamples = (nbsamples < totalsamples) ? nbsamples : totalsamples; size_t i, j, index = 0, done; float *buffer = (float*)malloc(nbsamples*sizeof(float)); *buflen = nbsamples; do { ret = mpg123_read(m, decbuf, decbuflen, &done); switch (encoding) { case MPG123_ENC_SIGNED_16 : for (i = 0; i < done/sizeof(short); i+=channels) { buffer[index] = 0.0f; for (j = 0; j < channels ; j++) { buffer[index] += (float)(((short*)decbuf)[i+j])/(float)SHRT_MAX; } buffer[index++] /= channels; if (index >= nbsamples) break; } break; case MPG123_ENC_SIGNED_8: for (i = 0; i < done/sizeof(char); i+=channels) { buffer[index] = 0.0f; for (j = 0; j < channels ; j++) { buffer[index] += (float)(((char*)decbuf)[i+j])/(float)SCHAR_MAX; } buffer[index++] /= channels; if (index >= nbsamples) break; } break; case MPG123_ENC_FLOAT_32: for (i = 0; i < done/sizeof(float); i+=channels) { buffer[index] = 0.0f; for (j = 0; j < channels; j++) { buffer[index] += ((float*)decbuf)[i+j]; } buffer[index++] /= channels; if (index >= nbsamples) break; } break; default: done = 0; } } while (ret == MPG123_OK && index < nbsamples); free(decbuf); mpg123_close(m); mpg123_delete(m); mpg123_exit(); return buffer; }
float* readaudio_mp3(const char *filename,long *sr, unsigned int *buflen,\ const float nbsecs, AudioMetaData *mdata, int *error){ mpg123_handle *m; int ret = 0; mpg123_id3v1 *v1 = NULL; mpg123_id3v2 *v2 = NULL; if ((ret = mpg123_init()) != MPG123_OK || ((m = mpg123_new(NULL,&ret)) == NULL)|| \ (ret = mpg123_open(m, filename)) != MPG123_OK){ *error = (ret != 0) ? ret : PHERR_MP3NEW; return NULL; } /*turn off logging */ mpg123_param(m, MPG123_ADD_FLAGS, MPG123_QUIET, 0); off_t totalsamples; mpg123_scan(m); totalsamples = mpg123_length(m); if (totalsamples <= 0){ *error = PHERR_NOSAMPLES; return NULL; } int meta = mpg123_meta_check(m); if (mdata)init_mdata(mdata); if (mdata && (meta & MPG123_ID3) && mpg123_id3(m, &v1, &v2) == MPG123_OK){ if (v2){ get_v2_data(v2, mdata); } else if (v1){ get_v1_data(v1, mdata); } } int channels, encoding; if (mpg123_getformat(m, sr, &channels, &encoding) != MPG123_OK){ *error = PHERR_NOFORMAT; return NULL; } mpg123_format_none(m); mpg123_format(m, *sr, channels, encoding); if (channels <= 0 || encoding <= 0){ *error = PHERR_NOENCODING; return NULL; } size_t decbuflen = mpg123_outblock(m); if (decbuflen == 0){ /* take a guess */ decbuflen = 1<<16; } unsigned char *decbuf = (unsigned char*)malloc(decbuflen); if (decbuf == NULL){ *error = PHERR_MEMALLOC; return NULL; } unsigned int nbsamples = (nbsecs <= 0) ? totalsamples : nbsecs*(*sr); nbsamples = (nbsamples <= totalsamples) ? nbsamples : totalsamples; size_t i, j, index = 0, done; float *buffer = (float*)malloc(nbsamples*sizeof(float)); if (buffer == NULL){ *error = PHERR_MEMALLOC; return NULL; } *buflen = nbsamples; do { ret = mpg123_read(m, decbuf, decbuflen, &done); switch (encoding) { case MPG123_ENC_SIGNED_16 : for (i = 0; i < done/sizeof(short); i+=channels){ buffer[index] = 0.0f; for (j = 0; j < channels ; j++){ buffer[index] += (float)(((short*)decbuf)[i+j])/(float)SHRT_MAX; } buffer[index++] /= channels; if (index >= nbsamples) break; } break; case MPG123_ENC_SIGNED_8: for (i = 0; i < done/sizeof(char); i+=channels){ buffer[index] = 0.0f; for (j = 0; j < channels ; j++){ buffer[index] += (float)(((char*)decbuf)[i+j])/(float)SCHAR_MAX; } buffer[index++] /= channels; if (index >= nbsamples) break; } break; case MPG123_ENC_FLOAT_32: for (i = 0; i < done/sizeof(float); i+=channels){ buffer[index] = 0.0f; for (j = 0; j < channels; j++){ buffer[index] += ((float*)decbuf)[i+j]; } buffer[index++] /= channels; if (index >= nbsamples) break; } break; default: done = 0; } } while (ret == MPG123_OK && index < nbsamples); if (ret != MPG123_DONE && ret != MPG123_OK && index < nbsamples){ free(buffer); *error = ret; buffer=NULL; } free(decbuf); mpg123_close(m); mpg123_delete(m); mpg123_exit(); return buffer; }
g_id gaudio_Mp3Open(const char *fileName, int *numChannels, int *sampleRate, int *bitsPerSample, int *numSamples, gaudio_Error *error) { int err = MPG123_OK; mpg123_handle *mh = mpg123_new(NULL, &err); if (mh == NULL || err != MPG123_OK) { if (error) *error = GAUDIO_INTERNAL_ERROR; return 0; } G_FILE *file = g_fopen(fileName, "rb"); if (file == NULL) { mpg123_delete(mh); if (error) *error = GAUDIO_CANNOT_OPEN_FILE; return 0; } mpg123_replace_reader_handle(mh, mpg123read, mpg123lseek, mpg123cleanup); if (mpg123_open_handle(mh, file) != MPG123_OK) { mpg123_delete(mh); if (error) *error = GAUDIO_UNRECOGNIZED_FORMAT; return 0; } int channels = 0, encoding = 0; long rate = 0; if (mpg123_getformat(mh, &rate, &channels, &encoding) != MPG123_OK) { mpg123_delete(mh); if (error) *error = GAUDIO_UNRECOGNIZED_FORMAT; return 0; } // although signed 16 is the default output format, we ensure that anyway. encoding = MPG123_ENC_SIGNED_16; mpg123_format_none(mh); mpg123_format(mh, rate, channels, encoding); mpg123_scan(mh); off_t sampleCount = mpg123_length(mh); if (numChannels) *numChannels = channels; if (sampleRate) *sampleRate = rate; if (bitsPerSample) *bitsPerSample = 16; if (numSamples) *numSamples = sampleCount; if (error) *error = GAUDIO_NO_ERROR; GGMp3Handle *handle = new GGMp3Handle(); handle->mh = mh; handle->sampleSize = channels * 2; return (g_id)handle; }
int main(int sys_argc, char ** sys_argv) { int result; char end_of_files = FALSE; long parr; char *fname; int libpar = 0; mpg123_pars *mp; #if !defined(WIN32) && !defined(GENERIC) struct timeval start_time; #endif aux_out = stdout; /* Need to initialize here because stdout is not a constant?! */ #if defined (WANT_WIN32_UNICODE) if(win32_cmdline_utf8(&argc, &argv) != 0) { error("Cannot convert command line to UTF8!"); safe_exit(76); } #else argv = sys_argv; argc = sys_argc; #endif #if defined (WANT_WIN32_SOCKETS) win32_net_init(); #endif /* Extract binary and path, take stuff before/after last / or \ . */ if((prgName = strrchr(argv[0], '/')) || (prgName = strrchr(argv[0], '\\'))) { /* There is some explicit path. */ prgName[0] = 0; /* End byte for path. */ prgName++; binpath = argv[0]; } else { prgName = argv[0]; /* No path separators there. */ binpath = NULL; /* No path at all. */ } /* Need to initialize mpg123 lib here for default parameter values. */ result = mpg123_init(); if(result != MPG123_OK) { error1("Cannot initialize mpg123 library: %s", mpg123_plain_strerror(result)); safe_exit(77); } cleanup_mpg123 = TRUE; mp = mpg123_new_pars(&result); /* This may get leaked on premature exit(), which is mainly a cosmetic issue... */ if(mp == NULL) { error1("Crap! Cannot get mpg123 parameters: %s", mpg123_plain_strerror(result)); safe_exit(78); } /* get default values */ mpg123_getpar(mp, MPG123_DOWN_SAMPLE, &parr, NULL); param.down_sample = (int) parr; mpg123_getpar(mp, MPG123_RVA, ¶m.rva, NULL); mpg123_getpar(mp, MPG123_DOWNSPEED, ¶m.halfspeed, NULL); mpg123_getpar(mp, MPG123_UPSPEED, ¶m.doublespeed, NULL); mpg123_getpar(mp, MPG123_OUTSCALE, ¶m.outscale, NULL); mpg123_getpar(mp, MPG123_FLAGS, &parr, NULL); mpg123_getpar(mp, MPG123_INDEX_SIZE, ¶m.index_size, NULL); param.flags = (int) parr; param.flags |= MPG123_SEEKBUFFER; /* Default on, for HTTP streams. */ mpg123_getpar(mp, MPG123_RESYNC_LIMIT, ¶m.resync_limit, NULL); mpg123_getpar(mp, MPG123_PREFRAMES, ¶m.preframes, NULL); #ifdef OS2 _wildcard(&argc,&argv); #endif while ((result = getlopt(argc, argv, opts))) switch (result) { case GLO_UNKNOWN: fprintf (stderr, "%s: Unknown option \"%s\".\n", prgName, loptarg); usage(1); case GLO_NOARG: fprintf (stderr, "%s: Missing argument for option \"%s\".\n", prgName, loptarg); usage(1); } /* Do this _after_ parameter parsing. */ check_locale(); /* Check/set locale; store if it uses UTF-8. */ if(param.list_cpu) { const char **all_dec = mpg123_decoders(); printf("Builtin decoders:"); while(*all_dec != NULL){ printf(" %s", *all_dec); ++all_dec; } printf("\n"); mpg123_delete_pars(mp); return 0; } if(param.test_cpu) { const char **all_dec = mpg123_supported_decoders(); printf("Supported decoders:"); while(*all_dec != NULL){ printf(" %s", *all_dec); ++all_dec; } printf("\n"); mpg123_delete_pars(mp); return 0; } if(param.gain != -1) { warning("The parameter -g is deprecated and may be removed in the future."); } if (loptind >= argc && !param.listname && !param.remote) usage(1); /* Init audio as early as possible. If there is the buffer process to be spawned, it shouldn't carry the mpg123_handle with it. */ bufferblock = mpg123_safe_buffer(); /* Can call that before mpg123_init(), it's stateless. */ if(init_output(&ao) < 0) { error("Failed to initialize output, goodbye."); mpg123_delete_pars(mp); return 99; /* It's safe here... nothing nasty happened yet. */ } have_output = TRUE; /* ========================================================================================================= */ /* Enterning the leaking zone... we start messing with stuff here that should be taken care of when leaving. */ /* Don't just exit() or return out... */ /* ========================================================================================================= */ httpdata_init(&htd); #if !defined(WIN32) && !defined(GENERIC) if (param.remote) { param.verbose = 0; param.quiet = 1; param.flags |= MPG123_QUIET; } #endif /* Set the frame parameters from command line options */ if(param.quiet) param.flags |= MPG123_QUIET; #ifdef OPT_3DNOW if(dnow != 0) param.cpu = (dnow == SET_3DNOW) ? "3dnow" : "i586"; #endif if(param.cpu != NULL && (!strcmp(param.cpu, "auto") || !strcmp(param.cpu, ""))) param.cpu = NULL; if(!( MPG123_OK == (result = mpg123_par(mp, MPG123_VERBOSE, param.verbose, 0)) && ++libpar && MPG123_OK == (result = mpg123_par(mp, MPG123_FLAGS, param.flags, 0)) && ++libpar && MPG123_OK == (result = mpg123_par(mp, MPG123_DOWN_SAMPLE, param.down_sample, 0)) && ++libpar && MPG123_OK == (result = mpg123_par(mp, MPG123_RVA, param.rva, 0)) && ++libpar && MPG123_OK == (result = mpg123_par(mp, MPG123_FORCE_RATE, param.force_rate, 0)) && ++libpar && MPG123_OK == (result = mpg123_par(mp, MPG123_DOWNSPEED, param.halfspeed, 0)) && ++libpar && MPG123_OK == (result = mpg123_par(mp, MPG123_UPSPEED, param.doublespeed, 0)) && ++libpar && MPG123_OK == (result = mpg123_par(mp, MPG123_ICY_INTERVAL, 0, 0)) && ++libpar && MPG123_OK == (result = mpg123_par(mp, MPG123_RESYNC_LIMIT, param.resync_limit, 0)) && ++libpar && MPG123_OK == (result = mpg123_par(mp, MPG123_TIMEOUT, param.timeout, 0)) && ++libpar && MPG123_OK == (result = mpg123_par(mp, MPG123_OUTSCALE, param.outscale, 0)) && ++libpar && MPG123_OK == (result = mpg123_par(mp, MPG123_PREFRAMES, param.preframes, 0)) )) { error2("Cannot set library parameter %i: %s", libpar, mpg123_plain_strerror(result)); safe_exit(45); } if (!(param.listentry < 0) && !param.quiet) print_title(stderr); /* do not pollute stdout! */ { long default_index; mpg123_getpar(mp, MPG123_INDEX_SIZE, &default_index, NULL); if( param.index_size != default_index && (result = mpg123_par(mp, MPG123_INDEX_SIZE, param.index_size, 0.)) != MPG123_OK ) error1("Setting of frame index size failed: %s", mpg123_plain_strerror(result)); } if(param.force_rate && param.down_sample) { error("Down sampling and fixed rate options not allowed together!"); safe_exit(1); } /* Now actually get an mpg123_handle. */ mh = mpg123_parnew(mp, param.cpu, &result); if(mh == NULL) { error1("Crap! Cannot get a mpg123 handle: %s", mpg123_plain_strerror(result)); safe_exit(77); } mpg123_delete_pars(mp); /* Don't need the parameters anymore ,they're in the handle now. */ /* Prepare stream dumping, possibly replacing mpg123 reader. */ if(dump_open(mh) != 0) safe_exit(78); /* Now either check caps myself or query buffer for that. */ audio_capabilities(ao, mh); load_equalizer(mh); #ifdef HAVE_SETPRIORITY if(param.aggressive) { /* tst */ int mypid = getpid(); setpriority(PRIO_PROCESS,mypid,-20); } #endif #if defined (HAVE_SCHED_SETSCHEDULER) && !defined (__CYGWIN__) && !defined (HAVE_WINDOWS_H) /* Cygwin --realtime seems to fail when accessing network, using win32 set priority instead */ /* MinGW may have pthread installed, we prefer win32API */ if (param.realtime) { /* Get real-time priority */ struct sched_param sp; fprintf(stderr,"Getting real-time priority\n"); memset(&sp, 0, sizeof(struct sched_param)); sp.sched_priority = sched_get_priority_min(SCHED_FIFO); if (sched_setscheduler(0, SCHED_RR, &sp) == -1) fprintf(stderr,"Can't get real-time priority\n"); } #endif #ifdef HAVE_WINDOWS_H /* argument "3" is equivalent to realtime priority class */ win32_set_priority( param.realtime ? 3 : param.w32_priority); #endif if(!param.remote) prepare_playlist(argc, argv); #if !defined(WIN32) && !defined(GENERIC) /* Remote mode is special... but normal console and terminal-controlled operation needs to catch the SIGINT. For one it serves for track skip when not in terminal control mode. The more important use being a graceful exit, including telling the buffer process what's going on. */ if(!param.remote) catchsignal (SIGINT, catch_interrupt); #endif if(param.remote) { int ret; ret = control_generic(mh); safe_exit(ret); } #ifdef HAVE_TERMIOS debug1("param.term_ctrl: %i", param.term_ctrl); if(param.term_ctrl) term_init(); #endif if(APPFLAG(MPG123APP_CONTINUE)) frames_left = param.frame_number; while ((fname = get_next_file())) { char *dirname, *filename; int newdir; /* skip_tracks includes the previous one. */ if(skip_tracks) --skip_tracks; if(skip_tracks) { debug("Skipping this track."); continue; } if(param.delay > 0) { /* One should enable terminal control during that sleeping phase! */ if(param.verbose > 2) fprintf(stderr, "Note: pausing %i seconds before next track.\n", param.delay); output_pause(ao); #ifdef WIN32 Sleep(param.delay*1000); #else sleep(param.delay); #endif output_unpause(ao); } if(!APPFLAG(MPG123APP_CONTINUE)) frames_left = param.frame_number; debug1("Going to play %s", strcmp(fname, "-") ? fname : "standard input"); if(intflag || !open_track(fname)) { #ifdef HAVE_TERMIOS /* We need the opportunity to cancel in case of --loop -1 . */ if(param.term_ctrl) term_control(mh, ao); #endif /* No wait for a second interrupt before we started playing. */ if(intflag) break; continue; } if(!param.quiet) fprintf(stderr, "\n"); if(param.index) { if(param.verbose) fprintf(stderr, "indexing...\r"); mpg123_scan(mh); } /* Only trigger a seek if we do not want to start with the first frame. Rationale: Because of libmpg123 sample accuracy, this could cause an unnecessary backwards seek, that even may fail on non-seekable streams. For start frame of 0, we are already at the correct position! */ framenum = 0; if(param.start_frame > 0) framenum = mpg123_seek_frame(mh, param.start_frame, SEEK_SET); if(APPFLAG(MPG123APP_CONTINUE)) param.start_frame = 0; if(framenum < 0) { error1("Initial seek failed: %s", mpg123_strerror(mh)); if(mpg123_errcode(mh) == MPG123_BAD_OUTFORMAT) { fprintf(stderr, "%s", "So, you have trouble getting an output format... this is the matrix of currently possible formats:\n"); print_capabilities(ao, mh); fprintf(stderr, "%s", "Somehow the input data and your choices don't allow one of these.\n"); } mpg123_close(mh); continue; } /* Prinout and xterm title need this, possibly independently. */ newdir = split_dir_file(fname ? fname : "standard input", &dirname, &filename); if (!param.quiet) { if(newdir) fprintf(stderr, "Directory: %s\n", dirname); #ifdef HAVE_TERMIOS /* Reminder about terminal usage. */ if(param.term_ctrl) term_hint(); #endif fprintf(stderr, "Playing MPEG stream %lu of %lu: %s ...\n", (unsigned long)pl.pos, (unsigned long)pl.fill, filename); if(htd.icy_name.fill) fprintf(stderr, "ICY-NAME: %s\n", htd.icy_name.p); if(htd.icy_url.fill) fprintf(stderr, "ICY-URL: %s\n", htd.icy_url.p); } #if !defined(GENERIC) { const char *term_type; term_type = getenv("TERM"); if(term_type && param.xterm_title) { if(!strncmp(term_type,"xterm",5) || !strncmp(term_type,"rxvt",4)) fprintf(stderr, "\033]0;%s\007", filename); else if(!strncmp(term_type,"screen",6)) fprintf(stderr, "\033k%s\033\\", filename); else if(!strncmp(term_type,"iris-ansi",9)) fprintf(stderr, "\033P1.y %s\033\\\033P3.y%s\033\\", filename, filename); fflush(stderr); /* Paranoia: will the buffer buffer the escapes? */ } } #endif /* Rethink that SIGINT logic... */ #if !defined(WIN32) && !defined(GENERIC) #ifdef HAVE_TERMIOS if(!param.term_ctrl) #endif gettimeofday (&start_time, NULL); #endif while(!intflag) { int meta; if(param.frame_number > -1) { debug1("frames left: %li", (long) frames_left); if(!frames_left) { if(APPFLAG(MPG123APP_CONTINUE)) end_of_files = TRUE; break; } } if(!play_frame()) break; if(!param.quiet) { meta = mpg123_meta_check(mh); if(meta & (MPG123_NEW_ID3|MPG123_NEW_ICY)) { if(meta & MPG123_NEW_ID3) print_id3_tag(mh, param.long_id3, stderr); if(meta & MPG123_NEW_ICY) print_icy(mh, stderr); mpg123_meta_free(mh); /* Do not waste memory after delivering. */ } } if(!fresh && param.verbose) { #ifndef NOXFERMEM if (param.verbose > 1 || !(framenum & 0x7)) print_stat(mh,0,xfermem_get_usedspace(buffermem)); #else if(param.verbose > 1 || !(framenum & 0x7)) print_stat(mh,0,0); #endif } #ifdef HAVE_TERMIOS if(!param.term_ctrl) continue; else term_control(mh, ao); #endif } if(!param.smooth && param.usebuffer) buffer_drain(); if(param.verbose) print_stat(mh,0,xfermem_get_usedspace(buffermem)); if(!param.quiet) { double secs; long frank; fprintf(stderr, "\n"); if(mpg123_getstate(mh, MPG123_FRANKENSTEIN, &frank, NULL) == MPG123_OK && frank) fprintf(stderr, "This was a Frankenstein track.\n"); mpg123_position(mh, 0, 0, NULL, NULL, &secs, NULL); fprintf(stderr,"[%d:%02d] Decoding of %s finished.\n", (int)(secs / 60), ((int)secs) % 60, filename); } else if(param.verbose) fprintf(stderr, "\n"); mpg123_close(mh); if (intflag) { if(!skip_or_die(&start_time)) break; intflag = FALSE; #ifndef NOXFERMEM if(!param.smooth && param.usebuffer) buffer_resync(); #endif } if(end_of_files) break; } /* end of loop over input files */ /* Ensure we played everything. */ if(param.smooth && param.usebuffer) { buffer_drain(); buffer_resync(); } if(APPFLAG(MPG123APP_CONTINUE)) { continue_msg("CONTINUE"); } /* Free up memory used by playlist */ if(!param.remote) free_playlist(); safe_exit(0); /* That closes output and restores terminal, too. */ return 0; }