Index: libao2/ao_kai.c =================================================================== --- libao2/ao_kai.c (revision 0) +++ libao2/ao_kai.c (revision 0) @@ -0,0 +1,332 @@ +/* + * OS/2 KAI audio output driver + * + * Copyright (c) 2010 by KO Myung-Hun (komh@chollian.net) + * + * This file is part of MPlayer. + * + * MPlayer is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * MPlayer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with MPlayer; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#define INCL_DOS +#define INCL_DOSERRORS +#include + +#include +#include +#include +#include + +#include + +#include "config.h" +#include "libaf/af_format.h" +#include "audio_out.h" +#include "audio_out_internal.h" +#include "mp_msg.h" +#include "libvo/fastmemcpy.h" +#include "subopt-helper.h" +#include "libavutil/fifo.h" + +static const ao_info_t info = { + "KAI audio output", + "kai", + "KO Myung-Hun ", + "" +}; + +LIBAO_EXTERN(kai) + +#define OUTBURST_SAMPLES 512 +#define DEFAULT_SAMPLES (OUTBURST_SAMPLES << 2) + +#define CHUNK_SIZE ao_data.outburst + +static AVFifoBuffer *m_audioBuf; + +static int m_nBufSize = 0; + +static volatile int m_fQuit = FALSE; + +static KAISPEC m_kaiSpec; + +static int write_buffer(unsigned char *data, int len) +{ + int nFree = av_fifo_space(m_audioBuf); + + if (len > nFree) + len = nFree; + + return av_fifo_generic_write(m_audioBuf, data, len, NULL); +} + +static int read_buffer(unsigned char *data, int len) +{ + int nBuffered = av_fifo_size(m_audioBuf); + + if (len > nBuffered) + len = nBuffered; + + av_fifo_generic_read(m_audioBuf, data, len, NULL); + return len; +} + +// end ring buffer stuff + +static ULONG APIENTRY kai_audio_callback(PVOID pCBData, PVOID pBuffer, + ULONG ulSize) +{ + int nReadLen; + + nReadLen = read_buffer(pBuffer, ulSize); + if (nReadLen < ulSize && !m_fQuit) { + memset((uint8_t *)pBuffer + nReadLen, m_kaiSpec.bSilence, ulSize - nReadLen); + nReadLen = ulSize; + } + + return nReadLen; +} + +// to set/get/query special features/parameters +static int control(int cmd, void *arg) +{ + switch (cmd) { + case AOCONTROL_GET_VOLUME: + { + ao_control_vol_t *vol = arg; + + vol->left = vol->right = LOUSHORT(kaiGetVolume(MCI_STATUS_AUDIO_ALL)); + + return CONTROL_OK; + } + + case AOCONTROL_SET_VOLUME: + { + int mid; + ao_control_vol_t *vol = arg; + + mid = (vol->left + vol->right) / 2; + kaiSetVolume(MCI_SET_AUDIO_ALL, mid); + + return CONTROL_OK; + } + } + + return CONTROL_UNKNOWN; +} + +static void print_help(void) +{ + mp_msg(MSGT_AO, MSGL_FATAL, + "\n-ao kai commandline help:\n" + "Example: mplayer -ao kai:noshare\n" + " open audio in exclusive mode\n" + "\nOptions:\n" + " uniaud\n" + " Use UNIAUD audio driver\n" + " dart\n" + " Use DART audio driver\n" + " (no)share\n" + " Open audio in shareable or exclusive mode\n" + " bufsize=\n" + " Set buffer size to in samples(default: 2048)\n"); +} + +// open & set up audio device +// return: 1=success 0=fail +static int init(int rate, int channels, int format, int flags) +{ + int fUseUniaud = 0; + int fUseDart = 0; + int fShare = 1; + ULONG kaiMode; + KAICAPS kc; + int nSamples = DEFAULT_SAMPLES; + int nBytesPerSample; + KAISPEC ksWanted; + + const opt_t subopts[] = { + {"uniaud", OPT_ARG_BOOL, &fUseUniaud, NULL}, + {"dart", OPT_ARG_BOOL, &fUseDart, NULL}, + {"share", OPT_ARG_BOOL, &fShare, NULL}, + {"bufsize", OPT_ARG_INT, &nSamples, (opt_test_f)int_non_neg}, + {NULL} + }; + + PCSZ pcszAudioDriverStr[] = {"DART", "UNIAUD",}; + + if (subopt_parse(ao_subdevice, subopts) != 0) { + print_help(); + return 0; + } + + if (!!fUseUniaud + !!fUseDart > 1) + mp_msg(MSGT_VO, MSGL_WARN,"KAI: Multiple mode specified!!!\n"); + + if (fUseUniaud) + kaiMode = KAIM_UNIAUD; + else if (fUseDart) + kaiMode = KAIM_DART; + else + kaiMode = KAIM_AUTO; + + if (kaiInit(kaiMode)) { + mp_msg(MSGT_VO, MSGL_ERR, "KAI: Init failed!!!\n"); + return 0; + } + + kaiCaps(&kc); + mp_msg(MSGT_AO, MSGL_V, "KAI: selected audio driver = %s\n", + pcszAudioDriverStr[kc.ulMode - 1]); + mp_msg(MSGT_AO, MSGL_V, "KAI: PDD name = %s, maximum channels = %lu\n", + kc.szPDDName, kc.ulMaxChannels); + + if (!nSamples) + nSamples = DEFAULT_SAMPLES; + + mp_msg(MSGT_AO, MSGL_V, "KAI: open in %s mode, buffer size = %d sample(s)\n", + fShare ? "shareable" : "exclusive", nSamples); + + switch (format) { + case AF_FORMAT_S16_LE: + case AF_FORMAT_S8: + break; + + default: + format = AF_FORMAT_S16_LE; + mp_msg(MSGT_AO, MSGL_V, "KAI: format %s not supported defaulting to Signed 16-bit Little-Endian\n", + af_fmt2str_short(format)); + break; + } + + nBytesPerSample = (af_fmt2bits(format) >> 3) * channels; + + ksWanted.usDeviceIndex = 0; + ksWanted.ulType = KAIT_PLAY; + ksWanted.ulBitsPerSample = af_fmt2bits(format); + ksWanted.ulSamplingRate = rate; + ksWanted.ulDataFormat = MCI_WAVE_FORMAT_PCM; + ksWanted.ulChannels = channels; + ksWanted.ulNumBuffers = 2; + ksWanted.ulBufferSize = nBytesPerSample * nSamples; + ksWanted.fShareable = fShare; + ksWanted.pfnCallBack = kai_audio_callback; + ksWanted.pCallBackData = NULL; + + if (kaiOpen(&ksWanted, &m_kaiSpec)) { + mp_msg(MSGT_VO, MSGL_ERR, "KAI: Open failed!!!\n"); + return 0; + } + + mp_msg(MSGT_AO, MSGL_V, "KAI: obtained buffer count = %lu, size = %lu bytes\n", + m_kaiSpec.ulNumBuffers, m_kaiSpec.ulBufferSize); + + m_fQuit = FALSE; + + ao_data.channels = channels; + ao_data.samplerate = rate; + ao_data.format = format; + ao_data.bps = nBytesPerSample * rate; + ao_data.outburst = nBytesPerSample * OUTBURST_SAMPLES; + ao_data.buffersize = m_kaiSpec.ulBufferSize; + + m_nBufSize = (m_kaiSpec.ulBufferSize * m_kaiSpec.ulNumBuffers << 2); + + // multiple of CHUNK_SIZE + m_nBufSize = (m_nBufSize / CHUNK_SIZE) * CHUNK_SIZE; + + // and one more chunk plus round up + m_nBufSize += 2 * CHUNK_SIZE; + + mp_msg(MSGT_AO, MSGL_V, "KAI: internal audio buffer size = %d bytes\n", + m_nBufSize); + + m_audioBuf = av_fifo_alloc(m_nBufSize); + + kaiPlay(); + + // might cause PM DLLs to be loaded which incorrectly enable SIG_FPE, + // which AAC decoding might trigger. + // so, mask off all floating-point exceptions. + _control87(MCW_EM, MCW_EM); + + return 1; +} + +// close audio device +static void uninit(int immed) +{ + m_fQuit = TRUE; + + if (!immed) { + while (kaiStatus() & KAIS_PLAYING) + DosSleep(1); + } + + kaiClose(); + + kaiDone(); + + av_fifo_free(m_audioBuf); +} + +// stop playing and empty buffers (for seeking/pause) +static void reset(void) +{ + kaiPause(); + + // Reset ring-buffer state + av_fifo_reset(m_audioBuf); + + kaiResume(); +} + +// stop playing, keep buffers (for pause) +static void audio_pause(void) +{ + kaiPause(); +} + +// resume playing, after audio_pause() +static void audio_resume(void) +{ + kaiResume(); +} + +// return: how many bytes can be played without blocking +static int get_space(void) +{ + return av_fifo_space(m_audioBuf); +} + +// plays 'len' bytes of 'data' +// it should round it down to outburst*n +// return: number of bytes played +static int play(void *data, int len, int flags) +{ + + if (!(flags & AOPLAY_FINAL_CHUNK)) + len = (len / ao_data.outburst) * ao_data.outburst; + + return write_buffer(data, len); +} + +// return: delay in seconds between first and last sample in buffer +static float get_delay(void) +{ + int nBuffered = av_fifo_size(m_audioBuf); // could be less + + return (float)nBuffered / (float)ao_data.bps; +} Index: libao2/audio_out.c =================================================================== --- libao2/audio_out.c (revision 30272) +++ libao2/audio_out.c (working copy) @@ -47,6 +47,7 @@ extern const ao_functions_t audio_out_sgi; extern const ao_functions_t audio_out_win32; extern const ao_functions_t audio_out_dsound; +extern const ao_functions_t audio_out_kai; extern const ao_functions_t audio_out_dart; extern const ao_functions_t audio_out_dxr2; extern const ao_functions_t audio_out_ivtv; @@ -64,6 +65,9 @@ #ifdef CONFIG_WIN32WAVEOUT &audio_out_win32, #endif +#ifdef CONFIG_KAI + &audio_out_kai, +#endif #ifdef CONFIG_DART &audio_out_dart, #endif Index: Makefile =================================================================== --- Makefile (revision 30272) +++ Makefile (working copy) @@ -590,6 +590,7 @@ SRCS_MPLAYER-$(JACK) += libao2/ao_jack.c SRCS_MPLAYER-$(JOYSTICK) += input/joystick.c SRCS_MPLAYER-$(JPEG) += libvo/vo_jpeg.c +SRCS_MPLAYER-$(KAI) += libao2/ao_kai.c SRCS_MPLAYER-$(KVA) += libvo/vo_kva.c SRCS_MPLAYER-$(LIBAVCODEC) += libvo/vo_png.c SRCS_MPLAYER-$(LIBMENU) += libmenu/menu.c \ Index: configure =================================================================== --- configure (revision 30272) +++ configure (working copy) @@ -424,6 +424,7 @@ --disable-nas disable NAS audio output [autodetect] --disable-sgiaudio disable SGI audio output [autodetect] --disable-sunaudio disable Sun audio output [autodetect] + --disable-kai disable KAI audio output [autodetect] --disable-dart disable DART audio output [autodetect] --disable-win32waveout disable Windows waveout audio output [autodetect] --disable-coreaudio disable CoreAudio audio output [autodetect] @@ -613,6 +614,7 @@ _esd=auto _pulse=auto _jack=auto +_kai=auto _dart=auto _openal=auto _libcdio=auto @@ -1003,6 +1005,8 @@ --disable-jack) _jack=no ;; --enable-openal) _openal=yes ;; --disable-openal) _openal=no ;; + --enable-kai) _kai=yes ;; + --disable-kai) _kai=no ;; --enable-dart) _dart=yes ;; --disable-dart) _dart=no ;; --enable-mad) _mad=yes ;; @@ -5896,6 +5900,26 @@ if os2 ; then +echocheck "KAI (UNIAUD/DART)" +if test "$_kai" = auto; then + cat > $TMPC << EOF +#include +#include +int main( void ) { return 0; } +EOF + _kai=no; + cc_check -lkai && _kai=yes +fi +if test "$_kai" = yes ; then + def_kai='#define CONFIG_KAI 1' + libs_mplayer="$libs_mplayer -lkai" + _aomodules="kai $_aomodules" +else + def_kai='#undef CONFIG_KAI' + _noaomodules="kai $_noaomodules" +fi +echores "$_kai" + echocheck "DART" if test "$_dart" = auto; then cat > $TMPC << EOF @@ -8399,6 +8423,7 @@ JACK = $_jack JOYSTICK = $_joystick JPEG = $_jpeg +KAI = $_kai KVA = $_kva LADSPA = $_ladspa LIBA52 = $_liba52 @@ -8833,6 +8858,7 @@ $def_esd $def_esd_latency $def_jack +$def_kai $def_nas $def_openal $def_openal_h Index: DOCS/man/en/mplayer.1 =================================================================== --- DOCS/man/en/mplayer.1 (revision 30272) +++ DOCS/man/en/mplayer.1 (working copy) @@ -2860,6 +2864,22 @@ .PD 1 . .TP +.B kai (OS/2 only) +OS/2 KAI audio output driver +.PD 0 +.RSs +.IPs uniaud +Force UNIAUD mode +.IPs dart +Force DART mode +.IPs (no)share +Open audio in shareable or exclusive mode. +.IPs bufsize= +Set buffer size to in samples (default: 2048). +.RE +.PD 1 +. +.TP .B dart (OS/2 only) OS/2 DART audio output driver .PD 0