static void capline(mpg123_handle *mh, long rate) { int enci; const int *encs; size_t num_encs; mpg123_encodings(&encs, &num_encs); fprintf(stderr," %5ld |", pitch_rate(rate)); for(enci=0; enci<num_encs; ++enci) { switch(mpg123_format_support(mh, rate, encs[enci])) { case MPG123_MONO: fprintf(stderr, " M |"); break; case MPG123_STEREO: fprintf(stderr, " S |"); break; case MPG123_MONO|MPG123_STEREO: fprintf(stderr, " M/S |"); break; default: fprintf(stderr, " |"); } } fprintf(stderr, "\n"); }
/* * Change the playback sample rate. * Consider that changing it after starting playback is not covered by gapless code! */ static void reset_audio(long rate, int channels, int format) { #ifndef NOXFERMEM if (param.usebuffer) { /* wait until the buffer is empty, * then tell the buffer process to * change the sample rate. [OF] */ while (xfermem_get_usedspace(buffermem) > 0) if (xfermem_block(XF_WRITER, buffermem) == XF_CMD_TERMINATE) { intflag = TRUE; break; } buffermem->freeindex = -1; buffermem->readindex = 0; /* I know what I'm doing! ;-) */ buffermem->freeindex = 0; if (intflag) return; buffermem->rate = pitch_rate(rate); buffermem->channels = channels; buffermem->format = format; buffer_reset(); } else { #endif if(ao == NULL) { error("Audio handle should not be NULL here!"); safe_exit(98); } ao->rate = pitch_rate(rate); ao->channels = channels; ao->format = format; if(reset_output(ao) < 0) { error1("failed to reset audio device: %s", strerror(errno)); safe_exit(1); } #ifndef NOXFERMEM } #endif }
/* This uses the currently opened audio device, queries its caps. In case of buffered playback, this works _once_ by querying the buffer for the caps before entering the main loop. */ void audio_capabilities(audio_output_t *ao, mpg123_handle *mh) { int force_fmt = 0; int fmts; size_t ri; /* Pitching introduces a difference between decoder rate and playback rate. */ long rate, decode_rate; int channels; const long *rates; size_t num_rates, rlimit; debug("audio_capabilities"); mpg123_rates(&rates, &num_rates); mpg123_format_none(mh); /* Start with nothing. */ if(param.force_encoding != NULL) { int i; if(!param.quiet) fprintf(stderr, "Note: forcing output encoding %s\n", param.force_encoding); for(i=0;i<KNOWN_ENCS;++i) if(!strncasecmp(encdesc[i].name, param.force_encoding, encdesc[i].nlen)) { force_fmt = encdesc[i].code; break; } if(i==KNOWN_ENCS) { error1("Failed to find an encoding to match requested \"%s\"!\n", param.force_encoding); return; /* No capabilities at all... */ } else if(param.verbose > 2) fprintf(stderr, "Note: forcing encoding code 0x%x\n", force_fmt); } rlimit = param.force_rate > 0 ? num_rates+1 : num_rates; for(channels=1; channels<=2; channels++) for(ri = 0;ri<rlimit;ri++) { decode_rate = ri < num_rates ? rates[ri] : param.force_rate; rate = pitch_rate(decode_rate); if(param.verbose > 2) fprintf(stderr, "Note: checking support for %liHz/%ich.\n", rate, channels); #ifndef NOXFERMEM if(param.usebuffer) { /* Ask the buffer process. It is waiting for this. */ buffermem->rate = rate; buffermem->channels = channels; buffermem->format = 0; /* Just have it initialized safely. */ debug2("asking for formats for %liHz/%ich", rate, channels); xfermem_putcmd(buffermem->fd[XF_WRITER], XF_CMD_AUDIOCAP); xfermem_getcmd(buffermem->fd[XF_WRITER], TRUE); fmts = buffermem->format; } else #endif { /* Check myself. */ ao->rate = rate; ao->channels = channels; fmts = ao->get_formats(ao); } if(param.verbose > 2) fprintf(stderr, "Note: result 0x%x\n", fmts); if(force_fmt) { /* Filter for forced encoding. */ if((fmts & force_fmt) == force_fmt) fmts = force_fmt; else fmts = 0; /* Nothing else! */ if(param.verbose > 2) fprintf(stderr, "Note: after forcing 0x%x\n", fmts); } if(fmts < 0) continue; else mpg123_format(mh, decode_rate, channels, fmts); } #ifndef NOXFERMEM /* Buffer loop shall start normal operation now. */ if(param.usebuffer) { xfermem_putcmd(buffermem->fd[XF_WRITER], XF_CMD_WAKEUP); xfermem_getcmd(buffermem->fd[XF_WRITER], TRUE); } #endif if(param.verbose > 1) print_capabilities(ao, mh); }