SEXP do_read_mp3(SEXP s_blob) { state_t state; mad_decoder_t decoder; int result; SEXP s_res; /* Unpack argument */ UNPACK_RAW_VECTOR(s_blob, blob, n_blob); /* Scan stream to determine the number of samples */ state.input = blob; state.input_size = n_blob; state.output_size = 0; mad_decoder_init(&decoder, &state, mad_input_cb, mad_header_cb, NULL, NULL, NULL, NULL); result = mad_decoder_run(&decoder, MAD_DECODER_MODE_SYNC); mad_decoder_finish(&decoder); if (0 != result) error("MAD decoder error. Your MP3 is likely corrupt."); /* Allocate result matrix based on calculated number of samples */ PROTECT(s_res = NEW_OBJECT(MAKE_CLASS("Wave"))); *REAL(GET_SLOT(s_res, install("samp.rate"))) = state.sample_rate; *REAL(GET_SLOT(s_res, install("bit"))) = 16; *LOGICAL(GET_SLOT(s_res, install("stereo"))) = state.output_channels == 2; SET_SLOT(s_res, install("left"), allocVector(INTSXP, state.output_size)); state.left_output = INTEGER(GET_SLOT(s_res, install("left"))); if (state.output_channels == 2) { SET_SLOT(s_res, install("right"), allocVector(INTSXP, state.output_size)); state.right_output = INTEGER(GET_SLOT(s_res, install("right"))); } /* Run decoder again. This time decode frames and store PCM data in * state */ state.input = blob; state.input_size = n_blob; mad_decoder_init(&decoder, &state, mad_input_cb, NULL, NULL, mad_output_cb, NULL, NULL); result = mad_decoder_run(&decoder, MAD_DECODER_MODE_SYNC); mad_decoder_finish(&decoder); /* Unprotect memory */ UNPROTECT(1); /* s_res */ if (0 != result) error("MAD decoder error. Your MP3 is likely corrupt."); return s_res; }
/* * decode_mp3 */ int decode_mp3(http_t *p) { struct mad_decoder decoder; int result; buf1 = malloc (MP3_SIZE + MAD_BUFFER_GUARD); buf2 = malloc (MP3_SIZE + MAD_BUFFER_GUARD); buf = buf1; mad_decoder_init(&decoder, p, input, /* callback */ 0, /* header */ #ifdef EQ filter, #else 0, /* no filter */ #endif output, /* callback */ error, /* callback */ 0 /* message */ ); result = mad_decoder_run(&decoder, MAD_DECODER_MODE_SYNC); mad_decoder_finish(&decoder); free(buf1); free(buf2); return result; }
static int decode(unsigned char const *start, unsigned long length) { struct buffer buffer; struct mad_decoder decoder; int result; /* initialize our private message structure */ buffer.start = start; buffer.length = length; /* configure input, output, and error functions */ mad_decoder_init(&decoder, &buffer, input, 0 /* header */, 0 /* filter */, output, error, 0 /* message */); /* start decoding */ result = mad_decoder_run(&decoder, MAD_DECODER_MODE_SYNC); /* release the decoder */ mad_decoder_finish(&decoder); return result; }
//*************************************************************************** bool Kwave::MP3Decoder::decode(QWidget *widget, Kwave::MultiWriter &dst) { Q_ASSERT(m_source); if (!m_source) return false; m_source->seek(m_prepended_bytes); // skip id3v2 tag // set target of the decoding m_dest = &dst; m_failures = 0; m_parent_widget = widget; // setup the decoder struct mad_decoder decoder; mad_decoder_init(&decoder, this, _input_adapter, 0 /* header */, 0 /* filter */, _output_adapter, _error_adapter, 0 /* message */); // decode through libmad... int result = mad_decoder_run(&decoder, MAD_DECODER_MODE_SYNC); // release the decoder mad_decoder_finish(&decoder); return (result == 0); }
bool MP3ImportFileHandle::Import(TrackFactory *trackFactory, Track ***outTracks, int *outNumTracks) { int chn; /* Prepare decoder data, initialize decoder */ mPrivateData.file = mFile; mPrivateData.inputBuffer = new unsigned char [INPUT_BUFFER_SIZE]; mPrivateData.channels = NULL; mPrivateData.cancelled = false; mPrivateData.id3checked = false; mPrivateData.numChannels = 0; mPrivateData.trackFactory= trackFactory; mad_decoder_init(&mDecoder, &mPrivateData, input_cb, 0, 0, output_cb, error_cb, 0); /* and send the decoder on its way! */ if(mad_decoder_run(&mDecoder, MAD_DECODER_MODE_SYNC) == 0) { /* success */ /* printf("success\n"); */ mad_decoder_finish(&mDecoder); /* copy the WaveTrack pointers into the Track pointer list that * we are expected to fill */ *outTracks = new Track* [mPrivateData.numChannels]; for(chn = 0; chn < mPrivateData.numChannels; chn++) { mPrivateData.channels[chn]->Flush(); (*outTracks)[chn] = mPrivateData.channels[chn]; } *outNumTracks = mPrivateData.numChannels; delete mPrivateData.inputBuffer; delete[] mPrivateData.channels; return true; } else { /* failure */ /* printf("failure\n"); */ mad_decoder_finish(&mDecoder); /* delete everything */ for(chn = 0; chn < mPrivateData.numChannels; chn++) delete mPrivateData.channels[chn]; delete[] mPrivateData.channels; delete mPrivateData.inputBuffer; return false; } }
/// 创建编码器 BOOL CMp3Decoder::Create(void) { if(NULL != m_hHandleDecoder) return FALSE; mad_decoder_init(&m_MadDecoder, NULL, AudioInput, AudioHeader, AudioFilter, AudioOutput, Error, Message); m_hHandleDecoder = &m_MadDecoder; return TRUE; }
void *audeng_mad_play () { struct mad_decoder decoder; int result; // Initiliaze decoder mad_decoder_init(&decoder, &audeng_buffer, audeng_mad_input, 0, 0, audeng_mad_output, 0, 0); // Run the decoder result = mad_decoder_run(&decoder, MAD_DECODER_MODE_SYNC); // Clean up mad_decoder_finish(&decoder); pthread_exit(0); }
int MP3ImportFileHandle::Import(TrackFactory *trackFactory, TrackHolders &outTracks, Tags *tags) { outTracks.clear(); CreateProgress(); /* Prepare decoder data, initialize decoder */ mPrivateData.file = mFile; mPrivateData.inputBuffer = new unsigned char [INPUT_BUFFER_SIZE]; mPrivateData.progress = mProgress.get(); mPrivateData.updateResult= eProgressSuccess; mPrivateData.id3checked = false; mPrivateData.numChannels = 0; mPrivateData.trackFactory= trackFactory; mad_decoder_init(&mDecoder, &mPrivateData, input_cb, 0, 0, output_cb, error_cb, 0); /* and send the decoder on its way! */ bool res = (mad_decoder_run(&mDecoder, MAD_DECODER_MODE_SYNC) == 0) && (mPrivateData.numChannels > 0) && !(mPrivateData.updateResult == eProgressCancelled) && !(mPrivateData.updateResult == eProgressFailed); mad_decoder_finish(&mDecoder); delete[] mPrivateData.inputBuffer; if (!res) { /* failure */ /* printf("failure\n"); */ return (mPrivateData.updateResult); } /* success */ /* printf("success\n"); */ /* copy the WaveTrack pointers into the Track pointer list that * we are expected to fill */ for(const auto &channel : mPrivateData.channels) { channel->Flush(); } outTracks.swap(mPrivateData.channels); /* Read in any metadata */ ImportID3(tags); return mPrivateData.updateResult; }
int slimaudio_decoder_mad_process(slimaudio_t *audio) { /* configure input, output, and error functions */ mad_decoder_init(&audio->mad_decoder, audio, mad_input, 0 /* header */, 0 /* filter */, mad_output, mad_error, 0 /* message */); /* start decoding */ audio->decoder_end_of_stream = false; int result = mad_decoder_run(&audio->mad_decoder, MAD_DECODER_MODE_SYNC); if (result != 0) return -1; /* release the decoder */ mad_decoder_finish(&audio->mad_decoder); return 0; }
void play(FILE *fp) { struct stream data; struct mad_decoder dec; memset(&data, 0, sizeof data); data.fp = fp; if(NULL == data.fp) { fprintf(stderr, "stream is null\n"); return; } ao_initialize(); data.driver_id = ao_default_driver_id(); if(-1 == data.driver_id) { fprintf(stderr, "no driver has been found: %s", strerror(errno)); return; } data.fmt.bits = 16; data.fmt.rate = 44100; data.fmt.channels = 2; data.fmt.byte_format = AO_FMT_NATIVE; data.device = ao_open_live(data.driver_id, &data.fmt, NULL); if(NULL == data.device) { fprintf(stderr, "unable to open device: %s", strerror(errno)); return; } mad_decoder_init(&dec, &data, input, NULL, NULL, output, NULL, NULL); mad_decoder_run(&dec, MAD_DECODER_MODE_SYNC); mad_decoder_finish(&dec); ao_close(data.device); ao_shutdown(); }
bool MADStream::openFromFile(const std::string& loc) { if (mFdm) { munmap(mFdm, mStat.st_size); mCurrentSamples.clear(); mad_decoder_finish(&mDecoder); } int fd = ::open(loc.c_str(), O_RDONLY); if (fstat(fd, &mStat) == -1 || mStat.st_size == 0) { std::cerr << "Fstat failed (" << loc << ")" << std::endl; return false; } void* m = mmap(0, mStat.st_size, PROT_READ, MAP_SHARED, fd, 0); if (m == MAP_FAILED) { std::cerr << "mmap failed (" << loc << ")" << std::endl; return false; } mFdm = (unsigned char*)m; mReadProgress = mStat.st_size; mad_decoder_init(&mDecoder, this, ms_input, ms_header, 0, ms_output, ms_error, 0); new std::thread( [&]() { mad_decoder_run(&mDecoder, MAD_DECODER_MODE_SYNC); }); alCheck(alSourcef(alSource, AL_PITCH, 1)); alCheck(alSourcef(alSource, AL_GAIN, 1)); alCheck(alSource3f(alSource, AL_POSITION, 0, 0, 0)); alCheck(alSource3f(alSource, AL_VELOCITY, 0, 0, 0)); alCheck(alSourcei(alSource, AL_LOOPING, AL_FALSE)); return true; }
IoObject *IoMP3Decoder_start(IoMP3Decoder *self, IoObject *locals, IoMessage *m) { int result; DATA(self)->isRunning = 1; DATA(self)->lastInputPos = 0; mad_decoder_init(&(DATA(self)->decoder), (void *)self, IoMP3Decoder_inputCallback, 0 /* header */, 0 /* filter */, IoMP3Decoder_outputCallback, IoMP3Decoder_errorCallback, 0 /* message */); /* start decoding */ result = mad_decoder_run(&(DATA(self)->decoder), MAD_DECODER_MODE_SYNC); mad_decoder_finish(&(DATA(self)->decoder)); /* release the decoder */ return IONUMBER(result); }
int playback(FILE * streamfd, int pipefd) { killed = 0; signal(SIGUSR1, sighand); #ifndef EXTERN_ONLY if(!haskey(& rc, "extern")) { const char * freetrack = NULL; struct stream data; struct mad_decoder dec; #ifdef LIBAO static int ao_initialized = 0; if(!ao_initialized) { ao_initialize(); ao_initialized = !0; } #else unsigned arg; int fd; #endif memset(& data, 0, sizeof(struct stream)); /* Check if there's a stream timeout configured and set it up for timed reads later. */ data.timeout = -1; if(haskey(& rc, "stream-timeout")) { const char * timeout = value(& rc, "stream-timeout"); data.timeout = atoi(timeout); if(data.timeout <= 0) { if(data.timeout < 0) fputs("Invalid stream-timeout.\n", stderr); data.timeout = -1; } } data.streamfd = streamfd; data.parent = getppid(); data.pipefd = pipefd; fcntl(pipefd, F_SETFL, O_NONBLOCK); #ifdef LIBAO data.driver_id = ao_default_driver_id(); if(-1 == data.driver_id) { fputs("Unable to find any usable output device!\n", stderr); return 0; } data.fmt.bits = 16; data.fmt.rate = 44100; data.fmt.channels = 2; data.fmt.byte_format = AO_FMT_NATIVE; data.device = ao_open_live(data.driver_id,&data.fmt,NULL); if(NULL == data.device) { fprintf(stderr, "Unable to open device. %s.\n", strerror(errno)); return 0; } #else data.audiofd = fd = open(value(& rc, "device"), O_WRONLY); if(-1 == data.audiofd) { fprintf( stderr, "Couldn't open %s! %s.\n", value(& rc, "device"), strerror(errno) ); return 0; } arg = 16; /* 16 bits */ ioctl(data.audiofd, SOUND_PCM_WRITE_BITS, & arg); #endif freetrack = value(& track, "freeTrackURL"); if(freetrack && strlen(freetrack) > 0 && haskey(& rc, "download")) { char * dnam; int rv; data.finpath = strdup(meta(value(& rc, "download"), M_RELAXPATH, & track)); assert(data.finpath != NULL); data.tmppath = strjoin("", data.finpath, ".streaming", NULL); assert(data.tmppath != NULL); dnam = strdup(data.tmppath); rv = dnam ? mkpath(dirname(dnam)) : -1; free(dnam); if(access(data.tmppath, R_OK) == -1) { data.dump = (rv == 0) ? fopen(data.tmppath, "w") : NULL; if(!data.dump) fprintf(stderr, "Can't write download to %s.\n", data.tmppath); } else { data.dump = NULL; } } mad_decoder_init(& dec, & data, input, NULL, NULL, output, NULL, NULL); mad_decoder_run(& dec, MAD_DECODER_MODE_SYNC); #ifndef LIBAO close(fd); #endif mad_decoder_finish(& dec); if(data.dump) { fclose(data.dump); if(killed) { unlink(data.tmppath); } else { int rv; #ifdef TAGLIB TagLib_File *tagme = taglib_file_new(data.tmppath); if(tagme != NULL) { TagLib_Tag *tag = taglib_file_tag(tagme); taglib_tag_set_title(tag, value(&track, "title")); taglib_tag_set_artist(tag, value(&track, "creator")); taglib_tag_set_album(tag, value(&track, "album")); taglib_file_save(tagme); taglib_file_free(tagme); } #endif if(haskey(& rc, "pp-cmd")) { const char *ppcmd = value(& rc, "pp-cmd"); size_t ppcmdlen = strlen(ppcmd); char *path = shellescape(data.tmppath); assert(path != NULL); size_t pathlen = strlen(path); char *command = malloc(ppcmdlen + pathlen + 2); assert(command != NULL); memcpy(command, ppcmd, ppcmdlen); command[ppcmdlen] = ' '; memcpy(command + ppcmdlen + 1, path, pathlen); command[ppcmdlen + 1 + pathlen] = 0; run(command); free(path); free(command); } rv = rename(data.tmppath, data.finpath); if (rv == -1) fprintf(stderr, "Can't rename %s to %s\n", data.tmppath, data.finpath); } free(data.tmppath); free(data.finpath); } } else #endif { pid_t ppid = getppid(), cpid = 0; const char * cmd = meta(value(& rc, "extern"), M_SHELLESC, & track); FILE * ext = openpipe(cmd, & cpid); unsigned char * buf; if(!ext) { fprintf(stderr, "Failed to execute external player (%s). %s.\n", cmd, strerror(errno)); return 0; } if(!(buf = calloc(BUFSIZE + 1, sizeof(unsigned char)))) { fputs("Couldn't allocate enough memory for input buffer.\n", stderr); fclose(ext); return 0; } while(!feof(streamfd)) { signed nbyte = fread(buf, sizeof(unsigned char), BUFSIZE, streamfd); if(nbyte > 0) { fwrite(buf, sizeof(unsigned char), nbyte, ext); fflush(ext); } if(kill(ppid, 0) == -1 && errno == ESRCH) break; if(killed) break; } free(buf); fclose(ext); waitpid(cpid, NULL, 0); } return !0; }
int main(int argc, char *argv[]) { int fd = 0; char *currentfile, old_dir[PATH_MAX]; playlist *pl = NULL; struct id3_file *id3struct = NULL; struct id3_tag *id3tag = NULL; int retval; buffer playbuf; struct mad_decoder decoder; pthread_t keyb_thread; key_t sem_key; key_t mem_key; key_t frames_key; union semun sem_ops; int shm_id; int frames_id; mad_decoder_position = 0; output_buffer_position = 0; old_dir[0] = '\0'; playbuf.pl = pl = new_playlist(); if (!pl) { fprintf(stderr, "malloc failed at startup!\n"); exit(1); } loop_remaining = 1; options.volume = MAD_F_ONE; status = MPG321_PLAYING; /* Get the command line options */ parse_options(argc, argv, pl); if(options.opt & MPG321_PRINT_FFT) if(!(options.opt & MPG321_REMOTE_PLAY)) { /* printf("FFT analysis can only be used in Remote mode play.\n\n"); */ usage(argv[0]); exit(0); } /* If there were no files and no playlist specified just print the usage */ if (!playlist_file && optind == argc) { usage(argv[0]); exit(0); } if (playlist_file) load_playlist(pl, playlist_file); if(options.opt & MPG321_RECURSIVE_DIR) add_cmdline_files_recursive_dir(pl, argv); else add_cmdline_files(pl, argv); if (shuffle_play) shuffle_files(pl); if(options.opt & MPG321_ENABLE_BUFFER) { /* Initialize semaphore and shared memeory */ if(access(argv[0],X_OK) == 0) sem_key = ftok(argv[0],0); else sem_key = ftok(MPG321_PATH,0); if(sem_key == -1) { perror("Cannot obtain resources for semaphores"); exit(EXIT_FAILURE); } semarray = semget(sem_key,3,IPC_CREAT | IPC_EXCL | S_IRWXU); if(semarray == -1) { perror("Cannot initialize semaphores"); exit(EXIT_FAILURE); } sem_ops.val = buffer_size-1; if(semctl(semarray,0,SETVAL,sem_ops) == -1) { perror("Error while initializing mad_decoder semaphore"); if(semctl(semarray,0,IPC_RMID) == -1) perror("Error while destroying semaphores"); goto out; //exit(EXIT_FAILURE); } sem_ops.val = 0; if(semctl(semarray,1,SETVAL,sem_ops) == -1) { perror("Error while initializing mad_decoder semaphore"); if(semctl(semarray,0,IPC_RMID) == -1) perror("Error while destroying semaphores"); goto out; //exit(EXIT_FAILURE); } sem_ops.val = 0; if(semctl(semarray,2,SETVAL,sem_ops) == -1) { perror("Error while initializing mad_decoder semaphore"); if(semctl(semarray,0,IPC_RMID) == -1) perror("Error while destroying semaphores"); goto out; //exit(EXIT_FAILURE); } /* Shared Memory */ mem_key = ftok(argv[0],1); shm_id = shmget(mem_key,buffer_size * sizeof(output_frame), IPC_CREAT | S_IREAD | S_IWRITE); if(shm_id == -1) { perror("Cannot initialize shared buffer"); goto out; //exit(EXIT_FAILURE); } Output_Queue = shmat(shm_id,NULL,0); if(*(int *)Output_Queue == -1) { perror("Error while attaching shared buffer to mad_decoder"); if(shmctl(shm_id,IPC_RMID,NULL)) perror("Cannot destroy shared buffer"); goto out; //exit(EXIT_FAILURE); } static int n; for(n=0;n<buffer_size;n++) { memset((Output_Queue+n)->data,'\0',4608); memset((Output_Queue+n)->time,'\0',80); (Output_Queue+n)->length = 0; (Output_Queue+n)->seconds = 0; (Output_Queue+n)->num_frames = 0; } frames_key = ftok(argv[0],2); frames_id = shmget(frames_key,buffer_size * sizeof(decoded_frames), IPC_CREAT | S_IREAD | S_IWRITE); if(frames_id == -1) { perror("Cannot initialize shared frames counter"); goto out; //exit(EXIT_FAILURE); } Decoded_Frames = shmat(frames_id,NULL,0); if(*(int *)Decoded_Frames == -1) { perror("Error while attaching shared frames counter to mad_decoder"); if(shmctl(frames_id,IPC_RMID,NULL)) perror("Cannot destroy shared frames counter"); goto out; //exit(EXIT_FAILURE); } Decoded_Frames->is_http = 0; Decoded_Frames->is_file = 0; } else { ao_initialize(); check_default_play_device(); } if (!(options.opt & MPG321_REMOTE_PLAY)) { handle_signals(-1); /* initialize signal handler */ remote_input_buf[0] = '\0'; } if (!(options.opt & MPG321_QUIET_PLAY)) mpg123_boilerplate(); if (options.opt & MPG321_REMOTE_PLAY) { printf ("@R MPG123\n"); if(options.opt & MPG321_ENABLE_BUFFER) { #ifdef HAVE_ALSA init_alsa_volume_control("default"); /* For the moment use "default", it works on most of the systems. Tested in Debian,Fedora,Ubuntu,RedHat,CentOS,Gentoo */ if(options.volume != MAD_F_ONE) mpg321_alsa_set_volume((long)options.volume*volume_max/100); #endif } } /* Fork here. */ if(options.opt & MPG321_ENABLE_BUFFER) { output_pid = fork(); if(output_pid == -1) { perror("Error while forking output process"); goto out; /* Release shared memeory and semaphores */ // exit(EXIT_FAILURE); } if(output_pid == 0) { frame_buffer_p(); exit(EXIT_SUCCESS); } signal(SIGUSR1,handle_signals); if(!(options.opt & MPG321_REMOTE_PLAY)) { #ifdef HAVE_ALSA init_alsa_volume_control("default"); if(options.volume != MAD_F_ONE) mpg321_alsa_set_volume((long)options.volume*volume_max/100); #endif } } if( (options.volume != MAD_F_ONE) && !(options.opt & MPG321_ENABLE_BUFFER)) { options.volume = mad_f_tofixed((long)options.volume/100.0); } else{ options.volume = MAD_F_ONE; /* When using the buffer options.volume when decoding each frame should be equal to MAD_F_ONE */ // options.volume = mad_f_tofixed((long)100.0/100.0); } if (!(options.opt & MPG321_REMOTE_PLAY)) { if(options.opt & MPG321_ENABLE_BASIC) { /* Now create and detach the basic controls thread */ sem_init(&main_lock,0,0); pthread_create(&keyb_thread,NULL,read_keyb,NULL); pthread_detach(keyb_thread); } } if(set_xterm) { tty_control(); get_term_title(title); }else { if (!(options.opt & MPG321_REMOTE_PLAY)) { if (tcgetattr(0, &terminal_settings) < 0) perror("tcgetattr()"); memcpy(&old_terminal_settings, &terminal_settings, sizeof(struct termios)); /* Early thread start */ sem_post(&main_lock); } } /* Play the mpeg files or zip it! */ while((currentfile = get_next_file(pl, &playbuf))) { //printf("Current File: %s\n",currentfile); if (quit_now) break; signal(SIGINT, SIG_DFL); playbuf.buf = NULL; playbuf.fd = -1; playbuf.length = 0; playbuf.done = 0; playbuf.num_frames = 0; current_frame = 0; playbuf.max_frames = -1; strncpy(playbuf.filename,currentfile, PATH_MAX); playbuf.filename[PATH_MAX-1] = '\0'; if (status == MPG321_PLAYING || status == MPG321_STOPPED) file_change = 1; mad_timer_reset(&playbuf.duration); mad_timer_reset(¤t_time); id3struct = NULL; if (!(options.opt & MPG321_QUIET_PLAY) && file_change) { /* id3struct = id3_file_open (currentfile, ID3_FILE_MODE_READONLY);*/ if (id3struct == NULL) get_id3_info(currentfile, &id3struct, &id3tag); if(id3tag) show_id3(id3tag); } scrobbler_time = -1; if(options.opt & MPG321_USE_SCROBBLER) { if(id3struct == NULL) get_id3_info(currentfile,&id3struct,&id3tag); if (id3tag) { char emptystring[31], emptyyear[5] = " "; int i; if(parse_id3(scrobbler_args, id3tag)) { memset(emptystring, ' ', 30); emptystring[30] = '\0'; if((options.opt & MPG321_VERBOSE_PLAY) && (options.opt & MPG321_USE_SCROBBLER)) { fprintf(stderr, "\nPreparing for the AudioScrobbler:\n"); for(i = 0; i < 6; i++) { if(scrobbler_args[i] == NULL) scrobbler_args[i] = ( i == 3 ? emptyyear: emptystring); fprintf(stderr, "- %s\n", scrobbler_args[i]); } } } } } if (options.opt & MPG321_REMOTE_PLAY && file_change) { if(id3struct == NULL) get_id3_info(currentfile, &id3struct, &id3tag); if(id3tag) { if (!show_id3(id3tag)) { /* This shouldn't be necessary, but it appears that libid3tag doesn't necessarily know if there are no id3 tags on a given mp3 */ char * basec = strdup(currentfile); char * basen = basename(basec); char * dot = strrchr(basen, '.'); if (dot) *dot = '\0'; printf("@I %s\n", basen); free(basec); } } else { char * basec = strdup(currentfile); char * basen = basename(basec); char * dot = strrchr(basen, '.'); if (dot) *dot = '\0'; printf("@I %s\n", basen); free(basec); } } if(id3struct != NULL) id3_file_close(id3struct); /* Create the MPEG stream */ /* Check if source is on the network */ if((fd = raw_open(currentfile)) != 0 || (fd = http_open(currentfile)) != 0 || (fd = ftp_open(currentfile)) != 0) { playbuf.fd = fd; playbuf.buf = malloc(BUF_SIZE); playbuf.length = BUF_SIZE; if(options.opt & MPG321_ENABLE_BUFFER) { Decoded_Frames->is_http = 1; Decoded_Frames->is_file = 0; } calc_http_length(&playbuf); mad_decoder_init(&decoder, &playbuf, read_from_fd, read_header, /*filter*/0, output, handle_error, /* message */ 0); } /* Check if we are to use stdin for input */ else if(strcmp(currentfile, "-") == 0) { playbuf.fd = fileno(stdin); playbuf.buf = malloc(BUF_SIZE); playbuf.length = BUF_SIZE; mad_decoder_init(&decoder, &playbuf, read_from_fd, read_header, /*filter*/0, output, handle_error, /* message */ 0); } /* currentfile is a local file (presumably.) mmap() it */ else { struct stat stat; if((fd = open(currentfile, O_RDONLY)) == -1) { mpg321_error(currentfile); /* Restore TTY from keyboard reader thread */ if(options.opt & MPG321_ENABLE_BASIC) if (tcsetattr(0, TCSANOW, &old_terminal_settings) < 0) perror("tcsetattr ICANON"); if(set_xterm) { set_tty_restore(); osc_print(0,0,title); if (ctty) fclose(ctty); } if( options.opt & MPG321_REMOTE_PLAY) if(remote_restart) { clear_remote_file(pl); /* If restart is enabled, restart remote shell when file doesn't exist*/ continue; } if(options.opt & MPG321_ENABLE_BUFFER) goto out; else exit(1); /* mpg123 stops immediately if it can't open a file */ /* If sth goes wrong break!!!*/ break; } if(options.opt & MPG321_ENABLE_BUFFER) { Decoded_Frames->is_http = 0; Decoded_Frames->is_file = 1; } if(fstat(fd, &stat) == -1) { mpg321_error(currentfile); close(fd); continue; } if (!S_ISREG(stat.st_mode)) { if(S_ISFIFO(stat.st_mode)) { fallback = 1; goto fall_back_to_read_from_fd; } close(fd); continue; } retval = calc_length(currentfile, &playbuf); //FIXME Check also if it is an mp3 file. If not break and go to the next file possible if(retval < 0) { if(options.opt & MPG321_REMOTE_PLAY) { fprintf(stderr,"@E Corrupted file: %s\n",currentfile); close(fd); if(remote_restart) { clear_remote_file(pl); /* If restart is enabled, restart remote shell when file is corrupted */ continue; } break; } mpg321_error(currentfile); close(fd); // break; //FIXME Break and stop OR continue the playlist ???? continue; } if((options.opt & MPG321_VERBOSE_PLAY) && (options.opt & MPG321_USE_SCROBBLER)) fprintf(stderr, "Track duration: %ld seconds\n",playbuf.duration.seconds); if(options.opt & MPG321_USE_SCROBBLER) scrobbler_set_time(playbuf.duration.seconds); if ((options.maxframes != -1) && (options.maxframes <= playbuf.num_frames)) { playbuf.max_frames = options.maxframes; } playbuf.frames = malloc((playbuf.num_frames + 1) * sizeof(void*)); playbuf.times = malloc((playbuf.num_frames + 1) * sizeof(mad_timer_t)); #ifdef __uClinux__ if((playbuf.buf = mmap(0, playbuf.length, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED) #else if((playbuf.buf = mmap(0, playbuf.length, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) #endif { mpg321_error(currentfile); continue; } playbuf.frames[0] = playbuf.buf; mad_decoder_init(&decoder, &playbuf, read_from_mmap, read_header, /*filter*/0, output, handle_error, /* message */ 0); fall_back_to_read_from_fd: //FIXME. Reported that on some embedded systems with low memory, less than 16MB doesn't work properly. if(fallback) { playbuf.fd = fd; playbuf.buf = malloc(BUF_SIZE); playbuf.length = BUF_SIZE; mad_decoder_init(&decoder, &playbuf, read_from_fd, read_header, /*filter*/0, output, handle_error, /* message */ 0); fallback = 1; } } if(!(options.opt & MPG321_QUIET_PLAY))/*zip it!!!*/ { /* Because dirname might modify the argument */ char * dirc = strdup(currentfile); char * basec = strdup(currentfile); char * basen = basename(basec); char * dirn = dirname(dirc); /* make sure that the file has a pathname; otherwise don't print out a Directory: listing */ if(strchr(currentfile, '/') && strncmp(old_dir, dirn, PATH_MAX) != 0) { /* Print information about the file */ fprintf(stderr, "\n"); fprintf(stderr,"Directory: %s\n", dirn); strncpy(old_dir, dirn, PATH_MAX); old_dir[PATH_MAX-1] = '\0'; } /* print a newline between different songs only, not after Directory: listing */ else { fprintf(stderr, "\n"); } fprintf(stderr,"Playing MPEG stream from %s ...\n", basen); /* Printing xterm title */ if(set_xterm) { osc_print(0,0,basen); } free(dirc); free(basec); } signal(SIGINT, handle_signals); signal(SIGCHLD, handle_sigchld); /*Give control back so that we can implement SIG's*/ if(set_xterm) { set_tty_restore(); if (tcgetattr(0, &terminal_settings) < 0) perror("tcgetattr()"); memcpy(&old_terminal_settings, &terminal_settings, sizeof(struct termios)); /* disable canonical mode processing in the line discipline driver */ terminal_settings.c_lflag &= ~(ICANON | ECHO); /* apply our new settings */ if (tcsetattr(0, TCSANOW, &terminal_settings) < 0) perror("tcsetattr ICANON"); if(options.opt & MPG321_ENABLE_BASIC) { /* Late thread start */ sem_post(&main_lock); } } /* Every time the user gets us to rewind, we exit decoding, reinitialize it, and re-start it */ if(options.opt & MPG321_ENABLE_BUFFER) { Decoded_Frames->total_decoded_frames = 0; Decoded_Frames->done = 0; } while (1) { decoder.options |= MAD_OPTION_IGNORECRC; mad_decoder_run(&decoder, MAD_DECODER_MODE_SYNC); if(options.opt & MPG321_ENABLE_BUFFER) { static struct sembuf start_sops = {2,-1,0}; semop(semarray,&start_sops,1); mad_decoder_position = 0; output_buffer_position = 0; union semun sem_ops; sem_ops.val = 0; semctl(semarray,2,SETVAL,sem_ops); Decoded_Frames->total_decoded_frames = 0; Decoded_Frames->done = 0; Decoded_Frames->is_http = 0; Decoded_Frames->is_file = 0; } /* if we're rewinding on an mmap()ed stream */ if(status == MPG321_REWINDING && playbuf.fd == -1) { mad_decoder_init(&decoder, &playbuf, read_from_mmap, read_header, /*filter*/0, output, /*error*/0, /* message */ 0); } else break; } if (!(options.opt & MPG321_QUIET_PLAY)) { char time_formatted[11]; mad_timer_string(current_time, time_formatted, "%.1u:%.2u", MAD_UNITS_MINUTES, MAD_UNITS_SECONDS, 0); fprintf(stderr," \r"); fprintf(stderr, "\n[%s] Decoding of %s finished.\n",time_formatted, basename(currentfile)); /* Report total decoded seconds. Maybe for the frame buffer report only total played time?? */ } if (options.opt & MPG321_REMOTE_PLAY && status == MPG321_STOPPED) { clear_remote_file(pl); } mad_decoder_finish(&decoder); if (playbuf.frames) free(playbuf.frames); if (playbuf.times) free(playbuf.times); if (playbuf.fd == -1) { munmap(playbuf.buf, playbuf.length); close(fd); } else { free(playbuf.buf); if (playbuf.fd != fileno(stdin)) close(playbuf.fd); } } if(!(options.opt & MPG321_ENABLE_BUFFER)) { if(playdevice) ao_close(playdevice); ao_shutdown(); } if (!(options.opt & MPG321_REMOTE_PLAY)) { if(options.opt & MPG321_ENABLE_BASIC) { pflag = 1; /* Restore TTY from keyboard reader thread */ if (tcsetattr(0, TCSANOW, &old_terminal_settings) < 0) perror("tcsetattr ICANON"); } } /*Restoring TTY*/ if(set_xterm) { set_tty_restore(); osc_print(0,0,title); if (ctty) fclose(ctty); } out: if(options.opt & MPG321_ENABLE_BUFFER) { if(kill(output_pid,SIGUSR1) == -1) perror("Error while stopping output process"); static int wstatus; wait(&wstatus); if(wstatus == -1) perror("Error while waiting for output process to exit"); if(semctl(semarray,0,IPC_RMID) == -1) perror("Error while destroying semaphores"); if(shmdt(Output_Queue) == -1) perror("Error while detaching shared buffer"); if(shmctl(shm_id,IPC_RMID,NULL)) perror("Cannot destroy shared buffer"); if(shmctl(frames_id,IPC_RMID,NULL)) perror("Cannot destroy shared buffer"); } return(0); }
int MP3ImportFileHandle::Import(TrackFactory *trackFactory, Track ***outTracks, int *outNumTracks, Tags *tags) { int chn; CreateProgress(); /* Prepare decoder data, initialize decoder */ mPrivateData.file = mFile; mPrivateData.inputBuffer = new unsigned char [INPUT_BUFFER_SIZE]; mPrivateData.progress = mProgress; mPrivateData.channels = NULL; mPrivateData.cancelled = false; mPrivateData.id3checked = false; mPrivateData.numChannels = 0; mPrivateData.trackFactory= trackFactory; mad_decoder_init(&mDecoder, &mPrivateData, input_cb, 0, 0, output_cb, error_cb, 0); /* and send the decoder on its way! */ bool res = (mad_decoder_run(&mDecoder, MAD_DECODER_MODE_SYNC) == 0) && (mPrivateData.numChannels > 0) && (!mPrivateData.cancelled); mad_decoder_finish(&mDecoder); delete[] mPrivateData.inputBuffer; if (!res) { /* failure */ /* printf("failure\n"); */ /* delete everything */ for (chn = 0; chn < mPrivateData.numChannels; chn++) { delete mPrivateData.channels[chn]; } delete[] mPrivateData.channels; return (mPrivateData.cancelled ? eImportCancelled : eImportFailed); } /* success */ /* printf("success\n"); */ /* copy the WaveTrack pointers into the Track pointer list that * we are expected to fill */ *outNumTracks = mPrivateData.numChannels; *outTracks = new Track* [mPrivateData.numChannels]; for(chn = 0; chn < mPrivateData.numChannels; chn++) { mPrivateData.channels[chn]->Flush(); (*outTracks)[chn] = mPrivateData.channels[chn]; } delete[] mPrivateData.channels; /* Read in any metadata */ ImportID3(tags); return eImportSuccess; }
int main(int argc, char *argv[]) { int fd = 0; char *currentfile, old_dir[PATH_MAX]; playlist *pl = NULL; struct id3_file *id3struct = NULL; struct id3_tag *id3tag = NULL; buffer playbuf; struct mad_decoder decoder; old_dir[0] = '\0'; playbuf.pl = pl = new_playlist(); if (!pl) { fprintf(stderr, "malloc failed at startup!\n"); exit(1); } options.volume = MAD_F_ONE; status = MPG321_PLAYING; /* Get the command line options */ parse_options(argc, argv, pl); /* If there were no files and no playlist specified just print the usage */ if (!playlist_file && optind == argc) { usage(argv[0]); exit(0); } if (playlist_file) load_playlist(pl, playlist_file); add_cmdline_files(pl, argv); if (shuffle_play) shuffle_files(pl); ao_initialize(); check_default_play_device(); if (!(options.opt & MPG321_REMOTE_PLAY)) { handle_signals(-1); /* initialize signal handler */ remote_input_buf[0] = '\0'; } if (!(options.opt & MPG321_QUIET_PLAY)) mpg123_boilerplate(); if (options.opt & MPG321_REMOTE_PLAY) { printf ("@R MPG123\n"); } /* Play the mpeg files or zip it! */ while((currentfile = get_next_file(pl, &playbuf))) { if (quit_now) break; signal(SIGINT, SIG_DFL); playbuf.buf = NULL; playbuf.fd = -1; playbuf.length = 0; playbuf.done = 0; playbuf.num_frames = 0; playbuf.max_frames = -1; strncpy(playbuf.filename,currentfile, PATH_MAX); playbuf.filename[PATH_MAX-1] = '\0'; if (status == MPG321_PLAYING) file_change = 1; mad_timer_reset(&playbuf.duration); mad_timer_reset(¤t_time); if (!(options.opt & MPG321_QUIET_PLAY) && file_change) { id3struct = id3_file_open (currentfile, ID3_FILE_MODE_READONLY); if (id3struct) { id3tag = id3_file_tag (id3struct); if (id3tag) { show_id3 (id3tag); } id3_file_close (id3struct); } } if (options.opt & MPG321_REMOTE_PLAY && file_change) { id3struct = id3_file_open (currentfile, ID3_FILE_MODE_READONLY); if (id3struct) { id3tag = id3_file_tag (id3struct); if (id3tag) { if (!show_id3(id3tag)) { /* This shouldn't be necessary, but it appears that libid3tag doesn't necessarily know if there are no id3 tags on a given mp3 */ char * basec = strdup(currentfile); char * basen = basename(basec); char * dot = strrchr(basen, '.'); if (dot) *dot = '\0'; printf("@I %s\n", basen); free(basec); } } else { fprintf(stderr, "Allocation error"); exit(1); } id3_file_close (id3struct); } else { char * basec = strdup(currentfile); char * basen = basename(basec); char * dot = strrchr(basen, '.'); if (dot) *dot = '\0'; printf("@I %s\n", basen); free(basec); } } /* Create the MPEG stream */ /* Check if source is on the network */ if((fd = raw_open(currentfile)) != 0 || (fd = http_open(currentfile)) != 0 || (fd = ftp_open(currentfile)) != 0) { playbuf.fd = fd; playbuf.buf = malloc(BUF_SIZE); playbuf.length = BUF_SIZE; mad_decoder_init(&decoder, &playbuf, read_from_fd, read_header, /*filter*/0, output, /*error*/0, /* message */ 0); } /* Check if we are to use stdin for input */ else if(strcmp(currentfile, "-") == 0) { playbuf.fd = fileno(stdin); playbuf.buf = malloc(BUF_SIZE); playbuf.length = BUF_SIZE; mad_decoder_init(&decoder, &playbuf, read_from_fd, read_header, /*filter*/0, output, /*error*/0, /* message */ 0); } /* currentfile is a local file (presumably.) mmap() it */ else { struct stat stat; if((fd = open(currentfile, O_RDONLY)) == -1) { mpg321_error(currentfile); /* mpg123 stops immediately if it can't open a file */ break; } if(fstat(fd, &stat) == -1) { close(fd); mpg321_error(currentfile); continue; } if (!S_ISREG(stat.st_mode)) { close(fd); continue; } calc_length(currentfile, &playbuf); if ((options.maxframes != -1) && (options.maxframes <= playbuf.num_frames)) { playbuf.max_frames = options.maxframes; } playbuf.frames = malloc((playbuf.num_frames + 1) * sizeof(void*)); playbuf.times = malloc((playbuf.num_frames + 1) * sizeof(mad_timer_t)); if((playbuf.buf = mmap(0, playbuf.length, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) { close(fd); mpg321_error(currentfile); continue; } close(fd); playbuf.frames[0] = playbuf.buf; mad_decoder_init(&decoder, &playbuf, read_from_mmap, read_header, /*filter*/0, output, /*error*/0, /* message */ 0); } if(!(options.opt & MPG321_QUIET_PLAY))/*zip it!!!*/ { /* Because dirname might modify the argument */ char * dirc = strdup(currentfile); char * basec = strdup(currentfile); char * basen = basename(basec); char * dirn = dirname(dirc); /* make sure that the file has a pathname; otherwise don't print out a Directory: listing */ if(strchr(currentfile, '/') && strncmp(old_dir, dirn, PATH_MAX) != 0) { /* Print information about the file */ fprintf(stderr, "\n"); fprintf(stderr,"Directory: %s/\n", dirn); strncpy(old_dir, dirn, PATH_MAX); old_dir[PATH_MAX-1] = '\0'; } /* print a newline between different songs only, not after Directory: listing */ else { fprintf(stderr, "\n"); } fprintf(stderr,"Playing MPEG stream from %s ...\n", basen); free(dirc); free(basec); } signal(SIGINT, handle_signals); /* Every time the user gets us to rewind, we exit decoding, reinitialize it, and re-start it */ while (1) { mad_decoder_run(&decoder, MAD_DECODER_MODE_SYNC); /* if we're rewinding on an mmap()ed stream */ if(status == MPG321_REWINDING && playbuf.fd == -1) { mad_decoder_init(&decoder, &playbuf, read_from_mmap, read_header, /*filter*/0, output, /*error*/0, /* message */ 0); } else break; } if (!(options.opt & MPG321_QUIET_PLAY)) { char time_formatted[11]; mad_timer_string(current_time, time_formatted, "%.1u:%.2u", MAD_UNITS_MINUTES, MAD_UNITS_SECONDS, 0); fprintf(stderr, "\n[%s] Decoding of %s finished.\n",time_formatted, basename(currentfile)); } if (options.opt & MPG321_REMOTE_PLAY && status == MPG321_STOPPED) { clear_remote_file(pl); } mad_decoder_finish(&decoder); if (quit_now) break; if (playbuf.frames) free(playbuf.frames); if (playbuf.times) free(playbuf.times); if (playbuf.fd == -1) { munmap(playbuf.buf, playbuf.length); } else { free(playbuf.buf); if (playbuf.fd != fileno(stdin)) close(playbuf.fd); } } if(playdevice) ao_close(playdevice); ao_shutdown(); #if defined(RAW_SUPPORT) || defined(HTTP_SUPPORT) || defined(FTP_SUPPORT) if(fd) close(fd); #endif return(0); }