diff options
Diffstat (limited to 'src/output/alib.c')
-rw-r--r-- | src/output/alib.c | 209 |
1 files changed, 209 insertions, 0 deletions
diff --git a/src/output/alib.c b/src/output/alib.c new file mode 100644 index 0000000..635382d --- /dev/null +++ b/src/output/alib.c @@ -0,0 +1,209 @@ +/* + alib: audio output for HP-UX using alib + + copyright ?-2006 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 by Erwan Ducroquet + based on source code from HP (Audio SDK) +*/ + +/* + * + * for mpg123 : + * hpux: + * $(MAKE) \ + * CC=cc \ + * LDFLAGS=-L/opt/audio/lib \ + * AUDIO_LIB=-lAlib \ + * OBJECTS=decode.o dct64.o \ + * CFLAGS=-Ae +O3 -DREAL_IS_FLOAT -D_HPUX_SOURCE -DHPUX -I/opt/audio/include \ + * mpg123 + */ + + +/* + * For the user : + * If you launch mpg123 on a XTerm with sound capabilities, it's OK + * Else, you have to set the environment variable "AUDIO" to the name of + * an HP Xterm with sound card. + */ + +/**************************************************************************/ + +#include "mpg123app.h" + +#include <fcntl.h> + +#include <sys/socket.h> +#include <netdb.h> +#include <netinet/in.h> +#include <netinet/tcp.h> +#include <errno.h> + + +#include <Alib.h> /* /opt/audio/include */ +#include <CUlib.h> /* /opt/audio/include */ + +#include "debug.h" + +/**************************************************************************/ + + +/* FIXME: These globals should be moved into a structure */ +static Audio *audioServer = (Audio *) NULL; +static struct protoent *tcpProtocolEntry; +static ATransID xid; + +static void printAudioError(Audio *audio,char *message,int errorCode) { + char errorbuff[132]; + AGetErrorText(audio, errorCode, errorbuff, 131); + error2("%s: %s", message, errorbuff); +} +static long myHandler(Audio *audio,AErrorEvent *err_event) { + printAudioError( audio, "Audio error", err_event->error_code ); + /* we cannot just do random exists, that messes terminal up + need proper error propagation in that case for future, setting intflag or such */ + /* exit(1); */ +} + +/**************************************************************************/ + +/* + * Set the fn element of ai + * Use ao->rate and ao->channels + * Doesn't set any volume + */ + +/* return on error leaves stuff dirty here... */ +static int open_alib(audio_output_t *ao) +{ + AudioAttributes Attribs; + AudioAttrMask AttribsMask; + AGainEntry gainEntry[4]; + SSPlayParams playParams; + SStream audioStream; + AErrorHandler prevHandler; + char server[1]; + int i; + long status; + + if (audioServer) { + error("openAudio: audio already open"); + return -1; + } + + prevHandler = ASetErrorHandler(myHandler); + + server[0] = '\0'; + audioServer = AOpenAudio( server, NULL ); + if (audioServer==NULL) { + error("Error: could not open audio\n"); + return -1; + } + + ao->fn = socket( AF_INET, SOCK_STREAM, 0 ); + if(ao->fn<0) { + error("Socket creation failed"); + return -1; + } + + Attribs.type = ATSampled; + Attribs.attr.sampled_attr.sampling_rate = ao->rate; + Attribs.attr.sampled_attr.channels = ao->channels; + Attribs.attr.sampled_attr.data_format = ADFLin16; + AttribsMask = ASSamplingRateMask | ASChannelsMask | ASDataFormatMask; + + gainEntry[0].gain = AUnityGain; + gainEntry[0].u.o.out_ch = AOCTMono; + gainEntry[0].u.o.out_dst = AODTDefaultOutput; + + playParams.gain_matrix.type = AGMTOutput; /* gain matrix */ + playParams.gain_matrix.num_entries = 1; + playParams.gain_matrix.gain_entries = gainEntry; + playParams.play_volume = AUnityGain; /* play volume */ + playParams.priority = APriorityNormal; /* normal priority */ + playParams.event_mask = 0; /* don't solicit any events */ + + xid=APlaySStream(audioServer,AttribsMask,&Attribs, + &playParams,&audioStream,NULL); + + status=connect(ao->fn, + (struct sockaddr *) &audioStream.tcp_sockaddr, + sizeof(struct sockaddr_in) ); + if (status<0) { + error("Connect failed"); + return -1; + } + + i=-1; + tcpProtocolEntry=getprotobyname("tcp"); + setsockopt(ao->fn,tcpProtocolEntry->p_proto,TCP_NODELAY,&i,sizeof(i)); + + return ao->fn; +} + +/**************************************************************************/ + +static int close_alib(audio_output_t *ao) +{ + close(ao->fn); + ASetCloseDownMode( audioServer, AKeepTransactions, NULL ); + ACloseAudio( audioServer, NULL ); + audioServer = (Audio *) NULL; + return 0; +} + +/**************************************************************************/ + +/* + * very simple + * deserv to be inline + */ + +static int write_alib(audio_output_t *ao,unsigned char *buf,int len) +{ + return write(ao->fn,buf,len*2); +} + +/**************************************************************************/ + +static int get_formats_alib(audio_output_t *ao) +{ + return MPG123_ENC_SIGNED_16; +} + +static void flush_alib(audio_output_t *ao) +{ +} + + +static int init_alib(audio_output_t* ao) +{ + if (ao==NULL) return -1; + + /* Set callbacks */ + ao->open = open_alib; + ao->flush = flush_alib; + ao->write = write_alib; + ao->get_formats = get_formats_alib; + ao->close = close_alib; + + /* Success */ + return 0; +} + + + +/* + Module information data structure +*/ +mpg123_module_t mpg123_output_module_info = { + /* api_version */ MPG123_MODULE_API_VERSION, + /* name */ "alib", + /* description */ "Output audio HP-UX using alib.", + /* revision */ "$Rev:$", + /* handle */ NULL, + + /* init_output */ init_alib, +}; + |