[xiph-commits] r3123 - in liboggplay/trunk/plugin: . audio win32

laser13 at svn.annodex.net laser13 at svn.annodex.net
Thu Jun 28 07:18:05 PDT 2007


Author: laser13
Date: 2007-06-28 07:18:05 -0700 (Thu, 28 Jun 2007)
New Revision: 3123

Modified:
   liboggplay/trunk/plugin/audio/sydney_audio_waveapi.c
   liboggplay/trunk/plugin/plugin.h
   liboggplay/trunk/plugin/plugin_gui_win32.c
   liboggplay/trunk/plugin/win32/resource.h
Log:
Win32 more or less fully functional version of the plugin GUI.

Modified: liboggplay/trunk/plugin/audio/sydney_audio_waveapi.c
===================================================================
--- liboggplay/trunk/plugin/audio/sydney_audio_waveapi.c	2007-06-28 14:15:17 UTC (rev 3122)
+++ liboggplay/trunk/plugin/audio/sydney_audio_waveapi.c	2007-06-28 14:18:05 UTC (rev 3123)
@@ -49,10 +49,8 @@
 #define DEFAULT_DEVICE_NAME "Default WAVE Device"
 #define DEFAULT_DEVICE WAVE_MAPPER
 
-#define HAS_OGGPLAY 1
+#define VERBOSE_OUTPUT 1
 
-#define VERBOSE_OUTPUT 0
-
 // INFO: if you get weird compile errors make sure there is no extra chars pass '\' 
 #if defined(VERBOSE_OUTPUT)
 #define WAVE_ERROR_VERBOSE(error, message) \
@@ -101,9 +99,6 @@
 		return SA_ERROR_NO_INIT; \
 	}
 
-#define LEFT_CHANNEL_MASK 0x0000FFFF
-#define RIGHT_CHANNEL_MASK 0xFFFF0000
-
 /* local implementation of the sa_stream_t type */
 struct sa_stream {   
   char*           deviceName;
@@ -214,43 +209,38 @@
   return status;
 }
 
