/* sgi: audio output on SGI boxen copyright ?-2013 by the mpg123 project - free software under the terms of the LGPL 2.1 see COPYING and AUTHORS files in distribution or http://mpg123.org initially written (as it seems) by Thomas Woerner */ #include "out123_int.h" #include #include #include "errno.h" #include "debug.h" static int set_rate(out123_handle *ao, ALconfig config) { int dev = alGetDevice(config); ALpv params[1]; /* Make sure the device is OK */ if(dev < 0) { error1("set_rate: %s", alGetErrorString(oserror())); return -1; } if(ao->rate > 0) { params[0].param = AL_RATE; params[0].value.ll = alDoubleToFixed((double)ao->rate); if(alSetParams(dev, params, 1) < 0) { error1("set_rate: %s", alGetErrorString(oserror())); return -1; } } return 0; } static int set_channels(out123_handle *ao, ALconfig config) { int ret; if(ao->channels == 2) ret = alSetChannels(config, AL_STEREO); else ret = alSetChannels(config, AL_MONO); if(ret < 0) { error1("set_channels : %s", alGetErrorString(oserror())); return -1; } return 0; } static int set_format(out123_handle *ao, ALconfig config) { if(ao->format == MPG123_ENC_FLOAT_32) { if(alSetSampFmt(config, AL_SAMPFMT_FLOAT) < 0) { error1("SetSampFmt: %s", alGetErrorString(oserror())); return -1; } } else { if(alSetSampFmt(config, AL_SAMPFMT_TWOSCOMP) < 0) { error1("SetSampFmt: %s", alGetErrorString(oserror())); return -1; } if(alSetWidth(config, AL_SAMPLE_16) < 0) { error1("SetWidth: %s", alGetErrorString(oserror())); return -1; } } return 0; } static int open_sgi(out123_handle *ao) { int current_dev; ALport port = NULL; ALconfig config = alNewConfig(); ao->userptr = NULL; /* Test for correct completion */ if(config == 0) { error1("open_sgi: %s", alGetErrorString(oserror())); return -1; } /* Setup output device to specified device name. If there is no device name specified in ao structure, use the default for output */ if((ao->device) != NULL) { current_dev = alGetResourceByName(AL_SYSTEM, ao->device, AL_OUTPUT_DEVICE_TYPE); debug2("Dev: %s %i", ao->device, current_dev); if(!current_dev) { int i, numOut; char devname[32]; ALpv pv[1]; ALvalue *alvalues; error2("Invalid audio resource: %s (%s)", ao->device, alGetErrorString(oserror())); if((numOut= alQueryValues(AL_SYSTEM,AL_DEFAULT_OUTPUT,0,0,0,0))>=0) fprintf(stderr, "There are %d output devices on this system.\n", numOut); else { fprintf(stderr, "Can't find output devices. alQueryValues failed: %s\n", alGetErrorString(oserror())); goto open_sgi_bad; } alvalues = malloc(sizeof(ALvalue) * numOut); i = alQueryValues(AL_SYSTEM, AL_DEFAULT_OUTPUT, alvalues, numOut, pv, 0); if(i == -1) error1("alQueryValues: %s", alGetErrorString(oserror())); else { for(i=0; i < numOut; i++) { pv[0].param = AL_NAME; pv[0].value.ptr = devname; pv[0].sizeIn = 32; alGetParams(alvalues[i].i, pv, 1); fprintf(stderr, "%i: %s\n", i, devname); } } free(alvalues); goto open_sgi_bad; } if(alSetDevice(config, current_dev) < 0) { error1("open: alSetDevice : %s",alGetErrorString(oserror())); goto open_sgi_bad; } } else current_dev = AL_DEFAULT_OUTPUT; /* Set the device */ if(alSetDevice(config, current_dev) < 0) { error1("open_sgi: %s", alGetErrorString(oserror())); goto open_sgi_bad; } /* Set port parameters */ if(alSetQueueSize(config, 131069) < 0) { error1("open_sgi: setting audio buffer failed: %s", alGetErrorString(oserror())); goto open_sgi_bad; } if( set_format(ao, config) < 0 || set_rate(ao, config) < 0 || set_channels(ao, config) < 0 ) goto open_sgi_bad; /* Open the audio port */ port = alOpenPort("mpg123-VSC", "w", config); if(port == NULL) { error1("Unable to open audio channel: %s", alGetErrorString(oserror())); goto open_sgi_bad; } ao->userptr = (void*)port; alFreeConfig(config); return 1; open_sgi_bad: /* clean up and return error */ alFreeConfig(config); return -1; } static int get_formats_sgi(out123_handle *ao) { return MPG123_ENC_SIGNED_16|MPG123_ENC_FLOAT_32; } static int write_sgi(out123_handle *ao, unsigned char *buf, int len) { int length = len; if(!ao || !ao->userptr) return -1; ALport port = (ALport)ao->userptr; if(ao->channels == 2) length >>= 2; else length >>= 1; if(ao->format == MPG123_ENC_FLOAT_32) length >>=1; /* Not much error checking ... */ alWriteFrames(port, buf, length); return len; } static int close_sgi(out123_handle *ao) { if(!ao || !ao->userptr) return -1; ALport port = (ALport)ao->userptr; if(port) { /* play all remaining samples */ while(alGetFilled(port) > 0) sginap(1); alClosePort(port); ao->userptr=NULL; } return 0; } static void flush_sgi(out123_handle *ao) { ALport port = (ALport)ao->userptr; if(port) alDiscardFrames(port, alGetFilled(port)); } static int init_sgi(out123_handle* ao) { if(ao == NULL) return -1; /* Set callbacks */ ao->open = open_sgi; ao->flush = flush_sgi; ao->write = write_sgi; ao->get_formats = get_formats_sgi; ao->close = close_sgi; /* Success */ return 0; } /* Module information data structure */ mpg123_module_t mpg123_output_module_info = { /* api_version */ MPG123_MODULE_API_VERSION, /* name */ "sgi", /* description */ "Audio output for SGI.", /* revision */ "$Rev:$", /* handle */ NULL, /* init_output */ init_sgi, };