Index: libao2/ao_dart.c =================================================================== --- libao2/ao_dart.c (revision 0) +++ libao2/ao_dart.c (revision 0) @@ -0,0 +1,267 @@ +/* + * ao_dart.c - libao2 DART Audio Output Driver for MPlayer + * + * Copyright (c) 2007 by KO Myung-Hun (komh@chollian.net) + * + * This program 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. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Changes : + * KO Myung-Hun 2007/07/08 + * - Call fast_memcpy instead of memcpy() + */ + +#define INCL_DOS +#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 "dart.h" + +static ao_info_t info = +{ + "DART audio output", + "dart", + "KO Myung-Hun ", + "" +}; + +LIBAO_EXTERN( dart ) + +#define OUTBURST_SAMPLES 512 +#define DART_SAMPLES ( OUTBURST_SAMPLES << 2 ) +#define MPLAYER_SAMPLES ( OUTBURST_SAMPLES << 4 ) + +static uint8_t *m_audioBuf = NULL; +static volatile int m_nBufSize = 0; +static volatile int m_nBufLen = 0; +static volatile int m_iBufPos = 0; + +static ULONG APIENTRY dart_audio_callback( PVOID pBuffer, ULONG ulSize ) +{ + int nCopySize; + + nCopySize = ulSize < m_nBufLen ? ulSize : m_nBufLen; + + if( m_iBufPos + nCopySize > m_nBufSize ) + { + int len = m_nBufSize - m_iBufPos; + + fast_memcpy( pBuffer, m_audioBuf + m_iBufPos, len ); + fast_memcpy(( uint8_t * )pBuffer + len, m_audioBuf, nCopySize - len ); + } + else + fast_memcpy( pBuffer, m_audioBuf + m_iBufPos, nCopySize ); + + m_iBufPos = ( m_iBufPos + nCopySize ) % m_nBufSize; + m_nBufLen -= nCopySize; + + memset(( uint8_t * )pBuffer + nCopySize, DART.bSilence, ulSize - nCopySize ); + + return ulSize; +} + +// 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 = ( ao_control_vol_t * )arg; + + vol->left = vol->right = LOUSHORT( dartGetVolume()); + + return CONTROL_OK; + } + + case AOCONTROL_SET_VOLUME: + { + int mid; + ao_control_vol_t *vol = ( ao_control_vol_t * )arg; + + mid = ( vol->left + vol->right ) / 2; + dartSetVolume( MCI_SET_AUDIO_ALL, mid ); + + return CONTROL_OK; + } + } + + return CONTROL_UNKNOWN; +} + +static void print_help( void ) +{ + mp_msg( MSGT_AO, MSGL_FATAL, + "\n-ao dart commandline help:\n" + "Example: mplayer -ao kva:noshare\n" + " open DART as exclusive mode\n" + "\nOptions:\n" + " noshare\n" + " Open DART as exclusive mode\n"); +} + +// open & setup audio device +// return: 1=success 0=fail +static int init( int rate, int channels, int format, int flags ) +{ + BOOL fNoShare = FALSE; + int n; + + opt_t subopts[] = { + {"noshare", OPT_ARG_BOOL, &fNoShare, NULL }, + { NULL } + }; + + if( subopt_parse( ao_subdevice, subopts ) != 0 ) + { + print_help(); + return 0; + } + + mp_msg( MSGT_AO, MSGL_V, "DART : opened as %s mode\n", fNoShare ? "exclusive" : "shareable"); + + switch( format ) + { + case AF_FORMAT_S16_LE: + case AF_FORMAT_S8: + break; + + default : + format = AF_FORMAT_S16_LE; + mp_msg( MSGT_AO, MSGL_V, "DART: format %s not supported defaulting to Signed 16-bit Little-Endian\n", af_fmt2str_short( format )); + break; + } + + n = ( af_fmt2bits( format ) >> 3 ) * channels; + + m_nBufSize = n * MPLAYER_SAMPLES; + + if( dartInit( 0, af_fmt2bits( format ), rate, MCI_WAVE_FORMAT_PCM, channels, + 2, n * DART_SAMPLES, !fNoShare, dart_audio_callback )) + return 0; + + ao_data.channels = channels; + ao_data.samplerate = rate; + ao_data.format = format; + ao_data.bps = channels * rate * ( af_fmt2bits( format ) >> 3 ); + ao_data.outburst = n * OUTBURST_SAMPLES; + ao_data.buffersize = m_nBufSize; + + m_audioBuf = malloc( m_nBufSize ); + + m_nBufLen = 0; + m_iBufPos = 0; + + dartPlay(); + + return 1; +} + +// close audio device +static void uninit( int immed ) +{ + if( !immed ) + { + while( m_nBufLen ) + DosSleep( 1 ); + } + + dartClose(); + + free( m_audioBuf ); +} + +// stop playing and empty buffers (for seeking/pause) +static void reset( void ) +{ + dartPause(); + + // empty buffers + m_nBufLen = 0; + + dartResume(); +} + +// stop playing, keep buffers (for pause) +static void audio_pause( void ) +{ + dartPause(); +} + +// resume playing, after audio_pause() +static void audio_resume( void ) +{ + dartResume(); +} + +// return: how many bytes can be played without blocking +static int get_space( void ) +{ + return ( m_nBufSize - m_nBufLen ); +} + +// 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) +{ + int start_pos, end_pos; + + if( !( flags & AOPLAY_FINAL_CHUNK )) + len = ( len / ao_data.outburst ) * ao_data.outburst; + + if( len == 0 ) + return 0; + + start_pos = ( m_iBufPos + m_nBufLen ) % m_nBufSize; + + end_pos = ( start_pos + len ) % m_nBufSize; + if( end_pos <= start_pos ) + { + int len1 = m_nBufSize - start_pos; + + if( end_pos > m_iBufPos ) + end_pos = m_iBufPos; + + fast_memcpy( m_audioBuf + start_pos, data, len1 ); + fast_memcpy( m_audioBuf, ( uint8_t * )data + len1, end_pos ); + + len = len1 + end_pos; + } + else + fast_memcpy( m_audioBuf + start_pos, data, len ); + + m_nBufLen += len; + + return len; +} + +// return: delay in seconds between first and last sample in buffer +static float get_delay( void ) +{ + return ( float )m_nBufLen / ( float )ao_data.bps; +} + + Index: libvo/vo_kva.c =================================================================== --- libvo/vo_kva.c (revision 0) +++ libvo/vo_kva.c (revision 0) @@ -0,0 +1,889 @@ +/* + * vo_kva.c + * + * Copyright (c) 2007 by KO Myung-Hun (komh@chollian.net) + * + * This program 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. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Changes : + * KO Myung-Hun 2007/06/11 + * - Added workaround for T23 laptop with S3 Video + * + * KO Myung-Hun 2007/06/17 + * - Implemented VOCTRL_SET_EQUALIZER and VOCTRL_GET_EQUALIZER + * - Added YV12 as a supported image format + * - Added process VK_ENTER and VK_NEWLINE + * + * KO Myung-Hun 2007/07/08 + * - Call fast_memcpy() instead of memcpy() + * + */ + +#define INCL_WIN +#include + +#include + +#include +#include +#include +#include + +#include "config.h" +#include "mp_msg.h" +#include "help_mp.h" +#include "video_out.h" +#include "video_out_internal.h" + +#include "fastmemcpy.h" +#include "osdep/keycodes.h" +#include "input/input.h" +#include "input/mouse.h" +#include "subopt-helper.h" +#include "sub.h" + +#include "cpudetect.h" +#include "libswscale/swscale.h" +#include "libmpcodecs/vf_scale.h" + +#include "kva.h" + +static vo_info_t info = +{ + "DIVE/WarpOverlay! video output", + "kva", + "KO Myung-Hun ", + "" +}; + +LIBVO_EXTERN( kva ) + +#define WC_MPLAYER "WC_MPLAYER" +#define COLOR_OVERLAY 0x000008 + +#define SRC_WIDTH m_int.kvas.szlSrcSize.cx +#define SRC_HEIGHT m_int.kvas.szlSrcSize.cy + +#define SCREEN_WIDTH m_int.kvac.cxScreen +#define SCREEN_HEIGHT m_int.kvac.cyScreen + +typedef struct tagVOKVAINTERNAL +{ + HAB hab; + HMQ hmq; + HWND hwndFrame; + HWND hwndClient; + HWND hwndSysMenu; + HWND hwndTitleBar; + HWND hwndMinMax; + BOOL fFullScreen; + FOURCC fcc; + INT iImageFormat; + KVASETUP kvas; + KVACAPS kvac; + RECTL rclDst; + INT bpp; + LONG lStride; + PBYTE pbImage; + BOOL fFixT23; + PFNWP pfnwpOldFrame; + uint8_t *yv12Planes[ 3 ]; // use as YUV420P format unlike name + int yv12Stride[ 3 ]; + struct SwsContext *sws; +} VOKVAINTERNAL, *PVOKVAINTERNAL; + +static VOKVAINTERNAL m_int; + +extern void mplayer_put_key( int code ); // let mplayer handel the keyevents + +static PBYTE imgCreate( VOID ) +{ + int size; + + size = SRC_HEIGHT * m_int.lStride; + + if( m_int.iImageFormat == IMGFMT_YV12 ) + size += size / 2; + + return malloc( size ); +} + +static VOID imgFree( PBYTE pbImage ) +{ + if( pbImage ) + free( pbImage ); +} + +static VOID imgDisplay( PBYTE pbImage ) +{ + PVOID pBuffer; + ULONG ulBPL; + + if( !kvaLockBuffer( &pBuffer, &ulBPL )) + { + if( m_int.iImageFormat == IMGFMT_YV12 ) + { + sws_scale( m_int.sws, m_int.yv12Planes, m_int.yv12Stride, 0, SRC_HEIGHT, + &pBuffer, &ulBPL ); + + if( gCpuCaps.hasMMX ) + asm volatile ("emms\n\t"); + } + else + fast_memcpy( pBuffer, pbImage, SRC_HEIGHT * ulBPL ); + + kvaUnlockBuffer(); + } +} + +#define MRETURN( ret ) return ( MRESULT )( ret ) + +static MRESULT EXPENTRY NewFrameWndProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 ) +{ + switch( msg ) + { + case WM_QUERYTRACKINFO : + { + //USHORT ustflags = SHORT1FROMMP( mp1 ); + PTRACKINFO pti = ( PTRACKINFO )mp2; + RECTL rcl; + + if( m_int.fFullScreen ) + break; + + m_int.pfnwpOldFrame( hwnd, msg, mp1, mp2 ); + + //if( ustflags & ( TF_LEFT | TF_RIGHT | TF_TOP | TF_BOTTOM | TF_SETPOINTERPOS )) + { + #if 0 + pti->rclBoundary.xLeft = 0; + pti->rclBoundary.yBottom = 0; + pti->rclBoundary.xRight = SCREEN_WIDTH; + pti->rclBoundary.yTop = SCREEN_HEIGHT; + #endif + + rcl.xLeft = 0; + rcl.yBottom = 0; + rcl.xRight = SRC_WIDTH + 1 ; + rcl.yTop = SRC_HEIGHT + 1; + + WinCalcFrameRect( hwnd, &rcl, FALSE ); + + pti->ptlMinTrackSize.x = rcl.xRight - rcl.xLeft; + pti->ptlMinTrackSize.y = rcl.yTop - rcl.yBottom; + + pti->ptlMaxTrackSize.x = SCREEN_WIDTH; + pti->ptlMaxTrackSize.y = SCREEN_HEIGHT; + } + + MRETURN( TRUE ); + } + + case WM_ADJUSTWINDOWPOS : + { + PSWP pswp = ( PSWP )mp1; + RECTL rcl; + + if( m_int.fFullScreen ) + break; + + if( pswp->fl & SWP_SIZE ) + { + rcl.xLeft = pswp->x; + rcl.yBottom = pswp->y; + rcl.xRight = rcl.xLeft + pswp->cx; + rcl.yTop = rcl.yBottom + pswp->cy; + + WinCalcFrameRect( hwnd, &rcl, TRUE ); + + if( rcl.xRight - rcl.xLeft <= SRC_WIDTH ) + rcl.xRight = rcl.xLeft + ( SRC_WIDTH + 1 ); + + if( rcl.yTop - rcl.yBottom <= SRC_HEIGHT ) + rcl.yTop = rcl.yBottom + ( SRC_HEIGHT + 1 ); + + WinCalcFrameRect( hwnd, &rcl, FALSE ); + + if( rcl.xRight - rcl.xLeft > SCREEN_WIDTH ) + { + rcl.xLeft = 0; + rcl.xRight = SCREEN_WIDTH; + } + + if( rcl.yTop - rcl.yBottom > SCREEN_HEIGHT ) + { + rcl.yBottom = 0; + rcl.yTop = SCREEN_HEIGHT; + } + + pswp->fl |= SWP_MOVE; + pswp->x = rcl.xLeft; + pswp->y = rcl.yBottom; + + pswp->cx = rcl.xRight - rcl.xLeft; + pswp->cy = rcl.yTop - rcl.yBottom; + } + + break; + } + } + + MRETURN( m_int.pfnwpOldFrame( hwnd, msg, mp1, mp2 )); +} + +static MRESULT EXPENTRY WndProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 ) +{ + switch( msg ) + { + case WM_CLOSE : + mplayer_put_key( KEY_CLOSE_WIN ); + + MRETURN( 0 ); + + case WM_CHAR : + { + USHORT fsFlags = SHORT1FROMMP( mp1 ); + USHORT usCh = SHORT1FROMMP( mp2 ); + USHORT usVk = SHORT2FROMMP( mp2 ); + + if( fsFlags & KC_KEYUP ) + break; + + if( fsFlags & KC_VIRTUALKEY ) + { + switch( usVk ) + { + case VK_LEFT : + mplayer_put_key( KEY_LEFT ); + break; + + case VK_UP : + mplayer_put_key( KEY_UP ); + break; + + case VK_RIGHT : + mplayer_put_key( KEY_RIGHT ); + break; + + case VK_DOWN : + mplayer_put_key( KEY_DOWN ); + break; + + case VK_TAB : + mplayer_put_key( KEY_TAB ); + break; + + case VK_BACKSPACE : + mplayer_put_key( KEY_BS ); + break; + + case VK_DELETE : + mplayer_put_key( KEY_DELETE ); + break; + + case VK_INSERT : + mplayer_put_key( KEY_INSERT ); + break; + + case VK_HOME : + mplayer_put_key( KEY_HOME ); + break; + + case VK_END : + mplayer_put_key( KEY_END ); + break; + + case VK_PAGEUP : + mplayer_put_key( KEY_PAGE_UP ); + break; + + case VK_PAGEDOWN : + mplayer_put_key( KEY_PAGE_DOWN ); + break; + + case VK_ESC : + mplayer_put_key( KEY_ESC ); + break; + + case VK_SPACE : + mplayer_put_key(' '); + break; + + //case VK_ENTER : + case VK_NEWLINE : + mplayer_put_key( KEY_ENTER ); + break; + } + } + else if(( fsFlags & KC_CHAR ) && !HIBYTE( usCh )) + mplayer_put_key( usCh ); + + MRETURN( TRUE ); + } + + case WM_BUTTON1DOWN : + if( WinQueryFocus( HWND_DESKTOP ) != hwnd ) + { + WinSetFocus( HWND_DESKTOP, hwnd ); + MRETURN( TRUE ); + } + + if( !vo_nomouse_input ) + mplayer_put_key( MOUSE_BTN0 ); + + MRETURN( TRUE ); + + case WM_BUTTON3DOWN : + if( WinQueryFocus( HWND_DESKTOP ) != hwnd ) + { + WinSetFocus( HWND_DESKTOP, hwnd ); + MRETURN( TRUE ); + } + + if( !vo_nomouse_input ) + mplayer_put_key( MOUSE_BTN1 ); + + MRETURN( TRUE ); + + case WM_BUTTON2DOWN : + if( WinQueryFocus( HWND_DESKTOP ) != hwnd ) + { + WinSetFocus( HWND_DESKTOP, hwnd ); + MRETURN( TRUE ); + } + + if( !vo_nomouse_input ) + mplayer_put_key( MOUSE_BTN2 ); + + MRETURN( TRUE ); + + case WM_BUTTON1DBLCLK : + if( !vo_nomouse_input ) + mplayer_put_key( MOUSE_BTN0_DBL ); + + MRETURN( TRUE ); + + case WM_BUTTON3DBLCLK : + if( !vo_nomouse_input ) + mplayer_put_key( MOUSE_BTN1_DBL ); + + MRETURN( TRUE ); + + case WM_BUTTON2DBLCLK : + if( !vo_nomouse_input) + mplayer_put_key( MOUSE_BTN2_DBL ); + + MRETURN( TRUE ); + } + + MRETURN( WinDefWindowProc( hwnd, msg, mp1, mp2 )); +} + +static int preinit( const char *arg ) +{ + ULONG flFrameFlags; + + BOOL fUseDive = FALSE; + BOOL fFixT23 = FALSE; + + opt_t subopts[] = { + {"dive", OPT_ARG_BOOL, &fUseDive, NULL, 0 }, + {"t23", OPT_ARG_BOOL, &fFixT23, NULL, 0 }, + { NULL, 0, NULL, NULL, 0 } + }; + + if( subopt_parse( arg, subopts ) != 0 ) + return -1; + + memset( &m_int, 0, sizeof( VOKVAINTERNAL )); + + m_int.hab = WinInitialize( 0 ); + m_int.hmq = WinCreateMsgQueue( m_int.hab, 0); + + WinRegisterClass( + m_int.hab, + WC_MPLAYER, + WndProc, + CS_SIZEREDRAW | CS_MOVENOTIFY, + sizeof( PVOID ) + ); + + flFrameFlags = FCF_SYSMENU | FCF_TITLEBAR | FCF_MINMAX | FCF_SIZEBORDER | + FCF_TASKLIST; + + m_int.hwndFrame = + WinCreateStdWindow( + HWND_DESKTOP, // parent window handle + WS_VISIBLE, // frame window style + &flFrameFlags, // window style + WC_MPLAYER, // class name + "", // window title + 0L, // default client style + NULLHANDLE, // resource in exe file + 1, // frame window id + &m_int.hwndClient // client window handle + ); + + if( m_int.hwndFrame == NULLHANDLE ) + return -1; + + m_int.hwndSysMenu = WinWindowFromID( m_int.hwndFrame, FID_SYSMENU ); + m_int.hwndTitleBar = WinWindowFromID( m_int.hwndFrame, FID_TITLEBAR ); + m_int.hwndMinMax = WinWindowFromID( m_int.hwndFrame, FID_MINMAX ); + + m_int.fFullScreen = FALSE; + + m_int.fFixT23 = fFixT23; + + if( m_int.fFixT23 ) + m_int.pfnwpOldFrame = WinSubclassWindow( m_int.hwndFrame, NewFrameWndProc ); + + if( kvaInit( fUseDive, m_int.hwndClient, COLOR_OVERLAY )) + return -1; + + kvaCaps( &m_int.kvac ); + + switch( m_int.kvac.ulMode ) + { + case KVAM_WO : + m_int.fcc = FOURCC_Y422; + m_int.iImageFormat = IMGFMT_YUY2; + m_int.bpp = 2; + break; + + case KVAM_DIVE : + default : + switch( m_int.kvac.fccScreen ) + { + case FOURCC_BGR4 : + case FOURCC_BGR3 : + case FOURCC_LUT8 : // maybe best T.T + m_int.fcc = FOURCC_BGR3; + m_int.iImageFormat = IMGFMT_BGR24; + m_int.bpp = 3; + break; + + case FOURCC_R565 : + m_int.fcc = FOURCC_R565; + m_int.iImageFormat = IMGFMT_BGR16; + m_int.bpp = 2; + break; + + case FOURCC_R555 : + m_int.fcc = FOURCC_R555; + m_int.iImageFormat = IMGFMT_BGR15; + m_int.bpp = 2; + break; + } + break; + } + + return 0; +} + +static void uninit( void ) +{ + if( m_int.pbImage ) + imgFree( m_int.pbImage ); + + if( m_int.sws ) + sws_freeContext( m_int.sws ); + + if( m_int.hwndFrame != NULLHANDLE ) + { + if( m_int.fFixT23 ) + WinSubclassWindow( m_int.hwndFrame, m_int.pfnwpOldFrame ); + + kvaResetAttr(); + kvaDone(); + WinDestroyWindow( m_int.hwndFrame ); + } + + WinDestroyMsgQueue( m_int.hmq ); + WinTerminate( m_int.hab ); +} + +static int config( uint32_t width, uint32_t height, uint32_t d_width, uint32_t d_height, uint32_t flags, char *title, uint32_t format ) +{ + RECTL rcl; + + if( format != m_int.iImageFormat ) + { + mp_msg( MSGT_VO, MSGL_ERR, "KVA : Unsupported image format 0x%X(%s)\n", format, vo_format_name(format)); + return -1; + } + + if( mp_msg_test( MSGT_VO, MSGL_V )) + mp_msg( MSGT_VO, MSGL_V, "KVA: Using 0x%X (%s) image format\n", format, vo_format_name(format)); + + if( m_int.pbImage ) + imgFree( m_int.pbImage ); + + m_int.kvas.ulLength = sizeof( KVASETUP ); + m_int.kvas.szlSrcSize.cx = width; + m_int.kvas.szlSrcSize.cy = height; + m_int.kvas.rclSrcRect.xLeft = 0; + m_int.kvas.rclSrcRect.yTop = 0; + m_int.kvas.rclSrcRect.xRight = width; + m_int.kvas.rclSrcRect.yBottom = height; + m_int.kvas.ulRatio = KVAR_ORIGINAL; + m_int.kvas.fccSrcColor = m_int.fcc; + + kvaSetup( &m_int.kvas ); + + m_int.lStride = width * m_int.bpp; + + m_int.pbImage = imgCreate(); + + if( m_int.iImageFormat == IMGFMT_YV12 ) + { + int dstFormat; + + if( m_int.sws ) + sws_freeContext( m_int.sws ); + + m_int.yv12Planes[ 0 ] = m_int.pbImage; + m_int.yv12Planes[ 1 ] = m_int.yv12Planes[ 0 ] + ( m_int.lStride * height ); + m_int.yv12Planes[ 2 ] = m_int.yv12Planes[ 1 ] + ( m_int.lStride * height ) / 4; + + m_int.yv12Stride[ 0 ] = m_int.lStride; + m_int.yv12Stride[ 1 ] = m_int.lStride / 2; + m_int.yv12Stride[ 2 ] = m_int.lStride / 2; + + switch( m_int.fcc ) + { + case FOURCC_Y422 : + dstFormat = PIX_FMT_YUYV422; + break; + + case FOURCC_BGR3 : + dstFormat = PIX_FMT_BGR24; + break; + + case FOURCC_R565 : + dstFormat = PIX_FMT_BGR565; + break; + + case FOURCC_R555 : + dstFormat = PIX_FMT_BGR555; + break; + } + + m_int.sws = sws_getContext( width, height, PIX_FMT_YUV420P, + width, height, dstFormat, + SWS_FAST_BILINEAR | SWS_PRINT_INFO | get_sws_cpuflags(), + NULL, NULL, NULL ); + } + + WinSetWindowText( m_int.hwndFrame, title ); + + if( !d_width ) + d_width = width; + + if( !d_height ) + d_height = height; + + m_int.fFullScreen = flags & VOFLAG_FULLSCREEN; + + // workaround for T23 laptop with S3 Video by Franz Bakan + if( !m_int.fFullScreen && m_int.fFixT23 ) + { + d_width++; + d_height++; + } + + m_int.rclDst.xLeft = (( LONG )SCREEN_WIDTH - ( LONG )d_width ) / 2; + m_int.rclDst.yBottom = (( LONG )SCREEN_HEIGHT - ( LONG )d_height ) /2 ; + m_int.rclDst.xRight = m_int.rclDst.xLeft + d_width; + m_int.rclDst.yTop = m_int.rclDst.yBottom + d_height; + + if( m_int.fFullScreen ) + { + d_width = SCREEN_WIDTH; + d_height = SCREEN_HEIGHT; + + // when -fs option is used without this, title bar is not highlighted + WinSetActiveWindow( HWND_DESKTOP, m_int.hwndFrame ); + + WinSetParent( m_int.hwndSysMenu, HWND_OBJECT, FALSE ); + WinSetParent( m_int.hwndTitleBar, HWND_OBJECT, FALSE ); + WinSetParent( m_int.hwndMinMax, HWND_OBJECT, FALSE ); + } + + rcl.xLeft = (( LONG )SCREEN_WIDTH - ( LONG )d_width ) / 2; + rcl.yBottom = (( LONG )SCREEN_HEIGHT - ( LONG )d_height ) /2 ; + rcl.xRight = rcl.xLeft + d_width; + rcl.yTop = rcl.yBottom + d_height; + + WinCalcFrameRect( m_int.hwndFrame, &rcl, FALSE ); + + WinSetWindowPos( m_int.hwndFrame, HWND_TOP, + rcl.xLeft, rcl.yBottom, + rcl.xRight - rcl.xLeft, rcl.yTop - rcl.yBottom, + SWP_SIZE | SWP_MOVE | SWP_ZORDER | SWP_SHOW | SWP_ACTIVATE ); + + return 0; +} + +static uint32_t get_image( mp_image_t *mpi ) +{ + if( mpi->imgfmt != m_int.iImageFormat ) + return VO_FALSE; + + if( m_int.iImageFormat == IMGFMT_YV12 ) + { + mpi->planes[ 1 ] = m_int.yv12Planes[ 1 ]; + mpi->planes[ 2 ] = m_int.yv12Planes[ 2 ]; + + mpi->stride[ 1 ] = m_int.yv12Stride[ 1 ]; + mpi->stride[ 2 ] = m_int.yv12Stride[ 2 ]; + } + + mpi->planes[0] = m_int.pbImage; + mpi->stride[0] = m_int.lStride; + mpi->flags |= MP_IMGFLAG_DIRECT; + + return VO_TRUE; +} + +static int query_format( uint32_t format ) +{ + int res = 0; + + // here, modify image format and bpp in case of YV12 + if( format == IMGFMT_YV12 ) + { + m_int.iImageFormat = IMGFMT_YV12; + m_int.bpp = 1; + } + + if( format == m_int.iImageFormat ) + { + res = VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW | VFCAP_OSD | + VFCAP_HWSCALE_UP; + + if( !m_int.fFixT23 ) + res |= VFCAP_HWSCALE_DOWN; + } + + return res; +} + +static uint32_t color_ctrl_set( char *what, int value ) +{ + ULONG ulAttr; + ULONG ulValue; + + if( !strcmp( what, "brightness")) + ulAttr = KVAA_BRIGHTNESS; + else if( !strcmp( what, "contrast")) + ulAttr = KVAA_CONTRAST; + else if( !strcmp( what, "hue")) + ulAttr = KVAA_HUE; + else if( !strcmp( what, "saturation")) + ulAttr = KVAA_SATURATION; + else + return VO_NOTIMPL; + + ulValue = ( value + 100 ) * 255 / 200; + + if( kvaSetAttr( ulAttr, &ulValue )) + return VO_NOTIMPL; + + return VO_TRUE; +} + +static uint32_t color_ctrl_get( char *what, int *value ) +{ + ULONG ulAttr; + ULONG ulValue; + + if( !strcmp( what, "brightness")) + ulAttr = KVAA_BRIGHTNESS; + else if( !strcmp( what, "contrast")) + ulAttr = KVAA_CONTRAST; + else if( !strcmp( what, "hue")) + ulAttr = KVAA_HUE; + else if( !strcmp( what, "saturation")) + ulAttr = KVAA_SATURATION; + else + return VO_NOTIMPL; + + if( kvaQueryAttr( ulAttr, &ulValue )) + return VO_NOTIMPL; + + // add 1 to adjust range + *value = (( ulValue + 1 ) * 200 / 255 ) - 100; + + return VO_TRUE; +} + +static int control( uint32_t request, void *data, ... ) +{ + switch( request ) + { + case VOCTRL_GET_IMAGE : + return get_image( data ); + + case VOCTRL_QUERY_FORMAT : + return query_format( *(( uint32_t * )data )); + + case VOCTRL_FULLSCREEN : + { + RECTL rcl; + + m_int.fFullScreen = !m_int.fFullScreen; + + if( m_int.fFullScreen ) + { + WinSetParent( m_int.hwndSysMenu, HWND_OBJECT, FALSE ); + WinSetParent( m_int.hwndTitleBar, HWND_OBJECT, FALSE ); + WinSetParent( m_int.hwndMinMax, HWND_OBJECT, FALSE ); + + rcl.xLeft = 0; + rcl.yBottom = 0; + rcl.xRight = SCREEN_WIDTH; + rcl.yTop = SCREEN_HEIGHT; + } + else + { + WinSetParent( m_int.hwndSysMenu, m_int.hwndFrame, FALSE ); + WinSetParent( m_int.hwndTitleBar, m_int.hwndFrame, FALSE ); + WinSetParent( m_int.hwndMinMax, m_int.hwndFrame, FALSE ); + + rcl = m_int.rclDst; + } + + WinCalcFrameRect( m_int.hwndFrame, &rcl, FALSE ); + + WinSetWindowPos( m_int.hwndFrame, HWND_TOP, + rcl.xLeft, rcl.yBottom, + rcl.xRight - rcl.xLeft, rcl.yTop - rcl.yBottom, + SWP_SIZE | SWP_MOVE | SWP_ZORDER | SWP_SHOW | SWP_ACTIVATE ); + + return VO_TRUE; + } + + case VOCTRL_SET_EQUALIZER : + { + va_list ap; + int value; + + va_start( ap, data ); + value = va_arg( ap, int ); + va_end( ap ); + + return color_ctrl_set( data, value ); + } + + case VOCTRL_GET_EQUALIZER : + { + va_list ap; + int *value; + + va_start( ap, data ); + value = va_arg( ap, int * ); + va_end( ap ); + + return color_ctrl_get( data, value ); + } + } + + return VO_NOTIMPL; +} + +static int draw_frame( uint8_t *src[] ) +{ + fast_memcpy( m_int.pbImage, src[ 0 ], SRC_HEIGHT * m_int.lStride ); + + return 0; +} + +static int draw_slice( uint8_t *src[], int stride[], int w, int h, int x, int y ) +{ + uint8_t *s; + uint8_t *d; + + // copy Y + d = m_int.yv12Planes[ 0 ] + m_int.yv12Stride[ 0 ] * y + x; + s = src[ 0 ]; + mem2agpcpy_pic( d, s, w, h, m_int.yv12Stride[ 0 ], stride[ 0 ]); + + w /= 2; h /= 2; x /= 2; y /= 2; + + // copy U + d = m_int.yv12Planes[ 1 ] + m_int.yv12Stride[ 1 ] * y + x; + s = src[ 1 ]; + mem2agpcpy_pic( d, s, w, h, m_int.yv12Stride[ 1 ], stride[ 1 ]); + + // copy V + d = m_int.yv12Planes[ 2 ] + m_int.yv12Stride[ 2 ] * y + x; + s = src[ 2 ]; + mem2agpcpy_pic( d, s, w, h, m_int.yv12Stride[ 2 ], stride[ 2 ]); + + return 0; +} + +#define vo_draw_alpha( imgfmt ) \ + vo_draw_alpha_##imgfmt( w, h, src, srca, stride, \ + m_int.pbImage + m_int.lStride * y0 + m_int.bpp * x0 , \ + m_int.lStride ) + +static void draw_alpha(int x0, int y0, int w, int h, unsigned char *src, + unsigned char *srca, int stride) +{ + switch( m_int.iImageFormat ) + { + case IMGFMT_YV12 : + vo_draw_alpha( yv12 ); + break; + + case IMGFMT_YUY2 : + vo_draw_alpha( yuy2 ); + break; + + case IMGFMT_BGR24 : + vo_draw_alpha( rgb24 ); + break; + + case IMGFMT_BGR16 : + vo_draw_alpha( rgb16 ); + break; + + case IMGFMT_BGR15 : + vo_draw_alpha( rgb15 ); + break; + } +} + +static void draw_osd( void ) +{ + vo_draw_text( SRC_WIDTH, SRC_HEIGHT, draw_alpha ); +} + +static void flip_page( void ) +{ + imgDisplay( m_int.pbImage ); +} + +static void check_events( void ) +{ + QMSG qm; + + while( WinPeekMsg( m_int.hab, &qm, NULLHANDLE, 0, 0, PM_REMOVE )) + WinDispatchMsg( m_int.hab, &qm ); +} + + Index: osdep/getch2-os2.c =================================================================== --- osdep/getch2-os2.c (revision 0) +++ osdep/getch2-os2.c (revision 0) @@ -0,0 +1,181 @@ +/* + * getch2-os2.c : OS/2 TermIO for MPlayer + * + * Copyright (c) 2007 KO Myung-Hun (komh@chollian.net) + * + * This program 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. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#define INCL_KBD +#define INCL_VIO +#define INCL_DOS +#include + +#include + +#include "config.h" +#include "keycodes.h" +#include "input/input.h" + +#if defined( USE_LANGINFO ) && defined( USE_ICONV ) +#include +#include +#endif + +int mp_input_os2_slave_cmd_func( int fd, char *dest, int size) +{ + PPIB ppib; + CHAR szPipeName[ 100 ]; + HFILE hpipe; + ULONG ulAction; + ULONG cbActual; + ULONG rc; + + DosGetInfoBlocks( NULL, &ppib ); + + sprintf( szPipeName, "\\PIPE\\MPLAYER\\%lx", ppib->pib_ulpid ); + + rc = DosOpen( szPipeName, &hpipe, &ulAction, 0, FILE_NORMAL, + OPEN_ACTION_OPEN_IF_EXISTS, + OPEN_SHARE_DENYREADWRITE | OPEN_ACCESS_READWRITE, + NULL ); + if( rc ) + return MP_INPUT_NOTHING; + + rc = DosRead( hpipe, dest, size, &cbActual ); + if( rc ) + return MP_INPUT_NOTHING; + + rc = cbActual; + + // Send ACK + DosWrite( hpipe, &rc, sizeof( ULONG ), &cbActual ); + + DosClose( hpipe ); + + return rc; +} + + +int screen_width = 80; +int screen_height = 24; +char *erase_to_end_of_line = NULL; + +void get_screen_size( void ) +{ + VIOMODEINFO vmi; + + vmi.cb = sizeof( VIOMODEINFO ); + + VioGetMode( &vmi, 0 ); + + screen_width = vmi.col; + screen_height = vmi.row; +} + +static int getch2_status = 0; + +// FIXME : assume time == 0 +int getch2( int time ) +{ + KBDKEYINFO kki; + + if( !getch2_status ) + return -1; + + if( KbdCharIn( &kki, IO_NOWAIT, 0 )) + return -1; + + if( kki.fbStatus ) // key pressed ? + { + if(( kki.chChar == 0x00 ) || ( kki.chChar == 0xE0 )) // extended key ? + { + switch( kki.chScan ) + { + case 0x4B : // Left + return KEY_LEFT; + + case 0x48 : // Up + return KEY_UP; + + case 0x4D : // Right + return KEY_RIGHT; + + case 0x50 : // Down + return KEY_DOWN; + + case 0x53 : // Delete + return KEY_DELETE; + + case 0x52 : // Insert + return KEY_INSERT; + + case 0x47 : // Home + return KEY_HOME; + + case 0x4F : // End + return KEY_END; + + case 0x49 : // Page Up + return KEY_PAGE_UP; + + case 0x51 : // Page Down + return KEY_PAGE_DOWN; + } + } + else // character key ? + { + switch( kki.chChar ) + { + case 0x08 : // Backspace + return KEY_BS; + + case 0x1B : // Esc + return KEY_ESC; + } + + return kki.chChar; + } + } + + return -1; +} + + +void getch2_enable() +{ + getch2_status = 1; +} + +void getch2_disable() +{ + getch2_status = 0; +} + +#ifdef USE_ICONV +char *get_term_charset( void ) +{ + char *charset = NULL; + +#ifdef USE_LANGINFO + setlocale( LC_CTYPE, ""); + charset = nl_langinfo( CODESET ); + setlocale( LC_CTYPE, "C"); +#endif + + return charset; +} +#endif +