-/** 
- * retrieved volume as an int in a scale from 0x0000 to 0xFFFF
- * only one value for all channels
- */
-int sa_stream_get_write_volume(sa_stream_t *s, int32_t vol[], unsigned int *n) {
-	int status;
-	DWORD volume;
-	WORD left;
-	WORD right;
+#define LEFT_CHANNEL_MASK  0x0000FFFF
+#define RIGHT_CHANNEL_MASK 0xFFFF0000
 
-	ERROR_IF_NO_INIT(s);
+/** volume in hundreths of dB*/
+int sa_stream_get_write_volume(sa_stream_t *s, int32_t vol[], unsigned int *n) {
+  WORD left;
+  WORD right;
+  DWORD volume;
   
-	status = waveOutGetVolume(s->hWaveOut, &volume);
-	HANDLE_WAVE_ERROR(status, "reading audio volume level");
+  ERROR_IF_NO_INIT(s);
 
 	left = volume & LEFT_CHANNEL_MASK;
 	right = (volume & RIGHT_CHANNEL_MASK) >> 16;
-	//printf("Volume level is on the left channel %d, on the right %d\n", left, right);	
   vol[0] = (int32_t)(left + right /2);	
 
 	return SA_SUCCESS;
 
 }
 
-/** changes volume as an int in a scale from 0x0000 to 0xFFFF*/
+/** volume in hundreths of dB*/
 int sa_stream_change_write_volume(sa_stream_t *s, const int32_t vol[], unsigned int n) {
-	int status;
-	DWORD volume;
-	WORD left;
-	WORD right;
+  WORD left;
+  WORD right;
+  DWORD volume;
+  int   status;
+
+  ERROR_IF_NO_INIT(s);
 	
-	ERROR_IF_NO_INIT(s);
-	
   volume = (DWORD)vol[0];
-	left = volume & LEFT_CHANNEL_MASK;	
-	right = left << 16;	
-	volume = right | left;	
+	left = volume & LEFT_CHANNEL_MASK;	  
+	right = left;	  
+	volume =  (left << 16) | right;	
 	
 	status = waveOutSetVolume(s->hWaveOut, volume);
 	HANDLE_WAVE_ERROR(status, "setting new audio volume level");	
@@ -266,14 +256,14 @@
 
   ERROR_IF_NO_INIT(s);
 
-  if (position != SA_POSITION_WRITE_SOFTWARE) {
+  if (position != SA_POSITION_WRITE_HARDWARE) {
     return SA_ERROR_NOT_SUPPORTED;
   }
   // request playback progress in bytes
   mm.wType = TIME_BYTES;		
 	status = waveOutGetPosition(s->hWaveOut, &mm, sizeof(MMTIME));
-  HANDLE_WAVE_ERROR(status, "reading audio buffer position");  
-  *pos = (int64_t)mm.u.cb;    
+  HANDLE_WAVE_ERROR(status, "reading audio buffer position");
+  *pos = (int64_t)mm.u.cb;
 
 	return SA_SUCCESS;
 }
@@ -370,13 +360,8 @@
   int status;
   WAVEFORMATEX wfx;    
   UINT supported = FALSE;
-
-  // some random estimations of the correct block count
-  // could be to allocate enough for 250 ms audio offset 
-  // plus extra 2 spare blocks on to of initial burst of audio samples, e.g:
-  // int blockCount = (((250 * s->rate * s->channels * sizeof(short)) / (1000 * BLOCK_SIZE)) + 2);  
+		  
   status = allocateBlocks(BLOCK_SIZE, BLOCK_COUNT, &(s->waveBlocks));  
-  
 	HANDLE_WAVE_ERROR(status, "allocating audio buffer blocks");
   
   s->waveFreeBlockCount	= BLOCK_COUNT;
@@ -389,10 +374,10 @@
   wfx.nBlockAlign		= (wfx.wBitsPerSample * wfx.nChannels) >> 3;
   wfx.nAvgBytesPerSec	= wfx.nBlockAlign * wfx.nSamplesPerSec;
 
-  supported = waveOutOpen(NULL, s->device, &wfx, (DWORD_PTR)0, (DWORD_PTR)0, 
+  supported = waveOutOpen(NULL, WAVE_MAPPER, &wfx, (DWORD_PTR)0, (DWORD_PTR)0, 
 				WAVE_FORMAT_QUERY);
   if (supported == MMSYSERR_NOERROR) { // audio device opened sucessfully 
-    status = waveOutOpen((LPHWAVEOUT)&(s->hWaveOut), s->device, &wfx, 
+    status = waveOutOpen((LPHWAVEOUT)&(s->hWaveOut), WAVE_MAPPER, &wfx, 
 	  (DWORD_PTR)waveOutProc, (DWORD_PTR)s, CALLBACK_FUNCTION);
     HANDLE_WAVE_ERROR(status, "opening audio device for playback");
 		printf("Audio device sucessfully opened\n");
@@ -425,6 +410,7 @@
   int status, i;
 
   /* FIX ME: should the loop below have a timeout option? */
+   
   /* wait for all blocks to complete */
   while(s->waveFreeBlockCount < BLOCK_COUNT)
 	  Sleep(10);
@@ -435,10 +421,11 @@
 	    status = waveOutUnprepareHeader(s->hWaveOut, &(s->waveBlocks[i]), sizeof(WAVEHDR));
       HANDLE_WAVE_ERROR(status, "closing audio device");
     }
-  }
+  }  
+
   // reseting audio device and flushing buffers
-  status = waveOutReset(s->hWaveOut);    
-  HANDLE_WAVE_ERROR(status, "resetting audio device");
+  // status = waveOutReset(s->hWaveOut);    
+  // HANDLE_WAVE_ERROR(status, "resetting audio device");
 
   freeBlocks(s->waveBlocks);
   status = waveOutClose(s->hWaveOut);    
@@ -460,25 +447,25 @@
   UINT status;
   WAVEHDR* current;	  
   int remain;
-  
+
   current = &(s->waveBlocks[s->waveCurrentBlock]);
   
-  while(bytes > 0) {  
+  while(bytes > 0) {
     /* first make sure the header we're going to use is unprepared */
     if(current->dwFlags & WHDR_PREPARED) {      
         status = waveOutUnprepareHeader(s->hWaveOut, current, sizeof(WAVEHDR));         
-        HANDLE_WAVE_ERROR(status, "preparing audio headers for writing");        
+        HANDLE_WAVE_ERROR(status, "preparing audio headers for writing");
     }
-		
-    if(bytes < (int)(BLOCK_SIZE - current->dwUser)) {							  	          
-		  memcpy(current->lpData + current->dwUser, data, bytes);      
+		  
+    if(bytes < (int)(BLOCK_SIZE - current->dwUser)) {							  	    
+		  memcpy(current->lpData + current->dwUser, data, bytes);
       current->dwUser += bytes;
       break;
     }
 	
     /* remain is even as BLOCK_SIZE and dwUser are even too */
-    remain = BLOCK_SIZE - current->dwUser;          
-  	memcpy(current->lpData + current->dwUser, data, remain);    
+    remain = BLOCK_SIZE - current->dwUser;      
+  	memcpy(current->lpData + current->dwUser, data, remain);
     bytes -= remain;
     data += remain;
 	  current->dwBufferLength = BLOCK_SIZE;
@@ -493,7 +480,8 @@
     /*
      * wait for a block to become free
      */
-    if (!(s->waveFreeBlockCount)) {      
+    while (!(s->waveFreeBlockCount)) {
+        //printf("All audio buffer blocks empty\n");        
       WaitForSingleObject(s->callbackEvent, INFINITE);
         //Sleep(10);
     }		  
@@ -506,7 +494,7 @@
 
     current = &(s->waveBlocks[s->waveCurrentBlock]);
     current->dwUser = 0;
-  }  
+  }
   return SA_SUCCESS;
 }
 

Modified: liboggplay/trunk/plugin/plugin.h
===================================================================
--- liboggplay/trunk/plugin/plugin.h	2007-06-28 14:15:17 UTC (rev 3122)
+++ liboggplay/trunk/plugin/plugin.h	2007-06-28 14:18:05 UTC (rev 3123)
@@ -120,6 +120,8 @@
   void    registerPlaylistCallback(nsILibOggCallbackNoArg *cbObj);
   void    onCMMLData(char **cmml_data, int cmml_size);
   void    onEndOfMovie();
+  void    processCrossThreadCalls();
+  semaphore                   mCrossThreadSem;
 
   // This is only public so the Windows "heartbeat" function can
   // access it. If you're not PluginCallbackProc, don't touch!
@@ -130,6 +132,7 @@
   bool    playlistIndexOk(long index) const;
   void    clearCmmlStrings();
 
+
   NPP                         mInstance;
   NPBool                      mPluginInitialised;
   NPBool                      mWindowInitialised;
@@ -147,7 +150,6 @@
   nsILibOggCallbackString   * mCmmlCallback;
   nsILibOggCallbackNoArg    * mEndPlayCallback;
   nsILibOggCallbackNoArg    * mPlaylistCallback;
-  semaphore                   mCrossThreadSem;
 
 #if defined(XP_WIN)
   bool                        mPollingStarted;

Modified: liboggplay/trunk/plugin/plugin_gui_win32.c
===================================================================
--- liboggplay/trunk/plugin/plugin_gui_win32.c	2007-06-28 14:15:17 UTC (rev 3122)
+++ liboggplay/trunk/plugin/plugin_gui_win32.c	2007-06-28 14:18:05 UTC (rev 3123)
@@ -35,6 +35,7 @@
 #include <stdio.h>
 #include <windows.h>
 #include <windowsx.h>
+#include "resource.h"
 
 #include "std_semaphore.h"
 
@@ -47,7 +48,7 @@
 #include <oggplay/oggplay_tools.h>
 
 #define OGGPLAY_FRAME_SKIP_OFFSET -30
-#define OGGPLAY_MIN_OFFSET        10
+#define OGGPLAY_MIN_OFFSET        3
 
 typedef struct {
   // window related data
@@ -60,21 +61,21 @@
   HANDLE              thread;  
   int                 shutdown_gui;
   void            *   oggplay_handle;
-  semaphore           oggplay_replace_sem;
-  semaphore           start_stop_sem;
+  semaphore           oggplay_replace_sem;  
   semaphore           playback_sem;
   semaphore           synch_sem;  
   PluginPlaybackState   playback_state;
   __int64             playback_target;  
   void            *   new_oggplay_handle;
 #ifdef USE_AUDIO
-  sa_stream_t     *   audio_handle;
-  BOOL                audio_ok;  
+  sa_stream_t     *   audio_handle;  
   BOOL        	      audio_opened;  
 #endif
   BOOL                set_to_pause;
   BOOL                finished;
-  nsPluginInstance *  plugin_instance;
+  BOOL                valid_frame;
+  nsPluginInstance *  plugin_instance;  
+  
 } PluginWindowInfo;
 
 #ifdef USE_AUDIO
@@ -129,12 +130,16 @@
     if (info->new_oggplay_handle != NULL) {      
       old_ogg_handle = info->oggplay_handle;
       info->oggplay_handle = (void *)info->new_oggplay_handle;
-      info->new_oggplay_handle = NULL;      
+      info->new_oggplay_handle = NULL;            
 #ifdef USE_AUDIO
-      if (info->audio_opened == TRUE) {        
+      if (info->audio_opened == TRUE) {
+        //printf("Closing audio in switch oggplays\n");
         close_audio(info);              
       }      
 #endif
+      if (info->playback_state == PAUSED) {
+        info->set_to_pause = TRUE;
+      }
       rv = TRUE;
     }     
     SEM_SIGNAL(info->oggplay_replace_sem);    
@@ -143,121 +148,6 @@
   return rv;
 }
 
-/**
- * \brief display_thread - main loop do the tread responsible for display 
- * \param [in] _info - PluginWindowInfo stucture 
- */
-DWORD WINAPI display_thread(void *_info) {  
-  HWND                hWnd;  
-  RECT                r;    
-  __int64             ref_time;
-  __int64             offset;
-#ifdef USE_AUDIO      
-  __int64             bytes;
-#endif  
-  PluginWindowInfo *  info = (PluginWindowInfo*)_info;    
-  
-  /* initialise variables */  
-  info->playback_target = 0;
-  ref_time = 0;
-  info->shutdown_gui = 0;  
-  hWnd = (HWND)(info->window);
-  
-  /* signal that thread has been started sucessfully */
-  SEM_SIGNAL(info->start_stop_sem);  
-  
-
-  while (!info->shutdown_gui) {                
-    // check if we should pause display
-    if (info->playback_state == PAUSED) {
-#ifdef USE_AUDIO      
-      sa_stream_pause(info->audio_handle);
-      SEM_WAIT(info->playback_sem);
-      sa_stream_resume(info->audio_handle);
-#else
-      SEM_WAIT(info->playback_sem);
-#endif
-    }        
-    
-    // check if plugin hasn't been shut down
-    if (info->shutdown_gui) {      
-      break;
-    }
-      
-   /*
-    * Do not send WM_PAINT messages while waiting for GUI to shutdown.
-    * This is asynchronous call so all calls to plugin_oggplay functions are
-    * in the GUI message processing callback.
-    */    
-    // force refresh 
-    GetClientRect(hWnd, &r);    
-    InvalidateRect(hWnd, &r, FALSE);         
-    UpdateWindow(hWnd);  
-    SEM_WAIT(info->synch_sem);       
-#ifdef USE_AUDIO      
-    if (info->audio_opened == FALSE)     
-#endif
-    {      
-      info->playback_target = oggplay_sys_time_in_ms() << 16;
-    }      
-#ifdef USE_AUDIO
-    if ((info->audio_opened == TRUE) && (info->audio_ok == TRUE)) {
-      // calculate audio playback progress based on number of audio samples played    
-      if (sa_stream_get_position(info->audio_handle, 
-              SA_POSITION_WRITE_SOFTWARE, &bytes) != SA_SUCCESS) {
-        ref_time = oggplay_sys_time_in_ms();
-      } else {
-        ref_time = (bytes * 1000 / get_audio_rate(info->oggplay_handle) / 
-                        (sizeof(short) * get_audio_channels(info->oggplay_handle)));        
-      }
-    } else 
-#endif
-    {
-      ref_time = oggplay_sys_time_in_ms();      
-    }
-    
-    /* calculate how long we should wait with processing the next frame */
-    info->playback_target += get_callback_period(info->oggplay_handle);
-    offset = (info->playback_target >> 16) - ref_time;    
-    /*printf("Playback target [%lld], reference time [%lld] and offset [%lld] : \n", 
-      (info->playback_target >> 16), ref_time, offset);*/
-    offset = (offset > 0) ? offset : OGGPLAY_MIN_OFFSET;
-   
-    // !!! check if we should skip frames here
-
-    /* try switching oggplays */
-    if (switch_oggplays(info) == TRUE) {
-      offset = 10;
-    }
-    /* Now just wait... */
-    oggplay_millisleep(offset);   
-  }
-  
-  //clean up after receiving shut gui request
-
-  if (info->shutdown_gui) {
-    info->shutdown_gui = 0;
-#ifdef USE_AUDIO          
-    if (info->audio_opened == TRUE) {
-      close_audio(info);
-    }
-#endif        
-    
-    SubclassWindow((HWND)(info->window), (WNDPROC)(info->old_wnd_proc));    
-    
-    SEM_CLOSE(info->synch_sem);    
-    SEM_CLOSE(info->start_stop_sem);  
-    SEM_CLOSE(info->oggplay_replace_sem);  
-    SEM_CLOSE(info->playback_sem); 
-    shut_oggplay(info->oggplay_handle);  
-
-    free(info);
-
-    ExitThread(0);  
-  }
-     
-  return 0;
-}
 /*!
  * \brief initialise_gui() - setup plugin gui and fill in associated structures
  * \param [in/out] _info -
@@ -292,12 +182,11 @@
   info->plugin_instance     = instance;
   /* audio and synchronisation related variables */  
   info->playback_target     = 0;  
+  info->valid_frame         = FALSE;
   info->set_to_pause        = FALSE;
-  info->finished            = FALSE;
 #ifdef USE_AUDIO  
   info->audio_opened        = FALSE;    
-  info->audio_handle        = NULL;
-  info->audio_ok            = FALSE;
+  info->audio_handle        = NULL;  
 #endif
 
   /*
@@ -312,13 +201,8 @@
   // associate window with our PliuginWindowInfo so we can access 
   // it in the window procedure
   SetWindowLongPtr((HWND)hWnd, GWL_USERDATA, (LONG)info);     
-  
+    
   /*
-   * create semaphore to use for startup / shutdown synchronisation
-   */
-  SEM_CREATE(info->start_stop_sem, 1);
-  SEM_WAIT(info->start_stop_sem);  
-  /*
    * create semaphore responsible for playback and playback pausing
    */
   SEM_CREATE(info->playback_sem, 1);
@@ -326,30 +210,47 @@
 
   SEM_CREATE(info->synch_sem, 1);
   SEM_WAIT(info->synch_sem);
-
-  info->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)display_thread, 
-          (LPVOID)info, 0, &disp_id);    
-    
+   
   /*
-   * wait for the thread to start up
-   */
-  SEM_WAIT(info->start_stop_sem);
-  
+   * start the main processing loop for the frame data processing
+   * initial timer is called with a default @ 25fps timout
+   */ 
+  SetTimer(hWnd, IDT_DISPLAY_TIMER, 40, NULL);
+
   return info;
 }
