summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Champagne <tchamp@users.sourceforge.net>2003-04-22 20:09:38 +0000
committerTim Champagne <tchamp@users.sourceforge.net>2003-04-22 20:09:38 +0000
commite1d8559090fc00da048617282fcdde34a8b345ea (patch)
treed99f58c7d71701ad51048ff46a1efff37e65a405
parent8b64ee5ef1ec23458c925a60ffbf0427e0eacf32 (diff)
downloadxine-lib-e1d8559090fc00da048617282fcdde34a8b345ea.tar.gz
xine-lib-e1d8559090fc00da048617282fcdde34a8b345ea.tar.bz2
Adding a couple of files missing files for the Win32/msvc port (audio and video directx)
CVS patchset: 4648 CVS date: 2003/04/22 20:09:38
-rwxr-xr-xsrc/audio_out/audio_directx_out.c949
-rwxr-xr-xsrc/video_out/video_out_directx.c1289
-rwxr-xr-xsrc/video_out/video_out_win32.h67
3 files changed, 2305 insertions, 0 deletions
diff --git a/src/audio_out/audio_directx_out.c b/src/audio_out/audio_directx_out.c
new file mode 100755
index 000000000..2d233278e
--- /dev/null
+++ b/src/audio_out/audio_directx_out.c
@@ -0,0 +1,949 @@
+/*
+ * Copyright (C) 2000-2001 the xine project
+ *
+ * This file is part of xine, a unix video player.
+ *
+ * xine 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.
+ *
+ * xine 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * audio_directx_out.c, direct sound audio output plugin for xine
+ * by Matthew Grooms <elon@altavista.com>
+ */
+
+typedef unsigned char boolean;
+
+#include <windows.h>
+#include <dsound.h>
+#include "audio_out.h"
+#include "xine_internal.h"
+
+
+#if (0)
+#define LOG 1
+#endif
+
+#define MAX_CHANNELS 6
+#define MAX_BITS 16
+#define MAX_SAMPLE_RATE 44100
+#define SOUND_BUFFER_DIV 32
+#define SOUND_BUFFER_MAX MAX_CHANNELS * MAX_BITS * MAX_SAMPLE_RATE / SOUND_BUFFER_DIV
+
+#define DSBUFF_INIT 0
+#define DSBUFF_LEFT 1
+#define DSBUFF_RIGHT 2
+
+#define AO_DIRECTX_IFACE_VERSION 7
+
+// -----------------------------------------
+//
+// ao_directx driver struct
+//
+// -----------------------------------------
+
+typedef struct ao_directx_s
+{
+ ao_driver_t ao_driver;
+
+ int capabilities;
+
+ // directx objects
+
+ LPDIRECTSOUND dsobj;
+ LPDIRECTSOUNDBUFFER dsbuffer;
+ DSBCAPS dsbcaps;
+ LPDIRECTSOUNDNOTIFY notify;
+ DSBPOSITIONNOTIFY notify_events[ 2 ];
+
+ // buffer vars
+
+ long buffer_size;
+ long buffer_init;
+ int write_status;
+ long write_pos;
+
+ uint8_t prebuff[ SOUND_BUFFER_MAX ];
+ uint32_t prebuff_size;
+
+ // current buffer properties
+
+ int bits;
+ int rate;
+ int chnn;
+ int frsz;
+
+ // current mixer settings
+
+ int mute;
+ int volume;
+
+}ao_directx_t;
+
+typedef struct {
+ audio_driver_class_t driver_class;
+
+ config_values_t *config;
+
+ char *device_name;
+} audiox_class_t;
+
+// -------------------------------------------
+//
+// BEGIN : Direct Sound and win32 handlers
+// for xine audio output plugins.
+//
+// -------------------------------------------
+
+boolean CreateDirectSound( ao_directx_t * ao_directx );
+void DestroyDirectSound( ao_directx_t * ao_directx );
+boolean CreateSoundBuffer( ao_directx_t * ao_directx );
+void DestroySoundBuffer( ao_directx_t * ao_directx );
+uint32_t FillSoundBuffer( ao_directx_t * ao_directx, int code, unsigned char * samples );
+
+// Display formatted error message in
+// popup message box.
+
+void Error( HWND hwnd, LPSTR szfmt, ... )
+{
+ char tempbuff[ 256 ];
+ *tempbuff = 0;
+ wvsprintf( &tempbuff[ strlen( tempbuff ) ], szfmt, ( char * )( &szfmt + 1 ) );
+ MessageBox( hwnd, tempbuff, "Error", MB_ICONERROR | MB_OK | MB_APPLMODAL | MB_SYSTEMMODAL );
+}
+
+// Create our direct sound object and
+// set the cooperative level.
+
+boolean CreateDirectSound( ao_directx_t * ao_directx )
+{
+ DSCAPS dscaps;
+ HWND hxinewnd;
+
+#ifdef LOG
+ printf("audio_directx_out: CreateDirectSound(%08x) Enter\n", (unsigned long)ao_directx);
+#endif
+
+ // create direct sound object
+
+ if( DirectSoundCreate( 0, &ao_directx->dsobj, 0 ) != DS_OK )
+ {
+ Error( 0, "DirectSoundCreate : Unable to create direct sound object" );
+#ifdef LOG
+ printf("audio_directx_out: CreateDirectSound() Exit! Returning False\n");
+#endif
+ return FALSE;
+ }
+
+
+ // try to get our current xine window
+
+ hxinewnd = FindWindow( "xinectrlwindow", "xine" );
+ if( !hxinewnd )
+ hxinewnd = GetDesktopWindow();
+
+ // set direct sound cooperative level
+
+ if( IDirectSound_SetCooperativeLevel( ao_directx->dsobj, hxinewnd, DSSCL_EXCLUSIVE ) != DS_OK )
+ {
+ Error( 0, "IDirectSound_SetCooperativeLevel : could not set direct sound cooperative level" );
+#ifdef LOG
+ printf("audio_directx_out: CreateDirectSound() Exit! Returning False\n");
+#endif
+ return FALSE;
+ }
+
+ // get the direct sound device caps
+
+ memset( &dscaps, 0, sizeof( dscaps ) );
+ dscaps.dwSize = sizeof( dscaps );
+ if( IDirectSound_GetCaps( ao_directx->dsobj, &dscaps ) != DS_OK )
+ {
+ Error( 0, "IDirectSound_GetCaps : Unable to get direct sound device capabilities" );
+#ifdef LOG
+ printf("audio_directx_out: CreateDirectSound() Exit! Returning False\n");
+#endif
+ return FALSE;
+ }
+
+#ifdef LOG
+ printf("audio_directx_out: CreateDirectSound() Exit! Returning True\n");
+#endif
+ return TRUE;
+}
+
+// Destroy all direct sound allocated
+// resources.
+
+void DestroyDirectSound( ao_directx_t * ao_directx )
+{
+
+#ifdef LOG
+ printf("audio_directx_out: DestroyDirectSound(%08x) Enter\n", (unsigned long)ao_directx);
+#endif
+
+ if( ao_directx->dsobj )
+ {
+#ifdef LOG
+ printf("audio_directx_out: IDirectSound_Release()\n");
+#endif
+
+ IDirectSound_Release( ao_directx->dsobj );
+ ao_directx->dsobj = 0;
+ }
+
+#ifdef LOG
+ printf("audio_directx_out: DestroyDirectSound() Exit\n");
+#endif
+
+}
+
+// Used to create directx sound buffer,
+// notification events, and initialize
+// buffer to null sample data.
+
+boolean CreateSoundBuffer( ao_directx_t * ao_directx )
+{
+ DSBUFFERDESC dsbdesc;
+ PCMWAVEFORMAT pcmwf;
+
+#ifdef LOG
+ printf("audio_directx_out: CreateSoundBuffer(%08x) Enter\n", (unsigned long)ao_directx);
+#endif
+
+ // calculate buffer and frame size
+
+ ao_directx->frsz = ( ao_directx->bits / 8 ) * ao_directx->chnn;
+ ao_directx->buffer_size = ( ao_directx->frsz * ao_directx->rate ) / SOUND_BUFFER_DIV;
+
+ // release any existing sound buffer
+ // related resources
+
+ DestroySoundBuffer( ao_directx );
+
+ // create a secondary sound buffer
+
+ memset( &pcmwf, 0, sizeof( PCMWAVEFORMAT ) );
+ pcmwf.wBitsPerSample = ( unsigned short ) ao_directx->bits;
+ pcmwf.wf.wFormatTag = WAVE_FORMAT_PCM;
+ pcmwf.wf.nChannels = ao_directx->chnn;
+ pcmwf.wf.nSamplesPerSec = ao_directx->rate;
+ pcmwf.wf.nBlockAlign = ao_directx->frsz;
+ pcmwf.wf.nAvgBytesPerSec = ao_directx->rate * ao_directx->frsz;
+
+ memset( &dsbdesc, 0, sizeof( DSBUFFERDESC ) );
+ dsbdesc.dwSize = sizeof( DSBUFFERDESC );
+ dsbdesc.dwFlags = DSBCAPS_CTRLVOLUME | DSBCAPS_GLOBALFOCUS |
+ DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLPOSITIONNOTIFY;
+ dsbdesc.dwBufferBytes = ao_directx->buffer_size;
+ dsbdesc.lpwfxFormat = ( LPWAVEFORMATEX ) &pcmwf;
+
+ if( IDirectSound_CreateSoundBuffer( ao_directx->dsobj, &dsbdesc,
+ &ao_directx->dsbuffer, 0 ) != DS_OK )
+ {
+ Error( 0, "IDirectSound_CreateSoundBuffer : Unable to create secondary sound buffer" );
+ return FALSE;
+ }
+
+ // get the buffer capabilities
+
+ memset( &ao_directx->dsbcaps, 0, sizeof( DSBCAPS ) );
+ ao_directx->dsbcaps.dwSize = sizeof( DSBCAPS );
+
+ if( IDirectSound_GetCaps( ao_directx->dsbuffer, &ao_directx->dsbcaps ) != DS_OK )
+ {
+ Error( 0, "IDirectSound_GetCaps : Unable to get secondary sound buffer capabilities" );
+ return FALSE;
+ }
+
+ // create left side notification ( non-signaled )
+
+ ao_directx->notify_events[ 0 ].hEventNotify = CreateEvent( NULL, FALSE, FALSE, NULL );
+
+ // create right side notification ( signaled )
+
+ ao_directx->notify_events[ 1 ].hEventNotify = CreateEvent( NULL, FALSE, FALSE, NULL );
+
+ if( !ao_directx->notify_events[ 0 ].hEventNotify || !ao_directx->notify_events[ 1 ].hEventNotify )
+ {
+ Error( 0, "CreateEvent : Unable to create sound notification events" );
+ return FALSE;
+ }
+
+ // get the direct sound notification interface
+
+ if( IDirectSoundBuffer_QueryInterface( ao_directx->dsbuffer,
+ &IID_IDirectSoundNotify,
+ (LPVOID *)&ao_directx->notify ) != DS_OK )
+ {
+ Error( 0, "IDirectSoundBuffer_QueryInterface : Unable to get notification interface" );
+ return FALSE;
+ }
+
+ // set notification events
+
+ ao_directx->notify_events[ 0 ].dwOffset = 0;
+ ao_directx->notify_events[ 1 ].dwOffset = ao_directx->buffer_size / 2;
+
+ if( IDirectSoundNotify_SetNotificationPositions( ao_directx->notify, 2,
+ ao_directx->notify_events ) != DS_OK )
+ {
+ Error( 0, "IDirectSoundNotify_SetNotificationPositions : Unable to set notification positions" );
+ return FALSE;
+ }
+
+ // DEBUG : set sound buffer volume
+
+ if( IDirectSoundBuffer_SetVolume( ao_directx->dsbuffer, DSBVOLUME_MAX ) != DS_OK )
+ {
+ Error( 0, "IDirectSoundBuffer_SetVolume : Unable to set sound buffer volume" );
+ return FALSE;
+ }
+
+ // initialize our sound buffer
+
+ IDirectSoundBuffer_SetVolume( ao_directx->dsbuffer, DSBVOLUME_MIN );
+ FillSoundBuffer( ao_directx, DSBUFF_INIT, 0 );
+
+ return TRUE;
+
+#ifdef LOG
+ printf("audio_directx_out: CreateSoundBuffer() Exit\n");
+#endif
+
+}
+
+// Destroy all direct sound buffer allocated
+// resources.
+
+void DestroySoundBuffer( ao_directx_t * ao_directx )
+{
+#ifdef LOG
+ printf("audio_directx_out: DestroySoundBuffer(%08x) Enter\n", (unsigned long)ao_directx);
+#endif
+
+ // stop our buffer and zero it out
+
+ if( ao_directx->dsbuffer )
+ {
+ IDirectSoundBuffer_SetVolume( ao_directx->dsbuffer, DSBVOLUME_MIN );
+ IDirectSoundBuffer_Stop( ao_directx->dsbuffer );
+ FillSoundBuffer( ao_directx, DSBUFF_INIT, 0 );
+ }
+
+ // release our notification events
+
+ if( ao_directx->notify_events[ 0 ].hEventNotify )
+ {
+ CloseHandle( ao_directx->notify_events[ 0 ].hEventNotify );
+ ao_directx->notify_events[ 0 ].hEventNotify = 0;
+ }
+
+ if( ao_directx->notify_events[ 1 ].hEventNotify )
+ {
+ CloseHandle( ao_directx->notify_events[ 1 ].hEventNotify );
+ ao_directx->notify_events[ 1 ].hEventNotify = 0;
+ }
+
+ // release our buffer notification interface
+
+ if( ao_directx->notify )
+ {
+ IDirectSoundNotify_Release( ao_directx->notify );
+ ao_directx->notify = 0;
+ }
+
+ // release our direct sound buffer
+
+ if( ao_directx->dsbuffer )
+ {
+ IDirectSoundBuffer_Release( ao_directx->dsbuffer );
+ ao_directx->dsbuffer = 0;
+ }
+
+#ifdef LOG
+ printf("audio_directx_out: DestroySoundBuffer() Exit\n");
+#endif
+
+}
+
+// Used to fill our looping sound buffer
+// with data.
+
+uint32_t FillSoundBuffer( ao_directx_t * ao_directx, int code, unsigned char * samples )
+{
+ uint8_t * buff_pointer; // pointer inside circular buffer
+ uint32_t buff_length; // bytes locked by pointer
+ uint32_t half_size; // half our sound buffer size
+ uint32_t result; // error result
+
+#ifdef LOG
+ if ((void*)samples != (void*)0)
+ printf("audio_directx_out: FillSoundBuffer(%08x, %d, Null) Enter\n", (unsigned long)ao_directx, code);
+ else
+ printf("audio_directx_out: FillSoundBuffer(%08x, %d, Null) Enter\n", (unsigned long)ao_directx, code);
+#endif
+
+ half_size = ao_directx->buffer_size / 2;
+
+ if( code == DSBUFF_INIT )
+ {
+#ifdef LOG
+ printf("audio_directx_out: FillSoundBuffer: DSBUFF_INIT\n");
+#endif
+
+ // set our new status code
+
+ ao_directx->write_status = DSBUFF_RIGHT;
+
+ // lock our sound buffer for write access
+
+ result = IDirectSoundBuffer_Lock( ao_directx->dsbuffer,
+ 0, 0,
+ &buff_pointer, &buff_length,
+ 0, 0, DSBLOCK_ENTIREBUFFER );
+ if( result != DS_OK )
+ {
+ Error( 0, "IDirectSoundBuffer_Lock : could not lock sound buffer" );
+ return 0;
+ }
+
+ // clear our entire sound buffer
+
+ memset( buff_pointer, 0, buff_length );
+
+ // unlock our sound buffer
+
+ if( IDirectSoundBuffer_Unlock( ao_directx->dsbuffer,
+ buff_pointer, buff_length,
+ 0, 0 ) != DS_OK )
+ {
+ Error( 0, "IDirectSoundBuffer_Unlock : could not unlock sound buffer" );
+ return 0;
+ }
+
+ // start the buffer playing
+
+ if( IDirectSoundBuffer_Play( ao_directx->dsbuffer, 0, 0, DSBPLAY_LOOPING ) != DS_OK )
+ {
+ Error( 0, "IDirectSoundBuffer_Play : could not play sound buffer" );
+ return 0 ;
+ }
+ else
+ IDirectSoundBuffer_SetVolume( ao_directx->dsbuffer, ao_directx->volume );
+ }
+ else if( code == DSBUFF_LEFT )
+ {
+#ifdef LOG
+ printf("audio_directx_out: FillSoundBuffer: DSBUFF_LEFT\n");
+#endif
+ // set our new status code
+
+ ao_directx->write_status = DSBUFF_RIGHT;
+
+ // lock our sound buffer for write access
+
+ result = IDirectSoundBuffer_Lock( ao_directx->dsbuffer,
+ 0, half_size,
+ &buff_pointer, &buff_length,
+ 0, 0, 0 );
+ if( result != DS_OK )
+ {
+ Error( 0, "IDirectSoundBuffer_Lock : could not lock sound buffer" );
+ return 0;
+ }
+
+ // write data to our sound buffer
+
+ memcpy( buff_pointer, samples, buff_length );
+
+ // unlock our sound buffer
+
+ if( IDirectSoundBuffer_Unlock( ao_directx->dsbuffer,
+ buff_pointer, buff_length,
+ 0, 0 ) != DS_OK )
+ {
+ Error( 0, "IDirectSoundBuffer_Unlock : could not unlock sound buffer" );
+ return 0;
+ }
+
+ }
+ else if( code == DSBUFF_RIGHT )
+ {
+#ifdef LOG
+ printf("audio_directx_out: FillSoundBuffer: DSBUFF_RIGHT\n");
+#endif
+ // set our new status code
+
+ ao_directx->write_status = DSBUFF_LEFT;
+
+ // lock our sound buffer for write access
+
+ result = IDirectSoundBuffer_Lock( ao_directx->dsbuffer,
+ half_size, half_size,
+ &buff_pointer, &buff_length,
+ 0, 0, 0 );
+ if( result != DS_OK )
+ {
+ Error( 0, "IDirectSoundBuffer_Lock : could not lock sound buffer" );
+ return 0;
+ }
+
+ // write data to our sound buffer
+
+ memcpy( buff_pointer, samples, buff_length );
+
+ // unlock our sound buffer
+
+ if( IDirectSoundBuffer_Unlock( ao_directx->dsbuffer,
+ buff_pointer, buff_length,
+ 0, 0 ) != DS_OK )
+ {
+ Error( 0, "IDirectSoundBuffer_Unlock : could not unlock sound buffer" );
+ return 0;
+ }
+ }
+
+#ifdef LOG
+ printf("audio_directx_out: FillSoundBuffer() Exit\n");
+#endif
+
+ return buff_length;
+}
+
+// -----------------------------------------
+//
+// BEGIN : Xine driver audio output plugin
+// handlers.
+//
+// -----------------------------------------
+
+static int ao_directx_control(ao_driver_t *this_gen, int cmd, ...) {
+
+ ao_directx_t * ao_directx = ( ao_directx_t * ) this_gen;
+
+ switch (cmd)
+ {
+
+ case AO_CTRL_PLAY_PAUSE:
+ break;
+
+ case AO_CTRL_PLAY_RESUME:
+ break;
+
+ case AO_CTRL_FLUSH_BUFFERS:
+ break;
+ }
+
+ return 0;
+}
+
+
+
+static int ao_directx_open( ao_driver_t * ao_driver, uint32_t bits, uint32_t rate, int mode )
+{
+ ao_directx_t * ao_directx = ( ao_directx_t * ) ao_driver;
+
+#ifdef LOG
+ printf("audio_directx_out: ao_directx_open(%08x, %d, %d, %d) Enter\n", (unsigned long)ao_directx, bits, rate, mode);
+#endif
+ // store input rate and bits
+
+ ao_directx->bits = bits;
+ ao_directx->rate = rate;
+
+ // store channel count
+
+ switch( mode )
+ {
+ case AO_CAP_MODE_MONO:
+ ao_directx->chnn = 1;
+ printf( "ao_directx : opened in AO_CAP_MODE_MONO mode\n" );
+ break;
+
+ case AO_CAP_MODE_STEREO:
+ ao_directx->chnn = 2;
+ printf( "ao_directx : opened in AO_CAP_MODE_STEREO mode\n" );
+ break;
+
+ case AO_CAP_MODE_4CHANNEL:
+ ao_directx->chnn = 4;
+ printf( "ao_directx : opened in AO_CAP_MODE_4CHANNEL mode\n" );
+ break;
+
+ case AO_CAP_MODE_5CHANNEL:
+ ao_directx->chnn = 5;
+ printf( "ao_directx : opened in AO_CAP_MODE_5CHANNEL mode\n" );
+ break;
+
+ case AO_CAP_MODE_5_1CHANNEL:
+ ao_directx->chnn = 6;
+ printf( "ao_directx : opened in AO_CAP_MODE_5_1CHANNEL mode\n" );
+ break;
+
+ case AO_CAP_MODE_A52:
+ case AO_CAP_MODE_AC5:
+ return 0;
+ }
+
+ CreateSoundBuffer( ao_directx );
+
+#ifdef LOG
+ printf("audio_directx_out: ao_directx_open() Exit! Returning ao_directx->rate=%d\n", ao_directx->rate);
+#endif
+
+ return ao_directx->rate;
+}
+
+static int ao_directx_num_channels( ao_driver_t * ao_driver )
+{
+ ao_directx_t * ao_directx = ( ao_directx_t * ) ao_driver;
+ return ao_directx->chnn;
+}
+
+static int ao_directx_bytes_per_frame( ao_driver_t * ao_driver )
+{
+ ao_directx_t * ao_directx = ( ao_directx_t * ) ao_driver;
+ return ao_directx->frsz;
+}
+
+static int ao_directx_get_gap_tolerance( ao_driver_t * ao_driver )
+{
+ ao_directx_t * ao_directx = ( ao_directx_t * ) ao_driver;
+ return 5000;
+}
+
+static int ao_directx_delay( ao_driver_t * ao_driver )
+{
+ DWORD current_read;
+ DWORD bytes_left;
+ DWORD frames_left;
+
+ ao_directx_t * ao_directx = ( ao_directx_t * ) ao_driver;
+
+#ifdef LOG
+ printf("audio_directx_out: ao_directx_delay(%08x) Enter\n", (unsigned long)ao_directx);
+#endif
+
+ IDirectSoundBuffer_GetCurrentPosition( ao_directx->dsbuffer, &current_read, 0 );
+
+ if( ao_directx->write_pos > current_read )
+ bytes_left = ( ao_directx->write_pos - current_read );
+ else
+ bytes_left = ( ao_directx->write_pos + ao_directx->buffer_size - current_read );
+
+ frames_left = ( ao_directx->prebuff_size + bytes_left ) / ao_directx->frsz;
+
+#ifdef LOG
+ printf("audio_directx_out: ao_directx_delay() Exit! Returning frames_left=%d\n", frames_left);
+#endif
+
+ return frames_left;
+}
+
+static int ao_directx_write( ao_driver_t * ao_driver, int16_t * frame_buffer, uint32_t num_frames )
+{
+ ao_directx_t * ao_directx = ( ao_directx_t * ) ao_driver;
+
+ uint32_t frame_bytes; // how many bytes to lock
+ uint32_t wrote; // number of bytes written
+ uint32_t half_size; // half our sound buffer size
+
+#ifdef LOG
+ printf("audio_directx_out: ao_directx_write(%08x, %08x, %d) Enter\n", (unsigned long)ao_directx, (unsigned long)frame_buffer, num_frames);
+#endif
+
+ // zero write counter
+
+ wrote = 0;
+
+ // calculate how many bytes in frame_buffer
+
+ frame_bytes = num_frames * ao_directx->frsz;
+
+ // calculate half our buffer size
+
+ half_size = ao_directx->buffer_size / 2;
+
+ // fill audio prebuff
+
+ memcpy( ao_directx->prebuff + ao_directx->prebuff_size, frame_buffer, frame_bytes );
+ ao_directx->prebuff_size = ao_directx->prebuff_size + frame_bytes;
+
+ // check to see if we have enough in prebuff to
+ // fill half of our sound buffer
+
+ while( ao_directx->prebuff_size >= half_size )
+ {
+ // write to our sound buffer
+
+ if( ao_directx->write_status == DSBUFF_LEFT )
+ {
+ // wait for our read pointer to reach the right half
+ // of our sound buffer, we only want to write to the
+ // left side
+
+ WaitForSingleObject( ao_directx->notify_events[ 1 ].hEventNotify, INFINITE );
+
+ // fill left half of our buffer
+
+ wrote = FillSoundBuffer( ao_directx, DSBUFF_LEFT, ao_directx->prebuff );
+ }
+ else if( ao_directx->write_status == DSBUFF_RIGHT )
+ {
+ // wait for our read pointer to reach the left half,
+ // of our sound buffer, we only want to write to the
+ // right side
+
+ WaitForSingleObject( ao_directx->notify_events[ 0 ].hEventNotify, INFINITE );
+
+ // fill right half of our buffer
+
+ wrote = FillSoundBuffer( ao_directx, DSBUFF_RIGHT, ao_directx->prebuff );
+ }
+
+ // calc bytes written and store position for next write
+
+ ao_directx->write_pos = ( ao_directx->write_pos + wrote ) % ao_directx->buffer_size;
+
+ // copy remaining contents of prebuff and recalc size
+
+ memcpy( ao_directx->prebuff, ao_directx->prebuff + wrote, ao_directx->prebuff_size - wrote );
+ ao_directx->prebuff_size = ao_directx->prebuff_size - wrote;
+ }
+
+#ifdef LOG
+ printf("audio_directx_out: ao_directx_write() Exit! Returning num_frmaes=%d\n", num_frames);
+#endif
+
+ return num_frames;
+}
+
+static void ao_directx_close( ao_driver_t * ao_driver )
+{
+ ao_directx_t * ao_directx = ( ao_directx_t * ) ao_driver;
+
+#ifdef LOG
+ printf("audio_directx_out: ao_directx_close(%08x) Enter\n", (unsigned long)ao_directx);
+#endif
+
+ // release any existing sound buffer
+ // related resources
+
+ DestroySoundBuffer( ao_directx );
+
+#ifdef LOG
+ printf("audio_directx_out: ao_directx_close() Exit!\n");
+#endif
+
+}
+
+static uint32_t ao_directx_get_capabilities( ao_driver_t * ao_driver )
+{
+ ao_directx_t * ao_directx = ( ao_directx_t * ) ao_driver;
+ return AO_CAP_MODE_STEREO | AO_CAP_MIXER_VOL | AO_CAP_PCM_VOL | AO_CAP_MUTE_VOL;
+}
+
+static void ao_directx_exit( ao_driver_t * ao_driver )
+{
+ ao_directx_t * ao_directx = ( ao_directx_t * ) ao_driver;
+
+#ifdef LOG
+ printf("audio_directx_out: ao_directx_exit(%08x) Enter\n", (unsigned long)ao_directx);
+#endif
+
+ // release any existing sound buffer
+ // related resources
+
+ DestroySoundBuffer( ao_directx );
+
+ // release any existing direct sound
+ // related resources
+
+ DestroyDirectSound( ao_directx );
+
+ // free our driver
+
+ free( ao_directx );
+
+#ifdef LOG
+ printf("audio_directx_out: ao_directx_exit() Exit!\n");
+#endif
+
+}
+
+static int ao_directx_get_property( ao_driver_t * ao_driver, int property )
+{
+ ao_directx_t * ao_directx = ( ao_directx_t * ) ao_driver;
+ return 0;
+}
+
+static int ao_directx_set_property( ao_driver_t * ao_driver, int property, int value )
+{
+ ao_directx_t * ao_directx = ( ao_directx_t * ) ao_driver;
+
+#ifdef LOG
+ printf("audio_directx_out: ao_directx_set_property(%08x, %d, %d) Enter\n", (unsigned long)ao_directx, property, value);
+#endif
+
+ switch( property )
+ {
+ case AO_PROP_PCM_VOL:
+ case AO_PROP_MIXER_VOL:
+#ifdef LOG
+ printf("audio_directx_out: ao_directx_set_property: AO_PROP_PCM_VOL|AO_PROP_MIXER_VOL\n");
+#endif
+
+ ao_directx->volume = value * ( DSBVOLUME_MIN / 100 / 3);
+
+ if( !ao_directx->mute && ao_directx->dsbuffer )
+ IDirectSoundBuffer_SetVolume( ao_directx->dsbuffer, ao_directx->volume );
+
+ printf( "ao_directx : volume set to %d - directX volume = %d\n", value, ao_directx->volume);
+
+ return value;
+
+ break;
+
+ case AO_PROP_MUTE_VOL:
+
+#ifdef LOG
+ printf("audio_directx_out: ao_directx_set_property: AO_PROP_MUTE_VOL\n");
+#endif
+
+ ao_directx->mute = value;
+
+ if( !ao_directx->mute && ao_directx->dsbuffer )
+ IDirectSoundBuffer_SetVolume( ao_directx->dsbuffer, ao_directx->volume );
+
+ if( ao_directx->mute && ao_directx->dsbuffer )
+ IDirectSoundBuffer_SetVolume( ao_directx->dsbuffer, DSBVOLUME_MIN );
+
+ printf( "ao_directx : mute toggled" );
+
+ return value;
+
+ break;
+ }
+
+#ifdef LOG
+ printf("audio_directx_out: ao_directx_set_property() Exit! Returning ~value=%d\n", ~value);
+#endif
+
+ return ~value;
+}
+
+static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *data)
+{
+ ao_directx_t * ao_directx = ( ao_directx_t * ) malloc( sizeof( ao_directx_t ) );
+ memset( ao_directx, 0, sizeof( ao_directx_t ) );
+
+#ifdef LOG
+ printf("audio_directx_out: open_plugin(%08x, %08x) Enter\n", (unsigned long)class_gen, (unsigned long)data);
+ printf("audio_directx_out: open_plugin: ao_directx=%08x\n", (unsigned long)ao_directx);
+#endif
+
+ ao_directx->ao_driver.get_capabilities = ao_directx_get_capabilities;
+ ao_directx->ao_driver.get_property = ao_directx_get_property;
+ ao_directx->ao_driver.set_property = ao_directx_set_property;
+ ao_directx->ao_driver.open = ao_directx_open;
+ ao_directx->ao_driver.num_channels = ao_directx_num_channels;
+ ao_directx->ao_driver.bytes_per_frame = ao_directx_bytes_per_frame;
+ ao_directx->ao_driver.delay = ao_directx_delay;
+ ao_directx->ao_driver.write = ao_directx_write;
+ ao_directx->ao_driver.close = ao_directx_close;
+ ao_directx->ao_driver.exit = ao_directx_exit;
+ ao_directx->ao_driver.get_gap_tolerance = ao_directx_get_gap_tolerance;
+ ao_directx->ao_driver.control = ao_directx_control;
+
+ CreateDirectSound( ao_directx );
+
+#ifdef LOG
+ printf("audio_directx_out: open_plugin() Exit! Returning ao_directx=%08x\n", (unsigned long)ao_directx);
+#endif
+
+ return ( ao_driver_t * ) ao_directx;
+}
+
+static char* get_identifier (video_driver_class_t *this_gen) {
+ return "DirectX";
+}
+
+static char* get_description (audio_driver_class_t *this_gen) {
+ return _("xine audio output plugin for win32 using directx");
+}
+
+static void dispose_class (audio_driver_class_t *this_gen) {
+
+ audiox_class_t *audiox = (audiox_class_t *) this_gen;
+ free (audiox);
+}
+
+static void *init_class (xine_t *xine, void *data) {
+
+ audiox_class_t *audiox;
+ char* device_name;
+
+#ifdef LOG
+ printf("audio_directx_out: init_class() Enter\n");
+#endif
+
+ device_name = xine->config->register_string(xine->config,
+ "audio.directx_device", "/dev/audio_directx",
+ _("xine audio output plugin for win32 using directx"),
+ NULL, 10, NULL, NULL);
+
+ /*
+ * from this point on, nothing should go wrong anymore
+ */
+ audiox = (audiox_class_t *) malloc (sizeof (audiox_class_t));
+ memset( audiox, 0, sizeof( audiox_class_t ) );
+
+ audiox->driver_class.open_plugin = open_plugin;
+ audiox->driver_class.get_identifier = get_identifier;
+ audiox->driver_class.get_description = get_description;
+ audiox->driver_class.dispose = dispose_class;
+
+ audiox->config = xine->config;
+ audiox->device_name = device_name;
+
+#ifdef LOG
+ printf("audio_directx_out: init_class() Exit! Returning audiox=%08x\n", audiox);
+#endif
+
+ return audiox;
+}
+
+static uint32_t audio_types[] = {
+ BUF_AUDIO_DIRECTX,
+ 0
+ };
+
+static decoder_info_t dec_info_audio = {
+ audio_types, /* supported types */
+ 1 /* priority */
+};
+
+/*
+ * exported plugin catalog entry
+ */
+plugin_info_t xine_plugin_info[] = {
+ /* type, API, "name", version, special_info, init_function */
+ { PLUGIN_AUDIO_OUT, AO_DIRECTX_IFACE_VERSION, "directx", XINE_VERSION_CODE, &dec_info_audio, init_class },
+ { PLUGIN_NONE, 0, "", 0, NULL, NULL }
+};
+
+ao_info_t *get_audio_out_plugin_info()
+{
+ return (ao_info_t *)&dec_info_audio;
+}
+
diff --git a/src/video_out/video_out_directx.c b/src/video_out/video_out_directx.c
new file mode 100755
index 000000000..590574da2
--- /dev/null
+++ b/src/video_out/video_out_directx.c
@@ -0,0 +1,1289 @@
+/*
+ * Copyright (C) 2000-2001 the xine project
+ *
+ * This file is part of xine, a unix video player.
+ *
+ * xine 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.
+ *
+ * xine 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * video_out_directx.c, direct draw video output plugin for xine
+ * by Matthew Grooms <elon@altavista.com>
+ */
+
+typedef unsigned char boolean;
+
+#include <windows.h>
+#include <ddraw.h>
+
+#include "xine.h"
+#include "video_out.h"
+#include "video_out_win32.h"
+#include "alphablend.h"
+#include "xine_internal.h"
+#include "yuv2rgb.h"
+
+/**/
+#define LOG 1
+/**/
+
+#define NEW_YUV 1
+
+/* Set to 1 for RGB support */
+#define RGB_SUPPORT 0
+
+#define BORDER_SIZE 8
+#define IMGFMT_NATIVE 4
+
+// -----------------------------------------
+//
+// vo_directx frame struct
+//
+// -----------------------------------------
+
+typedef struct win32_frame_s
+{
+ vo_frame_t vo_frame;
+
+ uint8_t * buffer;
+ int format;
+ int width;
+ int height;
+ int size;
+ int rcode;
+
+}win32_frame_t;
+
+// -----------------------------------------
+//
+// vo_directx driver struct
+//
+// -----------------------------------------
+
+typedef struct
+{
+ vo_driver_t vo_driver;
+ win32_visual_t * win32_visual;
+
+ LPDIRECTDRAW7 ddobj; // direct draw object
+ LPDIRECTDRAWSURFACE primary; // primary dd surface
+ LPDIRECTDRAWSURFACE secondary; // secondary dd surface
+ LPDIRECTDRAWCLIPPER ddclipper; // dd clipper object
+ uint8_t * contents; // secondary contents
+ win32_frame_t *current; // current frame
+
+ int req_format; // requested frame format
+ int act_format; // actual frame format
+ int width; // frame with
+ int height; // frame height
+ double ratio; // frame ratio
+
+ yuv2rgb_factory_t *yuv2rgb_factory; // used for format conversion
+ yuv2rgb_t *yuv2rgb; // used for format conversion
+ int mode; // rgb mode
+ int bytespp; // rgb bits per pixel
+
+}win32_driver_t;
+
+
+typedef struct {
+ video_driver_class_t driver_class;
+
+ config_values_t *config;
+
+ char *device_name;
+} directx_class_t;
+
+// -----------------------------------------
+//
+// BEGIN : Direct Draw and win32 handlers
+// for xine video output plugins.
+//
+// -----------------------------------------
+
+// Display formatted error message in
+// popup message box.
+
+void Error( HWND hwnd, LPSTR szfmt, ... )
+{
+ char tempbuff[ 256 ];
+ *tempbuff = 0;
+ wvsprintf( &tempbuff[ strlen( tempbuff ) ], szfmt, ( char * )( &szfmt + 1 ) );
+ MessageBox( hwnd, tempbuff, "Error", MB_ICONERROR | MB_OK | MB_APPLMODAL | MB_SYSTEMMODAL );
+}
+
+// Update our drivers current knowledge
+// of our windows video out posistion
+
+void UpdateRect( win32_visual_t * win32_visual )
+{
+ if( win32_visual->FullScreen )
+ {
+ SetRect( &win32_visual->WndRect, 0, 0,
+ GetSystemMetrics( SM_CXSCREEN ),
+ GetSystemMetrics( SM_CYSCREEN ) );
+ }
+ else
+ {
+ GetClientRect( win32_visual->WndHnd, &win32_visual->WndRect );
+ ClientToScreen( win32_visual->WndHnd, ( POINT * ) &win32_visual->WndRect );
+ ClientToScreen( win32_visual->WndHnd, ( POINT * ) &win32_visual->WndRect + 1 );
+ }
+}
+
+// Create our direct draw object, primary
+// surface and clipper object.
+//
+// NOTE : The primary surface is more or
+// less a viewport into the parent desktop
+// window and will always have a pixel format
+// identical to the current display mode.
+
+boolean CreatePrimary( win32_driver_t * win32_driver )
+{
+ LPDIRECTDRAW ddobj;
+ DDSURFACEDESC2 ddsd;
+ HRESULT result;
+
+ // create direct draw object
+
+ result = DirectDrawCreate( 0, &ddobj, 0 );
+ if( result != DD_OK )
+ {
+ Error( 0, "DirectDrawCreate : error %i", result );
+ printf( "vo_out_directx : DirectDrawCreate : error %i\n", result );
+ return 0;
+ }
+
+ // set cooperative level
+
+ result = IDirectDraw_SetCooperativeLevel( ddobj, win32_driver->win32_visual->WndHnd, DDSCL_NORMAL );
+ if( result != DD_OK )
+ {
+ Error( 0, "SetCooperativeLevel : error %i", result );
+ return 0;
+ }
+
+ // try to get new interface
+
+ result = IDirectDraw_QueryInterface( ddobj, &IID_IDirectDraw7, (LPVOID *) &win32_driver->ddobj );
+ if( result != DD_OK )
+ {
+ Error( 0, "ddobj->QueryInterface : DirectX 7 or higher required" );
+ return 0;
+ }
+
+ // release our old interface
+
+ IDirectDraw_Release( ddobj );
+
+ // create primary_surface
+
+ memset( &ddsd, 0, sizeof( ddsd ) );
+ ddsd.dwSize = sizeof( ddsd );
+ ddsd.dwFlags = DDSD_CAPS;
+ ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
+
+ result = IDirectDraw7_CreateSurface( win32_driver->ddobj, &ddsd, &win32_driver->primary, 0 );
+ if( result != DD_OK )
+ {
+ Error( 0, "CreateSurface ( primary ) : error %i ", result );
+ return 0;
+ }
+
+ // create our clipper object
+
+ result = IDirectDraw7_CreateClipper( win32_driver->ddobj, 0, &win32_driver->ddclipper, 0 );
+ if( result != DD_OK )
+ {
+ Error( 0, "CreateClipper : error %i", result );
+ return 0;
+ }
+
+ // associate our clipper with our window
+
+ result = IDirectDrawClipper_SetHWnd( win32_driver->ddclipper, 0, win32_driver->win32_visual->WndHnd );
+ if( result != DD_OK )
+ {
+ Error( 0, "ddclipper->SetHWnd : error %i", result );
+ return 0;
+ }
+
+ // associate our primary surface with our clipper
+
+ result = IDirectDrawSurface7_SetClipper( win32_driver->primary, win32_driver->ddclipper );
+ if( result != DD_OK )
+ {
+ Error( 0, "ddclipper->SetHWnd : error %i", result );
+ return 0;
+ }
+
+ // store our objects in our visual struct
+
+ UpdateRect( win32_driver->win32_visual );
+
+ return 1;
+}
+
+// Create our secondary ( off screen ) buffer.
+// The optimal secondary buffer is a h/w
+// overlay with the same pixel format as the
+// xine frame type. However, since this is
+// not always supported by the host h/w,
+// we will fall back to creating an rgb buffer
+// in video memory qith the same pixel format
+// as the primary surface. At least then we
+// can use h/w scaling if supported.
+
+boolean CreateSecondary( win32_driver_t * win32_driver, int width, int height, int format )
+{
+ DDSURFACEDESC2 ddsd;
+
+ if( format == XINE_IMGFMT_YV12 )
+ printf( "vo_out_directx : switching to YV12 overlay type\n" );
+
+ if( format == XINE_IMGFMT_YUY2 )
+ printf( "vo_out_directx : switching to YUY2 overlay type\n" );
+
+#if RGB_SUPPORT
+ if( format == IMGFMT_RGB )
+ printf( "vo_out_directx : switching to RGB overlay type\n" );
+#endif
+
+ if( !win32_driver->ddobj )
+ return FALSE;
+
+ // store our reqested format,
+ // width and height
+
+ win32_driver->req_format = format;
+ win32_driver->width = width;
+ win32_driver->height = height;
+
+ // if we already have a secondary
+ // surface then release it
+
+ if( win32_driver->secondary )
+ IDirectDrawSurface7_Release( win32_driver->secondary );
+
+ memset( &ddsd, 0, sizeof( ddsd ) );
+ ddsd.dwSize = sizeof( ddsd );
+ ddsd.dwWidth = width;
+ ddsd.dwHeight = height;
+
+ if( format == XINE_IMGFMT_YV12 )
+ {
+ // the requested format is XINE_IMGFMT_YV12
+
+ ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
+ ddsd.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_OVERLAY;
+ ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
+ ddsd.ddpfPixelFormat.dwFlags = DDPF_FOURCC;
+ ddsd.ddpfPixelFormat.dwYUVBitCount = 16;
+ ddsd.ddpfPixelFormat.dwFourCC = mmioFOURCC( 'Y', 'V', '1', '2' );
+
+#ifdef LOG
+ printf("CreateSecondary() - act_format = (YV12) %d\n", XINE_IMGFMT_YV12);
+#endif
+
+ win32_driver->act_format = XINE_IMGFMT_YV12;
+ }
+
+ if( format == XINE_IMGFMT_YUY2 )
+ {
+ // the requested format is XINE_IMGFMT_YUY2
+
+ ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
+ ddsd.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_OVERLAY;
+ ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
+ ddsd.ddpfPixelFormat.dwFlags = DDPF_FOURCC;
+ ddsd.ddpfPixelFormat.dwYUVBitCount = 16;
+ ddsd.ddpfPixelFormat.dwFourCC = mmioFOURCC( 'Y', 'U', 'Y', '2' );
+
+#ifdef LOG
+ printf("CreateSecondary() - act_format = (YUY2) %d\n", XINE_IMGFMT_YUY2);
+#endif
+
+ win32_driver->act_format = XINE_IMGFMT_YUY2;
+ }
+
+#if RGB_SUPPORT
+ if( format == IMGFMT_RGB )
+ {
+ // the requested format is IMGFMT_RGB
+
+ ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
+ ddsd.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_OVERLAY;
+ ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
+ ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
+ ddsd.ddpfPixelFormat.dwYUVBitCount = 24;
+ ddsd.ddpfPixelFormat.dwRBitMask = 0xff0000;
+ ddsd.ddpfPixelFormat.dwGBitMask = 0x00ff00;
+ ddsd.ddpfPixelFormat.dwBBitMask = 0x0000ff;
+
+#ifdef LOG
+ printf("CreateSecondary() - act_format = (RGB) %d\n", IMGFMT_RGB);
+#endif
+
+ win32_driver->act_format = IMGFMT_RGB;
+ }
+#endif /* RGB_SUPPORT */
+
+#ifdef LOG
+ printf("CreateSecondary() - IDirectDraw7_CreateSurface()\n");
+#endif
+
+ if( IDirectDraw7_CreateSurface( win32_driver->ddobj, &ddsd, &win32_driver->secondary, 0 ) == DD_OK )
+ return TRUE;
+
+ // Our fallback method is to create a back buffer
+ // with the same image format as the primary surface
+
+#ifdef LOG
+ printf("CreateSecondary() - Falling back to back buffer same as primary\n");
+#endif
+
+ ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
+ ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;
+
+#ifdef LOG
+ printf("CreateSecondary() - act_format = (NATIVE) %d\n", IMGFMT_NATIVE);
+#endif
+
+ win32_driver->act_format = IMGFMT_NATIVE;
+
+ if( IDirectDraw7_CreateSurface( win32_driver->ddobj, &ddsd, &win32_driver->secondary, 0 ) == DD_OK )
+ return TRUE;
+
+ // This is bad. We cant even create a surface with
+ // the same format as the primary surface.
+
+ Error( 0, "CreateSurface ( Secondary ) : unable to create a suitable rendering surface" );
+
+ return FALSE;
+}
+
+// Destroy all direct draw driver allocated
+// resources.
+
+void Destroy( win32_driver_t * win32_driver )
+{
+ if( win32_driver->ddclipper )
+ IDirectDrawClipper_Release( win32_driver->ddclipper );
+
+ if( win32_driver->primary )
+ IDirectDrawSurface7_Release( win32_driver->primary );
+
+ if( win32_driver->secondary )
+ IDirectDrawSurface7_Release( win32_driver->secondary );
+
+ if( win32_driver->ddobj )
+ IDirectDraw_Release( win32_driver->ddobj );
+
+ free( win32_driver );
+}
+
+// Check the current pixel format of the
+// display mode. This is neccesary in case
+// the h/w does not support an overlay for
+// the native frame format.
+
+boolean CheckPixelFormat( win32_driver_t * win32_driver )
+{
+ DDPIXELFORMAT ddpf;
+ HRESULT result;
+
+ // get the pixel format of our primary surface
+
+ memset( &ddpf, 0, sizeof( DDPIXELFORMAT ));
+ ddpf.dwSize = sizeof( DDPIXELFORMAT );
+ result = IDirectDrawSurface7_GetPixelFormat( win32_driver->primary, &ddpf );
+ if( result != DD_OK )
+ {
+ Error( 0, "IDirectDrawSurface7_GetPixelFormat ( CheckPixelFormat ) : error %u", result );
+ return 0;
+ }
+
+ // TODO : support paletized video modes
+
+ if( ( ddpf.dwFlags & DDPF_PALETTEINDEXED1 ) ||
+ ( ddpf.dwFlags & DDPF_PALETTEINDEXED2 ) ||
+ ( ddpf.dwFlags & DDPF_PALETTEINDEXED4 ) ||
+ ( ddpf.dwFlags & DDPF_PALETTEINDEXED8 ) ||
+ ( ddpf.dwFlags & DDPF_PALETTEINDEXEDTO8 ) )
+ return FALSE;
+
+ // store bytes per pixel
+
+ win32_driver->bytespp = ddpf.dwRGBBitCount / 8;
+
+ // find the rgb mode for software
+ // colorspace conversion
+
+ if( ddpf.dwRGBBitCount == 32 )
+ {
+ if( ddpf.dwRBitMask == 0xff0000 )
+ win32_driver->mode = MODE_32_RGB;
+ else
+ win32_driver->mode = MODE_32_BGR;
+ }
+
+ if( ddpf.dwRGBBitCount == 24 )
+ {
+ if( ddpf.dwRBitMask == 0xff0000 )
+ win32_driver->mode = MODE_24_RGB;
+ else
+ win32_driver->mode = MODE_24_BGR;
+ }
+
+ if( ddpf.dwRGBBitCount == 16 )
+ {
+ if( ddpf.dwRBitMask == 0xf800 )
+ win32_driver->mode = MODE_16_RGB;
+ else
+ win32_driver->mode = MODE_16_BGR;
+ }
+
+ if( ddpf.dwRGBBitCount == 15 )
+ {
+ if( ddpf.dwRBitMask == 0x7C00 )
+ win32_driver->mode = MODE_15_RGB;
+ else
+ win32_driver->mode = MODE_15_BGR;
+ }
+
+ return TRUE;
+}
+
+// Create a Direct draw surface from
+// a bitmap resource..
+//
+// NOTE : This is not really useful
+// anymore since the xine logo code is
+// being pushed to the backend.
+
+
+LPDIRECTDRAWSURFACE7 CreateBMP( win32_driver_t * win32_driver, int resource )
+{
+ LPDIRECTDRAWSURFACE7 bmp_surf;
+ DDSURFACEDESC2 bmp_ddsd;
+ HBITMAP bmp_hndl;
+ BITMAP bmp_head;
+ HDC hdc_dds;
+ HDC hdc_mem;
+
+ // load our bitmap from a resource
+
+ if( !( bmp_hndl = LoadBitmap( win32_driver->win32_visual->HInst, MAKEINTRESOURCE( resource ) ) ) )
+ {
+ Error( 0, "CreateBitmap : could not load bmp resource" );
+ return 0;
+ }
+
+ // create an off screen surface with
+ // the same dimentions as our bitmap
+
+ GetObject( bmp_hndl, sizeof( bmp_head ), &bmp_head );
+
+ memset( &bmp_ddsd, 0, sizeof( bmp_ddsd ) );
+ bmp_ddsd.dwSize = sizeof( bmp_ddsd );
+ bmp_ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
+ bmp_ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;
+ bmp_ddsd.dwWidth = bmp_head.bmWidth;
+ bmp_ddsd.dwHeight = bmp_head.bmHeight;
+
+ if( IDirectDraw7_CreateSurface( win32_driver->ddobj, &bmp_ddsd, &bmp_surf, 0 ) != DD_OK )
+ {
+ Error( 0, "CreateSurface ( bitmap ) : could not create dd surface" );
+ return 0;
+ }
+
+ // get a handle to our surface dc,
+ // create a compat dc and load
+ // our bitmap into the compat dc
+
+ IDirectDrawSurface7_GetDC( bmp_surf, &hdc_dds );
+ hdc_mem = CreateCompatibleDC( hdc_dds );
+ SelectObject( hdc_mem, bmp_hndl );
+
+ // copy our bmp from the compat dc
+ // into our dd surface
+
+ BitBlt( hdc_dds, 0, 0, bmp_head.bmWidth, bmp_head.bmHeight,
+ hdc_mem, 0, 0, SRCCOPY );
+
+ // clean up
+
+ DeleteDC( hdc_mem );
+ DeleteObject( bmp_hndl );
+ IDirectDrawSurface7_ReleaseDC( bmp_surf, hdc_dds );
+
+ return bmp_surf;
+}
+
+// Merge overlay with the current primary
+// surface. This funtion is only used when
+// a h/w overlay of the current frame type
+// is supported.
+
+boolean Overlay( LPDIRECTDRAWSURFACE7 src_surface, RECT * src_rect,
+ LPDIRECTDRAWSURFACE7 dst_surface, RECT * dst_rect,
+ COLORREF color_key )
+{
+ DWORD dw_color_key;
+ DDPIXELFORMAT ddpf;
+ DDOVERLAYFX ddofx;
+ int flags;
+ HRESULT result;
+
+ // compute the colorkey pixel value from the RGB value we've got/
+ // NOTE : based on videolan colorkey code
+
+ memset( &ddpf, 0, sizeof( DDPIXELFORMAT ));
+ ddpf.dwSize = sizeof( DDPIXELFORMAT );
+ result = IDirectDrawSurface7_GetPixelFormat( dst_surface, &ddpf );
+ if( result != DD_OK )
+ {
+ Error( 0, "IDirectDrawSurface7_GetPixelFormat : could not get surface pixel format" );
+ return FALSE;
+ }
+
+ dw_color_key = ( DWORD ) color_key;
+ dw_color_key = ( DWORD ) ( ( ( dw_color_key * ddpf.dwRBitMask ) / 255 ) & ddpf.dwRBitMask );
+
+ memset( &ddofx, 0, sizeof( DDOVERLAYFX ) );
+ ddofx.dwSize = sizeof( DDOVERLAYFX );
+ ddofx.dckDestColorkey.dwColorSpaceLowValue = dw_color_key;
+ ddofx.dckDestColorkey.dwColorSpaceHighValue = dw_color_key;
+
+ // set our overlay flags
+
+ flags = DDOVER_SHOW | DDOVER_KEYDESTOVERRIDE;
+
+ // attempt to overlay the surface
+
+ result = IDirectDrawSurface7_UpdateOverlay( src_surface, src_rect, dst_surface, dst_rect, flags, &ddofx );
+ if( result != DD_OK )
+ {
+ if( result == DDERR_SURFACELOST )
+ {
+ IDirectDrawSurface7_Restore( src_surface );
+ IDirectDrawSurface7_Restore( dst_surface );
+
+ IDirectDrawSurface7_UpdateOverlay( src_surface, src_rect, dst_surface, dst_rect, flags, &ddofx );
+ }
+ else
+ {
+ Error( 0, "IDirectDrawSurface7_UpdateOverlay : error %i", result );
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+// Copy our off screen surface into our primary
+// surface. This funtion is only used when a
+// h/w overlay of the current frame format is
+// not supported.
+
+boolean BltCopy( LPDIRECTDRAWSURFACE7 src_surface, RECT * src_rect,
+ LPDIRECTDRAWSURFACE7 dst_surface, RECT * dst_rect )
+{
+ DDSURFACEDESC ddsd_target;
+ HRESULT result;
+
+ memset( &ddsd_target, 0, sizeof( ddsd_target ) );
+ ddsd_target.dwSize = sizeof( ddsd_target );
+
+ // attempt to blt the surface sontents
+
+ result = IDirectDrawSurface7_Blt( dst_surface, dst_rect, src_surface, src_rect, DDBLT_WAIT, 0 );
+ if( result != DD_OK )
+ {
+ if( result != DDERR_SURFACELOST )
+ {
+ IDirectDrawSurface7_Restore( src_surface );
+ IDirectDrawSurface7_Restore( dst_surface );
+
+ IDirectDrawSurface7_Blt( dst_surface, dst_rect, src_surface, src_rect, DDBLT_WAIT, 0 );
+ }
+ else
+ {
+ Error( 0, "IDirectDrawSurface7_Blt : error %i", result );
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+// Display our current frame. This function
+// corrects frame output ratio and clipps the
+// frame if nessesary. It will then handle
+// moving the image contents contained in our
+// secondary surface to our primary surface.
+
+boolean DisplayFrame( win32_driver_t * win32_driver )
+{
+ int view_width;
+ int view_height;
+ int scaled_width;
+ int scaled_height;
+ int screen_width;
+ int screen_height;
+ RECT clipped;
+ RECT centered;
+
+ // aspect ratio calculations
+
+ // TODO : account for screen ratio as well
+
+ view_width = win32_driver->win32_visual->WndRect.right - win32_driver->win32_visual->WndRect.left;
+ view_height = win32_driver->win32_visual->WndRect.bottom - win32_driver->win32_visual->WndRect.top;
+
+ if( view_width / win32_driver->ratio < view_height )
+ {
+ scaled_width = view_width - BORDER_SIZE;
+ scaled_height = view_width / win32_driver->ratio - BORDER_SIZE;
+ }
+ else
+ {
+ scaled_width = view_height * win32_driver->ratio - BORDER_SIZE;
+ scaled_height = view_height - BORDER_SIZE;
+ }
+
+ // center our overlay in our view frame
+
+ centered.left = ( view_width - scaled_width ) / 2 + win32_driver->win32_visual->WndRect.left;
+ centered.right = centered.left + scaled_width;
+ centered.top = ( view_height - scaled_height ) / 2 + win32_driver->win32_visual->WndRect.top;
+ centered.bottom = centered.top + scaled_height;
+
+ // clip our overlay if it is off screen
+
+ screen_width = GetSystemMetrics( SM_CXSCREEN );
+ screen_height = GetSystemMetrics( SM_CYSCREEN );
+
+ if( centered.left < 0 )
+ {
+ double x_scale = ( double ) ( view_width + centered.left ) / ( double ) view_width;
+ clipped.left = win32_driver->width - ( int ) ( win32_driver->width * x_scale );
+ centered.left = 0;
+ }
+ else
+ clipped.left = 0;
+
+ if( centered.top < 0 )
+ {
+ double y_scale = ( double ) ( view_height + centered.top ) / ( double ) view_height;
+ clipped.left = win32_driver->height - ( int ) ( win32_driver->height * y_scale );
+ centered.left = 0;
+ }
+ else
+ clipped.top = 0;
+
+ if( centered.right > screen_width )
+ {
+ double x_scale = ( double ) ( view_width - ( centered.right - screen_width ) ) / ( double ) view_width;
+ clipped.right = ( int ) ( win32_driver->width * x_scale );
+ centered.right = screen_width;
+ }
+ else
+ clipped.right = win32_driver->width;
+
+ if( centered.bottom > screen_height )
+ {
+ double y_scale = ( double ) ( view_height - ( centered.bottom - screen_height ) ) / ( double ) view_height;
+ clipped.bottom = ( int ) ( win32_driver->height * y_scale );
+ centered.bottom = screen_height;
+ }
+ else
+ clipped.bottom = win32_driver->height;
+
+ // if surface is entirely off screen or the
+ // width or height is 0 for the overlay or
+ // the output view area, then return without
+ // overlay update
+
+ if( ( centered.left > screen_width ) ||
+ ( centered.top > screen_height ) ||
+ ( centered.right < 0 ) ||
+ ( centered.bottom < 0 ) ||
+ ( clipped.left >= clipped.right ) ||
+ ( clipped.top >= clipped.bottom ) ||
+ ( view_width <= 0 ) ||
+ ( view_height <= 0 ) )
+
+ return 1;
+
+ // we have a h/w supported overlay
+
+ if( ( win32_driver->act_format == XINE_IMGFMT_YV12 ) || ( win32_driver->act_format == XINE_IMGFMT_YUY2 ) )
+ return Overlay( win32_driver->secondary, &clipped, win32_driver->primary, &centered, win32_driver->win32_visual->ColorKey );
+
+ // we do not have a h/w supported overlay
+
+ return BltCopy( win32_driver->secondary, &clipped, win32_driver->primary, &centered );
+}
+
+// Lock our back buffer to update its contents.
+
+void * Lock( void * surface )
+{
+ LPDIRECTDRAWSURFACE7 lock_surface = ( LPDIRECTDRAWSURFACE7 ) surface;
+ DDSURFACEDESC2 ddsd;
+ HRESULT result;
+
+ if( !surface )
+ return 0;
+
+ memset( &ddsd, 0, sizeof( ddsd ) );
+ ddsd.dwSize = sizeof( ddsd );
+
+ result = IDirectDrawSurface7_Lock( lock_surface, 0, &ddsd, DDLOCK_WAIT | DDLOCK_NOSYSLOCK, 0 );
+ if( result == DDERR_SURFACELOST )
+ {
+ IDirectDrawSurface7_Restore( lock_surface );
+ result = IDirectDrawSurface7_Lock( lock_surface, 0, &ddsd, DDLOCK_WAIT | DDLOCK_NOSYSLOCK, 0 );
+
+ if( result != DD_OK )
+ return 0;
+
+ }
+ else if( result != DD_OK )
+ {
+ if( result == DDERR_GENERIC )
+ {
+ Error( 0, "surface->Lock : error, DDERR_GENERIC" );
+ exit( 1 );
+ }
+ }
+
+ return ddsd.lpSurface;
+
+ return 0;
+}
+
+// Unlock our back buffer to prepair for display.
+
+void Unlock( void * surface )
+{
+ LPDIRECTDRAWSURFACE7 lock_surface = ( LPDIRECTDRAWSURFACE7 ) surface;
+
+ if( !surface )
+ return;
+
+ IDirectDrawSurface7_Unlock( lock_surface, 0 );
+}
+
+// -----------------------------------------
+//
+// BEGIN : Xine driver video output plugin
+// handlers.
+//
+// -----------------------------------------
+
+static uint32_t win32_get_capabilities( vo_driver_t * vo_driver )
+{
+ uint32_t retVal;
+
+ retVal = VO_CAP_YV12 | VO_CAP_YUY2;
+
+#if RGB_SUPPORT
+ retVal |= VO_CAP_RGB;
+#endif /* RGB_SUPPORT */
+
+ return retVal;
+}
+
+static void win32_frame_field( vo_frame_t * vo_frame, int which_field )
+{
+ // I have no idea what this even
+ // does, frame interlace stuff?
+}
+
+static void win32_free_framedata(vo_frame_t* vo_frame)
+{
+
+ win32_frame_t * frame = ( win32_frame_t * ) vo_frame;
+
+ if(frame->vo_frame.base[0]) {
+ free(frame->vo_frame.base[0]);
+ frame->vo_frame.base[0] = NULL;
+ }
+
+ if(frame->vo_frame.base[1]) {
+ free(frame->vo_frame.base[1]);
+ frame->vo_frame.base[1] = NULL;
+ }
+
+ if(frame->vo_frame.base[2]) {
+ free(frame->vo_frame.base[2]);
+ frame->vo_frame.base[2] = NULL;
+ }
+}
+
+static void win32_frame_dispose( vo_frame_t * vo_frame )
+{
+ win32_frame_t * win32_frame = ( win32_frame_t * ) vo_frame;
+
+ if( win32_frame->buffer )
+ free( win32_frame->buffer );
+
+ win32_free_framedata(vo_frame);
+
+ free( win32_frame );
+}
+
+static vo_frame_t * win32_alloc_frame( vo_driver_t * vo_driver )
+{
+ win32_frame_t * win32_frame;
+
+ win32_frame = ( win32_frame_t * ) malloc( sizeof( win32_frame_t ) );
+ memset( win32_frame, 0, sizeof( win32_frame_t ) );
+
+ win32_frame->vo_frame.copy = NULL;
+ win32_frame->vo_frame.field = win32_frame_field;
+ win32_frame->vo_frame.dispose = win32_frame_dispose;
+ win32_frame->format = -1;
+
+ return ( vo_frame_t * ) win32_frame;
+}
+
+
+static void win32_update_frame_format( vo_driver_t * vo_driver, vo_frame_t * vo_frame, uint32_t width,
+ uint32_t height, int ratio_code, int format, int flags )
+{
+ win32_driver_t * win32_driver = ( win32_driver_t * ) vo_driver;
+ win32_frame_t * win32_frame = ( win32_frame_t * ) vo_frame;
+
+ /*printf("vo_out_directx : win32_update_frame_format() - width = %d, height=%d, ratio_code=%d, format=%d, flags=%d\n", width, height, ratio_code, format, flags);*/
+
+ if( ( win32_frame->format != format ) ||
+ ( win32_frame->width != width ) ||
+ ( win32_frame->height != height ) )
+ {
+ // free our allocated memory
+
+ win32_free_framedata((vo_frame_t *)&win32_frame->vo_frame);
+
+ // create new render buffer
+ if( format == XINE_IMGFMT_YV12 )
+ {
+ win32_frame->vo_frame.pitches[0] = 8*((width + 7) / 8);
+ win32_frame->vo_frame.pitches[1] = 8*((width + 15) / 16);
+ win32_frame->vo_frame.pitches[2] = 8*((width + 15) / 16);
+
+ win32_frame->vo_frame.base[0] = malloc(win32_frame->vo_frame.pitches[0] * height);
+ win32_frame->vo_frame.base[1] = malloc(win32_frame->vo_frame.pitches[1] * ((height+1)/2));
+ win32_frame->vo_frame.base[2] = malloc(win32_frame->vo_frame.pitches[2] * ((height+1)/2));
+
+ win32_frame->size = win32_frame->vo_frame.pitches[0] * height * 2;
+ }
+ else if( format == XINE_IMGFMT_YUY2 )
+ {
+ win32_frame->vo_frame.pitches[0] = 8*((width + 3) / 4);
+
+ win32_frame->vo_frame.base[0] = malloc(win32_frame->vo_frame.pitches[0] * height * 2);
+ win32_frame->vo_frame.base[1] = NULL;
+ win32_frame->vo_frame.base[2] = NULL;
+
+ win32_frame->size = win32_frame->vo_frame.pitches[0] * height * 2;
+ }
+#if RGB_SUPPORT
+ else if( format == IMGFMT_RGB )
+ {
+ win32_frame->size = width * height * 3;
+ win32_frame->buffer = malloc( win32_frame->size );
+ vo_frame->base[0] = win32_frame->buffer;
+ }
+#endif
+ else
+ {
+ printf ( "vo_out_directx : !!! unsupported image format %04x !!!\n", format );
+ exit (1);
+ }
+
+ win32_frame->format = format;
+ win32_frame->width = width;
+ win32_frame->height = height;
+ win32_frame->rcode = ratio_code;
+ }
+}
+
+static void win32_display_frame( vo_driver_t * vo_driver, vo_frame_t * vo_frame )
+{
+ win32_driver_t * win32_driver = ( win32_driver_t * ) vo_driver;
+ win32_frame_t * win32_frame = ( win32_frame_t * ) vo_frame;
+ int offset;
+ int size;
+
+ // if the required width, height or format has changed
+ // then recreate the secondary buffer
+
+ if( ( win32_driver->req_format != win32_frame->format ) ||
+ ( win32_driver->width != win32_frame->width ) ||
+ ( win32_driver->height != win32_frame->height ) )
+ {
+ CreateSecondary( win32_driver, win32_frame->width, win32_frame->height, win32_frame->format );
+ }
+
+ // determine desired ratio
+
+ switch( win32_frame->rcode )
+ {
+ case ASPECT_ANAMORPHIC:
+ win32_driver->ratio = 16.0 / 9.0;
+ break;
+
+ case ASPECT_DVB:
+ win32_driver->ratio = 2.0 / 1.0;
+ break;
+
+ case ASPECT_SQUARE:
+ win32_driver->ratio = win32_frame->width / win32_frame->height;
+ break;
+
+ case ASPECT_FULL:
+ default:
+ win32_driver->ratio = 4.0 / 3.0;
+ }
+
+ // lock our surface to update its contents
+
+ win32_driver->contents = Lock( win32_driver->secondary );
+
+ // surface unavailable, skip frame render
+
+ if( !win32_driver->contents )
+ {
+ vo_frame->displayed( vo_frame );
+ return;
+ }
+
+ // if our actual frame format is the native screen
+ // pixel format, we need to convert it
+
+ if( win32_driver->act_format == IMGFMT_NATIVE )
+ {
+ // use the software color conversion functions
+ // to rebuild the frame in our native screen
+ // pixel format ... this is slow
+
+ if( win32_driver->req_format == XINE_IMGFMT_YV12 )
+ {
+ // convert from yv12 to native
+ // screen pixel format
+
+#if NEW_YUV
+ win32_driver->yuv2rgb->configure( win32_driver->yuv2rgb,
+ win32_driver->width, win32_driver->height,
+ win32_driver->width, win32_driver->width/2,
+ win32_driver->width, win32_driver->height,
+ win32_driver->width * win32_driver->bytespp );
+#else
+ yuv2rgb_setup( win32_driver->yuv2rgb,
+ win32_driver->width, win32_driver->height,
+ win32_driver->width, win32_driver->width/2,
+ win32_driver->width, win32_driver->height,
+ win32_driver->width * win32_driver->bytespp );
+
+#endif
+
+ win32_driver->yuv2rgb->yuv2rgb_fun( win32_driver->yuv2rgb,
+ win32_driver->contents,
+ win32_frame->vo_frame.base[0],
+ win32_frame->vo_frame.base[1],
+ win32_frame->vo_frame.base[2] );
+ }
+
+ if( win32_driver->req_format == XINE_IMGFMT_YUY2 )
+ {
+ // convert from yuy2 to native
+ // screen pixel format
+#if NEW_YUV
+ win32_driver->yuv2rgb->configure( win32_driver->yuv2rgb,
+ win32_driver->width, win32_driver->height,
+ win32_driver->width, win32_driver->width/2,
+ win32_driver->width, win32_driver->height,
+ win32_driver->width * win32_driver->bytespp );
+#else
+
+ yuv2rgb_setup( win32_driver->yuv2rgb,
+ win32_driver->width, win32_driver->height,
+ win32_driver->width, win32_driver->width/2,
+ win32_driver->width, win32_driver->height,
+ win32_driver->width * win32_driver->bytespp );
+
+#endif
+ win32_driver->yuv2rgb->yuy22rgb_fun( win32_driver->yuv2rgb,
+ win32_driver->contents,
+ win32_frame->vo_frame.base[0] );
+ }
+
+#if RGB_SUPPORT
+ if( win32_driver->req_format == IMGFMT_RGB )
+ {
+ // convert from 24 bit rgb to native
+ // screen pixel format
+
+ // TODO : rgb2rgb conversion
+ }
+#endif
+ }
+ else
+ {
+ // the actual format is identical to our
+ // stream format. we just need to copy it
+
+ switch(win32_frame->format)
+ {
+ case XINE_IMGFMT_YV12:
+ {
+ vo_frame_t *frame;
+ uint8_t *img;
+
+ frame = vo_frame;
+ img = (uint8_t *)win32_driver->contents;
+
+ offset = 0;
+ size = frame->pitches[0] * frame->height;
+ memcpy( img+offset, frame->base[0], size);
+
+ offset += size;
+ size = frame->pitches[2]* frame->height / 2;
+ memcpy( img+offset, frame->base[2], size);
+
+ offset += size;
+ size = frame->pitches[1] * frame->height / 2;
+ memcpy( img+offset, frame->base[1], size);
+ }
+ break;
+ case XINE_IMGFMT_YUY2:
+ memcpy( win32_driver->contents, win32_frame->vo_frame.base[0], win32_frame->vo_frame.pitches[0] * win32_frame->vo_frame.height * 2);
+ break;
+ default:
+ memcpy( win32_driver->contents, win32_frame->vo_frame.base[0], win32_frame->vo_frame.pitches[0] * win32_frame->vo_frame.height * 2);
+ break;
+ }
+ }
+
+ // unlock the surface
+
+ Unlock( win32_driver->secondary );
+
+ // scale, clip and display our frame
+
+ DisplayFrame( win32_driver );
+
+ // tag our frame as displayed
+ if((win32_driver->current != NULL) && (win32_driver->current != vo_frame)) {
+ vo_frame->displayed(&win32_driver->current->vo_frame);
+ }
+ win32_driver->current = vo_frame;
+}
+
+static void win32_overlay_blend( vo_driver_t * vo_driver, vo_frame_t * vo_frame, vo_overlay_t * vo_overlay )
+{
+ win32_frame_t * win32_frame = ( win32_frame_t * ) vo_frame;
+
+ // temporary overlay support, somthing more appropriate
+ // for win32 will be devised at a later date
+
+ if( vo_overlay->rle )
+ {
+ if( vo_frame->format == XINE_IMGFMT_YV12 )
+ blend_yuv( win32_frame->vo_frame.base, vo_overlay, win32_frame->width, win32_frame->height, win32_frame->vo_frame.pitches );
+ else
+ blend_yuy2( win32_frame->vo_frame.base[0], vo_overlay, win32_frame->width, win32_frame->height, win32_frame->vo_frame.pitches[0] );
+ }
+}
+
+static int win32_get_property( vo_driver_t * vo_driver, int property )
+{
+#ifdef LOG
+ printf( "win32_get_property\n" );
+#endif
+
+ return 0;
+}
+
+static int win32_set_property( vo_driver_t * vo_driver, int property, int value )
+{
+ return value;
+}
+
+static void win32_get_property_min_max( vo_driver_t * vo_driver, int property, int * min, int * max )
+{
+ *min = 0;
+ *max = 0;
+}
+
+static int win32_gui_data_exchange( vo_driver_t * vo_driver, int data_type, void * data )
+{
+ win32_driver_t * win32_driver = ( win32_driver_t * ) vo_driver;
+
+ switch( data_type )
+ {
+ case GUI_WIN32_MOVED_OR_RESIZED:
+ UpdateRect( win32_driver->win32_visual );
+ DisplayFrame( win32_driver );
+ break;
+ }
+
+ return 0;
+}
+
+
+static int win32_redraw_needed(vo_driver_t* this_gen)
+{
+ win32_driver_t* win32_driver = (win32_driver_t *) this_gen;
+
+ int ret = 0;
+
+ /* TC - May need to revisit this! */
+#ifdef TC
+ if( vo_scale_redraw_needed( &win32_driver->sc ) ) {
+ win32_gui_data_exchange(this_gen, GUI_WIN32_MOVED_OR_RESIZED, 0);
+ ret = 1;
+ }
+#endif
+
+ return ret;
+}
+
+static void win32_exit( vo_driver_t * vo_driver )
+{
+ win32_driver_t * win32_driver = ( win32_driver_t * ) vo_driver;
+
+ free(win32_driver->win32_visual);
+
+ Destroy( win32_driver );
+}
+
+static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *win32_visual)
+/*vo_driver_t *init_video_out_plugin( config_values_t * config, void * win32_visual )*/
+{
+
+ /* Make sure that the DirectX drivers are available and present! */
+ /* Not complete yet */
+
+ win32_driver_t * win32_driver = ( win32_driver_t * ) malloc ( sizeof( win32_driver_t ) );
+ memset( win32_driver, 0, sizeof( win32_driver_t ) );
+
+ win32_driver->win32_visual = win32_visual;
+ win32_driver->vo_driver.get_capabilities = win32_get_capabilities;
+ win32_driver->vo_driver.alloc_frame = win32_alloc_frame ;
+ win32_driver->vo_driver.update_frame_format = win32_update_frame_format;
+ win32_driver->vo_driver.display_frame = win32_display_frame;
+ win32_driver->vo_driver.overlay_blend = win32_overlay_blend;
+ win32_driver->vo_driver.get_property = win32_get_property;
+ win32_driver->vo_driver.set_property = win32_set_property;
+ win32_driver->vo_driver.get_property_min_max = win32_get_property_min_max;
+ win32_driver->vo_driver.gui_data_exchange = win32_gui_data_exchange;
+ win32_driver->vo_driver.dispose = win32_exit;
+ win32_driver->vo_driver.redraw_needed = win32_redraw_needed;
+
+ CreatePrimary( win32_driver );
+ if( !CheckPixelFormat( win32_driver ) )
+ {
+ Error( 0, "vo_directx : Your screen pixel format is not supported" );
+ Destroy( win32_driver );
+ return 0;
+ }
+
+#if (NEW_YUV)
+ win32_driver->yuv2rgb_factory = yuv2rgb_factory_init( win32_driver->mode, 0, 0 );
+ win32_driver->yuv2rgb = win32_driver->yuv2rgb_factory->create_converter(win32_driver->yuv2rgb_factory);
+#else
+ win32_driver->yuv2rgb = yuv2rgb_init( win32_driver->mode, 0, 0 );
+#endif
+
+ return ( vo_driver_t * ) win32_driver;
+}
+
+
+static char* get_identifier (video_driver_class_t *this_gen) {
+ return "DirectX";
+}
+
+static char* get_description (video_driver_class_t *this_gen) {
+ return _("xine video output plugin for win32 using directx");
+}
+
+static void dispose_class (video_driver_class_t *this_gen) {
+
+ directx_class_t *directx = (directx_class_t *) this_gen;
+ free (directx);
+}
+
+static void *init_class (xine_t *xine, void *visual_gen) {
+
+ directx_class_t *directx;
+ char* device_name;
+
+#ifdef TC
+ int fd;
+#endif
+
+ device_name = xine->config->register_string(xine->config,
+ "video.directx_device", "/dev/directx",
+ _("xine video output plugin for win32 using directx"),
+ NULL, 10, NULL, NULL);
+
+#ifdef TC
+ /* check for directx device */
+ if((fd = open(device_name, O_RDWR)) < 0) {
+ printf("video_out_directx: aborting. (unable to open directx device \"%s\")\n", device_name);
+ return NULL;
+ }
+ close(fd);
+#endif
+
+ /*
+ * from this point on, nothing should go wrong anymore
+ */
+ directx = (directx_class_t *) malloc (sizeof (directx_class_t));
+ memset( directx, 0, sizeof( directx_class_t ) );
+
+ directx->driver_class.open_plugin = open_plugin;
+ directx->driver_class.get_identifier = get_identifier;
+ directx->driver_class.get_description = get_description;
+ directx->driver_class.dispose = dispose_class;
+
+ directx->config = xine->config;
+ directx->device_name = device_name;
+
+ return directx;
+}
+
+static vo_info_t vo_info_win32 = {
+ 7, /* priority */
+ XINE_VISUAL_TYPE_WIN32 /* visual type */
+};
+
+/*
+ * exported plugin catalog entry
+ */
+
+plugin_info_t xine_plugin_info[] = {
+ /* type, API, "name", version, special_info, init_function */
+ { PLUGIN_VIDEO_OUT, 14, "vo_directx", XINE_VERSION_CODE, &vo_info_win32, init_class },
+ { PLUGIN_NONE, 0, "", 0, NULL, NULL }
+};
+
+vo_info_t * get_video_out_plugin_info()
+{
+ return &vo_info_win32;
+}
diff --git a/src/video_out/video_out_win32.h b/src/video_out/video_out_win32.h
new file mode 100755
index 000000000..0cf51094e
--- /dev/null
+++ b/src/video_out/video_out_win32.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2000-2001 the xine project
+ *
+ * This file is part of xine, a unix video player.
+ *
+ * xine 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.
+ *
+ * xine 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * $Id: video_out_win32.h,v 1.1 2003/04/22 20:09:39 tchamp Exp $
+ *
+ * structs and defines specific to all win32 related output plugins
+ * (any win32 base xine ui should include this)
+ */
+
+#include <windows.h>
+#include <windowsx.h>
+#include "inttypes.h"
+
+#include "vo_scale.h"
+
+#ifndef HAVE_VIDEO_OUT_WIN32_H
+#define HAVE_VIDEO_OUT_WIN32_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * this is the visual data struct any win32 gui should supply
+ * (pass this to init_video_out_plugin or the xine_load_video_output_plugin
+ * utility function)
+ */
+
+typedef struct {
+
+ HWND WndHnd; /* handle of window associated with primary surface */
+ HINSTANCE HInst; /* handle of windows application instance */
+ RECT WndRect; /* rect of window client points translated to screen cooridnates */
+ boolean FullScreen; /* is window fullscreen */
+ HBRUSH Brush; /* window brush for background color */
+ COLORREF ColorKey; /* window brush color key */
+ vo_scale_t vs;
+
+} win32_visual_t;
+
+/*
+ * constants for gui_data_exchange's data_type parameter
+ */
+
+#define GUI_WIN32_MOVED_OR_RESIZED 0
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif