+2007-1-1 Keishi Suenaga <skeishi@yahoo.co.jp>
+
+ * timidity/timidity.c
+ timidity/w32_a.c
+ timidity/portaudio_a.c: can select optput device.
+
2007-01-01 Kentaro Sato <kentaro@ranvis.com>
* timidity/playmidi.[ch], timidity/readmidi.c:
#include "playmidi.h"
#include "miditrace.h"
+int opt_pa_device_id = -1;
+
#define DATA_BLOCK_SIZE (27648*4) /* WinNT Latency is 600 msec read pa_dsound.c */
#define SAMPLE_RATE (44100)
static int output_data(char *buf, int32 nbytes);
static int acntl(int request, void *arg);
+static void print_device_list(void);
+
static int framesPerBuffer=128;
static int stereo=2;
static int conv16_32 =0;
#if PORTAUDIO_V19
PaHostApiTypeId HostApiTypeId;
+PaHostApiIndex HostApiIndex;
const PaHostApiInfo *HostApiInfo;
PaDeviceIndex DeviceIndex;
const PaDeviceInfo *DeviceInfo;
double rate;
int n, nrates, include_enc, exclude_enc;
PaSampleFormat SampleFormat, nativeSampleFormats;
-
+
#ifdef AU_PORTAUDIO_DLL
#if PORTAUDIO_V19
{
pa_active = 1;
}
+ if (opt_pa_device_id == -2){
+ print_device_list();
+ goto error2;
+ }
#ifdef PORTAUDIO_V19
#ifdef AU_PORTAUDIO_DLL
- {
- PaHostApiIndex i, ApiCount;
- i = 0;
- ApiCount = Pa_GetHostApiCount();
- do{
- HostApiInfo=Pa_GetHostApiInfo(i);
- if( HostApiInfo->type == HostApiTypeId ) break;
- i++;
- }while ( i < ApiCount );
- if ( i == ApiCount ) goto error;
- }
+ PaHostApiIndex i, ApiCount;
+ i = 0;
+ ApiCount = Pa_GetHostApiCount();
+ do{
+ HostApiInfo=Pa_GetHostApiInfo(i);
+ if( HostApiInfo->type == HostApiTypeId ) break;
+ i++;
+ }while ( i < ApiCount );
+ if ( i == ApiCount ) goto error;
+
DeviceIndex = HostApiInfo->defaultOutputDevice;
if(DeviceIndex==paNoDevice) goto error;
- DeviceInfo = Pa_GetDeviceInfo( DeviceIndex);
- if(DeviceInfo==NULL) goto error;
-
#else
DeviceIndex = Pa_GetDefaultOutputDevice();
if(DeviceIndex==paNoDevice) goto error;
+#endif
DeviceInfo = Pa_GetDeviceInfo( DeviceIndex);
if(DeviceInfo==NULL) goto error;
-#endif
-
+
+ if(opt_pa_device_id != -1){
+ const PaDeviceInfo *id_DeviceInfo;
+ id_DeviceInfo=Pa_GetDeviceInfo((PaDeviceIndex)opt_pa_device_id);
+ if(id_DeviceInfo==NULL) goto error;
+ if( DeviceInfo->hostApi == id_DeviceInfo->hostApi){
+ DeviceIndex=(PaDeviceIndex)opt_pa_device_id;
+ DeviceInfo = id_DeviceInfo;
+ }
+ }
+
+
if (dpm.encoding & PE_24BIT) {
SampleFormat = paInt24;
}else if (dpm.encoding & PE_16BIT) {
return 0;
#else
- DeviceID = Pa_GetDefaultOutputDeviceID();
- if(DeviceID==paNoDevice) goto error2;
+ if(opt_pa_device_id != -1){
+ DeviceID = Pa_GetDefaultOutputDeviceID();
+ if(DeviceID==paNoDevice) goto error2;
+ }else{
+ DeviceID = opt_pa_device_id;
+ }
DeviceInfo = Pa_GetDeviceInfo( DeviceID);
if(DeviceInfo==NULL) goto error2;
nativeSampleFormats = DeviceInfo->nativeSampleFormats;
ctl->cmsg( CMSG_ERROR, VERB_NORMAL, "PortAudio error in acntl : %s\n", Pa_GetErrorText( err ) );
return -1;
}
+
+static void print_device_list(void){
+ PaDeviceIndex maxDeviceIndex, i;
+ PaHostApiIndex HostApiIndex;
+ const PaDeviceInfo* DeviceInfo;
+
+#if PORTAUDIO_V19
+ HostApiIndex=Pa_HostApiTypeIdToHostApiIndex(HostApiTypeId);
+#endif
+
+ maxDeviceIndex=Pa_GetDeviceCount();
+
+ for( i = 0; i < maxDeviceIndex; i++){
+ DeviceInfo=Pa_GetDeviceInfo(i);
+#if PORTAUDIO_V19
+ if( DeviceInfo->hostApi == HostApiIndex){
+#endif
+ if( DeviceInfo->maxOutputChannels > 0){
+ ctl->cmsg( CMSG_ERROR, VERB_NORMAL, "%2d %s",i,DeviceInfo->name);
+ }
+#if PORTAUDIO_V19
+ }
+#endif
+ }
+}
+
TIM_OPT_OUTPUT_BITWIDTH,
TIM_OPT_OUTPUT_FORMAT,
TIM_OPT_OUTPUT_SWAB,
+ TIM_OPT_OUTPUT_DEVICE,
TIM_OPT_FLAC_VERIFY,
TIM_OPT_FLAC_PADDING,
TIM_OPT_FLAC_COMPLEVEL,
{ "output-alaw", no_argument, NULL, TIM_OPT_OUTPUT_FORMAT },
{ "no-output-swab", no_argument, NULL, TIM_OPT_OUTPUT_SWAB },
{ "output-swab", optional_argument, NULL, TIM_OPT_OUTPUT_SWAB },
+#if defined(AU_PORTAUDIO) || defined(AU_WIN32)
+ { "output-device", required_argument, NULL, TIM_OPT_OUTPUT_DEVICE },
+#endif
#ifdef AU_FLAC
{ "flac-verify", no_argument, NULL, TIM_OPT_FLAC_VERIFY },
{ "flac-padding", required_argument, NULL, TIM_OPT_FLAC_PADDING },
*opt_aq_fill_buff = NULL;
void timidity_init_aq_buff(void);
int opt_control_ratio = 0; /* Save -C option */
+#ifdef AU_PORTAUDIO
+extern int opt_pa_device_id;
+#endif
+#ifdef AU_W32
+extern int opt_wmme_device_id;
+#endif
int set_extension_modes(char *);
int set_ctl(char *);
static inline int parse_opt_output_bitwidth(const char *);
static inline int parse_opt_output_format(const char *);
static inline int parse_opt_output_swab(const char *);
+#if defined(AU_PORTAUDIO) || defined(AU_W32)
+static inline int parse_opt_output_device(const char *);
+#endif
#ifdef AU_FLAC
static inline int parse_opt_flac_verify(const char *);
static inline int parse_opt_flac_padding(const char *);
return parse_opt_output_format(arg);
case TIM_OPT_OUTPUT_SWAB:
return parse_opt_output_swab(arg);
+#if defined(AU_PORTAUDIO) || defined(AU_WIN32)
+ case TIM_OPT_OUTPUT_DEVICE:
+ return parse_opt_output_device(arg);
+#endif
#ifdef AU_FLAC
case TIM_OPT_FLAC_VERIFY:
return parse_opt_flac_verify(arg);
" `A' A-Law encoding" NLS
" `x' byte-swapped output" NLS, fp);
fputs(NLS, fp);
+#if defined(AU_PORTAUDIO) || defined(AU_WIN32)
+ fputs("Output device options (append to -O? option):" NLS
+" `d(num)' OutputDeviceID(if blank show available device list)" NLS, fp);
+ fputs(NLS, fp);
+#endif
fputs("Alternative output format long options:" NLS
" --output-stereo" NLS
" --output-mono" NLS
" --output-alaw" NLS
" --[no-]output-swab" NLS, fp);
fputs(NLS, fp);
+#if defined(AU_PORTAUDIO) || defined(AU_WIN32)
+ fputs("Output device long options:" NLS
+" --output-device=n (if n=-1 show available device list)" NLS, fp);
+ fputs(NLS, fp);
+#endif
+
fputs("Available WRD interfaces (-W, --wrd option):" NLS, fp);
for (wlpp = wrdt_list; (wlp = *wlpp) != NULL; wlpp++)
fprintf(fp, " -W%c %s" NLS, wlp->id, wlp->name);
pmp->encoding ^= PE_BYTESWAP; /* toggle */
pmp->encoding &= ~(PE_ULAW | PE_ALAW);
break;
+#if defined(AU_PORTAUDIO) || defined(AU_W32)
+ case 'd':
+#ifdef AU_PORTAUDIO
+ if (play_mode->id_character == 'p' || play_mode->id_character == 'P'||play_mode->id_character == 'o'){
+ int ret;
+ ret = sscanf(arg+1,"%d",&opt_pa_device_id);
+ if( (ret != 0) && (ret != EOF) ){
+ while( *(arg+1) >= '0' && *(arg + 1) <= '9') { arg++; }
+ }else{
+ opt_pa_device_id=-2;
+ play_mode->open_output();
+ return 1;
+ }
+ }
+#endif
+#ifdef AU_W32
+ if (play_mode->id_character == 'd'){
+ int ret;
+ ret = sscanf(arg+1,"%d",&opt_wmme_device_id);
+ if( (ret != 0) && (ret != EOF) ){
+ while( *(arg+1) >= '0' && *(arg + 1) <= '9') { arg++; }
+ }else{
+ opt_wmme_device_id=-2;
+ play_mode->open_output();
+ return 1;
+ }
+ }
+#endif
+ break;
+#endif
default:
ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
"Unknown format modifier `%c'", *arg);
return 0;
}
+#if defined(AU_PORTAUDIO) || defined(AU_W32)
+static inline int parse_opt_output_device(const char *arg)
+{
+ if (arg == NULL) return 1;
+#ifdef AU_PORTAUDIO
+ if ( (play_mode->id_character == 'p') || (play_mode->id_character == 'P') || (play_mode->id_character == 'o') ){
+ int ret;
+ ret = sscanf(arg,"%d",&opt_pa_device_id);
+ if( (ret == 0) || (ret == EOF) ) return 1;
+ if( opt_pa_device_id == -1){
+ opt_pa_device_id=-2;
+ play_mode->open_output();
+ return 1;
+ }
+ }
+#endif
+#ifdef AU_W32
+ if (play_mode->id_character == 'd'){
+ int ret;
+ ret = sscanf(arg,"%d",&opt_wmme_device_id);
+ if( (ret == 0) || (ret == EOF) ) return 1;
+ if( opt_wmme_device_id == -1){
+ opt_wmme_device_id=-2;
+ play_mode->open_output();
+ return 1;
+ }
+ }
+#endif
+ return 0;
+}
+#endif
#ifdef AU_FLAC
extern void flac_set_option_verify(int);
extern void flac_set_option_padding(int);
extern CRITICAL_SECTION critSect;
+int opt_wmme_device_id = -1;
+
/*****************************************************************************************************************************/
#if defined(__CYGWIN32__) || defined(__MINGW32__)
static int output_data (char * Data, int32 Size);
static int acntl (int request, void * arg);
+static void print_device_list(void);
+
#if defined ( IA_W32GUI ) || defined ( IA_W32G_SYN )
//#if defined ( IA_W32GUI )
volatile int data_block_bits = DEFAULT_AUDIO_BUFFER_BITS;
MMRESULT Result;
UINT DeviceID;
+ if (opt_wmme_device_id == -2){
+ print_device_list();
+ return -1;
+ }
+
if (dpm.extra_param[0] < 8)
{
ctl->cmsg(CMSG_WARNING, VERB_NORMAL, "Too small -B option: %d", dpm.extra_param[0]);
{ CHAR b[256]; wsprintf(b, "Opening device...\n"); OutputDebugString(b); }
- hDevice = 0;
+ hDevice = 0;
+
+ UINT uDeviceID;
+ if (opt_wmme_device_id == -1){
+ uDeviceID = WAVE_MAPPER;
+ }else{
+ uDeviceID= (UINT)opt_wmme_device_id;
+ }
if (AllowSynchronousWaveforms)
- Result = waveOutOpen(&hDevice, WAVE_MAPPER, (LPWAVEFORMATEX) &wf, (DWORD) OnPlaybackEvent, 0, CALLBACK_FUNCTION | WAVE_ALLOWSYNC);
+ Result = waveOutOpen(&hDevice, uDeviceID, (LPWAVEFORMATEX) &wf, (DWORD) OnPlaybackEvent, 0, CALLBACK_FUNCTION | WAVE_ALLOWSYNC);
else
- Result = waveOutOpen(&hDevice, WAVE_MAPPER, (LPWAVEFORMATEX) &wf, (DWORD) OnPlaybackEvent, 0, CALLBACK_FUNCTION);
+ Result = waveOutOpen(&hDevice, uDeviceID, (LPWAVEFORMATEX) &wf, (DWORD) OnPlaybackEvent, 0, CALLBACK_FUNCTION);
if (Result)
{
{ CHAR b[256]; wsprintf(b, "%2d: Wait finished.\n", NumBuffersInUse); OutputDebugString(b); }
}
}
+
+/*****************************************************************************************************************************/
+
+#define DEVLIST_MAX 20
+static void print_device_list(void){
+ UINT num;
+ int i, list_num;
+ WAVEOUTCAPS woc;
+ typedef struct tag_DEVICELIST{
+ int deviceID;
+ char name[256];
+ } DEVICELIST;
+ DEVICELIST device[DEVLIST_MAX];
+ num = waveOutGetNumDevs();
+ list_num=0;
+ for(i = 0 ; i < num && i < DEVLIST_MAX ; i++){
+ if (MMSYSERR_NOERROR == waveOutGetDevCaps((UINT)i, &woc, sizeof(woc)) ){
+ device[list_num].deviceID=i;
+ strcpy(device[list_num].name, woc.szPname);
+ list_num++;
+ }
+ }
+ for(i=0;i<list_num;i++){
+ ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%2d %s", device[i].deviceID, device[i].name);
+ }
+}