+
 /*!
  * \brief shut_gui() - clean up and shutdown plugin gui
  * \param [in/out] handle - pointer to the PluginWindowInfo structure
  * Comments: Fuction notifies the display
  * */
+
 void
 shut_gui(void *handle) {
   
-  PluginWindowInfo  * info = (PluginWindowInfo *)handle;    
-  info->shutdown_gui = 1;  
-  if (info->playback_state == PAUSED) {
-    SEM_SIGNAL(info->playback_sem);    
+  PluginWindowInfo  * info = (PluginWindowInfo *)handle;  
+  
+#ifdef USE_AUDIO          
+  if (info->audio_opened == TRUE) {
+    close_audio(info);
   }
+#endif        
+  SubclassWindow((HWND)(info->window), (WNDPROC)(info->old_wnd_proc));    
+  
+  SEM_CLOSE(info->synch_sem);      
+  SEM_CLOSE(info->oggplay_replace_sem);  
+  SEM_CLOSE(info->playback_sem); 
+  
+  shut_oggplay(info->oggplay_handle);  
+  
+  KillTimer(info->window, IDT_DISPLAY_TIMER);
+ 
+  /*if (info->frame_data != NULL) {
+    free(info->frame_data);
+  }*/
+  free(info);
+  printf("all closed all done\n");
 
   return;
 
@@ -406,6 +307,10 @@
   HDC           hdc, hdcMem;
   HBITMAP       hbmOld, hbm;
 
+  if (info->valid_frame == FALSE) {
+    return;
+  }
+
   /* display new video frame */
   hdc = BeginPaint(info->window, &ps);            
   GetClientRect(info->window, &r);      
@@ -428,8 +333,7 @@
 	//restore the initial state and clean up
 	SelectObject(hdcMem, hbmOld);
 	DeleteObject(hbm);      
-  EndPaint(info->window, &ps);  
-
+  EndPaint(info->window, &ps);
   return;
 }
 
@@ -439,14 +343,38 @@
   BOOL          has_audio = FALSE;
   BOOL          has_video = FALSE;
   BOOL          has_cmml = FALSE;
-    
-  // filter early and random *broken* WM_PAINT messages    
-  if (info == NULL) {        
-    SEM_SIGNAL(info->synch_sem);
-    return;  
-  }    
-  get_oggplay_frame(info->oggplay_handle, info->frame_data);      
-  // this has to be split 
+  HWND          hWnd; 
+  RECT          r;
+  __int64       bytes, ref_time, offset;
+
+  if ((info->playback_state == PAUSED) && (info->set_to_pause == FALSE)) {    
+      SetTimer(hWnd, IDT_DISPLAY_TIMER, OGGPLAY_MIN_OFFSET, NULL);
+      printf("Setting short timeout\n");
+      return;    
+  } 
+
+  hWnd = (HWND)(info->window);
+
+  /* check if we need to change oggplay objects */
+  switch_oggplays(info); 
+  
+  get_oggplay_frame(info->oggplay_handle, info->frame_data); 
+
+  switch (get_oggplay_stream_info(info->oggplay_handle, info->frame_data)) {
+    case OGGPLAY_STREAM_JUST_SEEKED:
+      close_audio(info);
+      break;
+
+    case OGGPLAY_STREAM_LAST_DATA:
+      info->finished = TRUE;
+      onEndOfMovie(info->plugin_instance);
+      return TRUE;
+
+    default:
+      break;
+  }
+
+  // this is split so we can skip frames as per the code in the end of that function
   convert_oggplay_frame(info->oggplay_handle, info->frame_data, BGR);  
   
   has_video = ((info->frame_data->video_data != NULL) && (info->frame_data->frame != NULL)) ? TRUE : FALSE;
@@ -456,13 +384,23 @@
   /* if there is need to update plugin GUI then go to next frame */
   if ((has_video == FALSE) && (has_audio == FALSE)
     /* && (has_cmml) */
-  ) {
-    //SEM_SIGNAL(info->synch_sem);
-    //return;
-    goto cleanup;    
+  ) {   
+    free_oggplay_frame(info->oggplay_handle, info->frame_data);
+    return;
   }
+  /* we have a valid data to be displayed */
+  info->valid_frame = TRUE;
+
   /* display frame */  
-  update_frame(info);    
+  GetClientRect(hWnd, &r);    
+  InvalidateRect(hWnd, &r, FALSE);
+  UpdateWindow(hWnd);  
+  
+  if (info->playback_state == PAUSED) {
+      info->set_to_pause = FALSE;
+  }
+  /* below: audio, timing calculations and frame skipping */
+calc_offset:
 
 #ifdef USE_AUDIO
   if (has_audio == TRUE) {    
@@ -471,18 +409,15 @@
       open_audio(info);
     }
     /* if audio device is opened try writing data */
-    if (info->audio_opened == TRUE) {
-      info->audio_ok = TRUE;      
-      if (info->frame_data->samples != NULL) {        
-      }
+    if (info->audio_opened == TRUE) {                 
       if (sa_stream_write(info->audio_handle, 
             info->frame_data->samples, 
             info->frame_data->size) != SA_SUCCESS) {
+        //printf("Closing audio on faulty write\n");
         close_audio(info);
-        info->playback_target = 0;
-        info->audio_ok = FALSE;        
-      }      
-    }
+        info->playback_target = 0;              
+      }
+    }   
   }  
 #endif
   
@@ -490,10 +425,49 @@
   if (has_cmml == TRUE) {    
     onCMMLData(info->plugin_instance, info->frame_data->cmml_strings, info->frame_data->cmml_size);      
   }      
-cleanup:
-  SEM_SIGNAL(info->synch_sem);  
-  // progress with decoding  
-  free_oggplay_frame(info->oggplay_handle, info->frame_data);     
+   
+#ifdef USE_AUDIO      
+  if (info->audio_opened == FALSE)     
+#endif
+  {      
+    info->playback_target = oggplay_sys_time_in_ms() << 16;
+  }      
+#ifdef USE_AUDIO
+  if (info->audio_opened == TRUE) {
+    // calculate audio playback progress based on number of audio samples played    
+    if (sa_stream_get_position(info->audio_handle, 
+            SA_POSITION_WRITE_SOFTWARE, &bytes) != SA_SUCCESS) {
+      ref_time = oggplay_sys_time_in_ms();
+    } else {
+      ref_time = (bytes * 1000 / get_audio_rate(info->oggplay_handle) / 
+                      (sizeof(short) * get_audio_channels(info->oggplay_handle)));        
+    }
+  } else 
+#endif
+  {
+    ref_time = oggplay_sys_time_in_ms();      
+  }
+  
+  /* calculate how long we should wait with processing the next frame */
+  info->playback_target += get_callback_period(info->oggplay_handle);
+  offset = (info->playback_target >> 16) - ref_time;        
+
+  free_oggplay_frame(info->oggplay_handle, info->frame_data);
+  info->valid_frame = FALSE;
+  
+  /* check if we are not lagging with display 
+  if (offset < OGGPLAY_FRAME_SKIP_OFFSET) {
+    get_oggplay_frame(info->oggplay_handle, info->frame_data);
+    goto calc_offset;
+  } else*/ 
+  if (offset < OGGPLAY_MIN_OFFSET) {
+    offset = OGGPLAY_MIN_OFFSET;
+  }  
+
+  printf("setting time for %lld milliseconds (target %lld bytes %lld\n", offset,
+    info->playback_target, bytes);
+  SetTimer(hWnd, IDT_DISPLAY_TIMER, offset, NULL);
+
   return;
 }
 
@@ -504,11 +478,20 @@
 LRESULT CALLBACK PluginWinProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
 {    
   PluginWindowInfo * info = NULL;  
+  
   switch (msg) {
-    case WM_PAINT: 
+    case WM_TIMER: 
+      printf("timer\n");
       info = (PluginWindowInfo*)GetWindowLongPtr(hWnd, GWL_USERDATA);      
-      process_frame_data(info);      
+      process_frame_data(info); 
+      printf("timed\n");
       break;    
+    case WM_PAINT:
+      printf("paint\n");
+      info = (PluginWindowInfo*)GetWindowLongPtr(hWnd, GWL_USERDATA);      
+      update_frame(info);
+      printf("painted\n");
+      break;
     case WM_CLOSE :      
       break;
     case WM_DESTROY : 
@@ -517,7 +500,7 @@
     default:
       break;
   }
-  return DefWindowProc(hWnd, msg, wParam, lParam);
+  return DefWindowProc(hWnd, msg, wParam, lParam);  
 }
 
 /*
@@ -534,8 +517,7 @@
     shut_oggplay(info->new_oggplay_handle);
   }
   info->new_oggplay_handle = oggplay_handle;
-  SEM_SIGNAL(info->oggplay_replace_sem); 
-  
+  SEM_SIGNAL(info->oggplay_replace_sem);   
 }
 
 void 
@@ -547,8 +529,7 @@
 void 
 gui_play(void *handle) {
   PluginWindowInfo  * info = (PluginWindowInfo *)handle;
-  info->playback_state = PLAYING;
-  SEM_SIGNAL(info->playback_sem);
+  info->playback_state = PLAYING;  
 }
      
 short
@@ -630,4 +611,3 @@
   }
   return height;
 }
-

Modified: liboggplay/trunk/plugin/win32/resource.h
===================================================================
--- liboggplay/trunk/plugin/win32/resource.h	2007-06-28 14:15:17 UTC (rev 3122)
+++ liboggplay/trunk/plugin/win32/resource.h	2007-06-28 14:18:05 UTC (rev 3123)
@@ -20,4 +20,6 @@
 #endif
 
 #define IDT_CALLBACK_TIMER                   12001
+#define IDT_DISPLAY_TIMER                    12002
 
+



More information about the commits mailing list