Merge pull request #123 from gameblabla/diablofix_hack
[pcsx_rearmed.git] / plugins / dfsound / oss.c
index b2685fb..6b1cb4a 100644 (file)
  *                                                                         *
  ***************************************************************************/
 
-#include "stdafx.h"
-
-#define _IN_OSS
-
-#include "externals.h"
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <sys/soundcard.h>
+#include "out.h"
 
 ////////////////////////////////////////////////////////////////////////
 // oss globals
@@ -30,6 +34,9 @@
 
 #define OSS_SPEED_44100     44100
 
+#define FRAGMENT_SHIFT 12
+#define FRAGMENT_SIZE  (1 << FRAGMENT_SHIFT)
+
 static int oss_audio_fd = -1;
 extern int errno;
 
@@ -37,12 +44,11 @@ extern int errno;
 // SETUP SOUND
 ////////////////////////////////////////////////////////////////////////
 
-void SetupSound(void)
+static int oss_init(void)
 {
  int pspeed=44100;
  int pstereo;
  int format;
- int fragsize = 0;
  int myfrag;
  int oss_speed, oss_stereo;
 
@@ -52,26 +58,25 @@ void SetupSound(void)
 
  if((oss_audio_fd=open("/dev/dsp",O_WRONLY,0))==-1)
   {
-   printf("Sound device not available!\n");
-   return;
+   printf("OSS device not available\n");
+   return -1;
   }
 
  if(ioctl(oss_audio_fd,SNDCTL_DSP_RESET,0)==-1)
   {
    printf("Sound reset failed\n");
-   return;
+   return -1;
   }
 
  // we use 64 fragments with 1024 bytes each
  // rearmed: now using 10*4096 for better latency
 
- fragsize=12;
- myfrag=(10<<16)|fragsize;
+ myfrag = (10<<16) | FRAGMENT_SHIFT;
 
  if(ioctl(oss_audio_fd,SNDCTL_DSP_SETFRAGMENT,&myfrag)==-1)
   {
    printf("Sound set fragment failed!\n");
-   return;        
+   return -1;
   }
 
  format = AFMT_S16_NE;
@@ -79,39 +84,41 @@ void SetupSound(void)
  if(ioctl(oss_audio_fd,SNDCTL_DSP_SETFMT,&format) == -1)
   {
    printf("Sound format not supported!\n");
-   return;
+   return -1;
   }
 
  if(format!=AFMT_S16_NE)
   {
    printf("Sound format not supported!\n");
-   return;
+   return -1;
   }
 
  if(ioctl(oss_audio_fd,SNDCTL_DSP_STEREO,&oss_stereo)==-1 || !oss_stereo)
   {
    printf("Stereo mode not supported!\n");
-   return;
+   return -1;
   }
 
  if(ioctl(oss_audio_fd,SNDCTL_DSP_SPEED,&oss_speed)==-1)
   {
    printf("Sound frequency not supported\n");
-   return;
+   return -1;
   }
 
  if(oss_speed!=pspeed)
   {
    printf("Sound frequency not supported\n");
-   return;
+   return -1;
   }
+
+ return 0;
 }
 
 ////////////////////////////////////////////////////////////////////////
 // REMOVE SOUND
 ////////////////////////////////////////////////////////////////////////
 
-void RemoveSound(void)
+static void oss_finish(void)
 {
  if(oss_audio_fd != -1 )
   {
@@ -121,21 +128,21 @@ void RemoveSound(void)
 }
 
 ////////////////////////////////////////////////////////////////////////
-// GET BYTES BUFFERED
+// GET BUFFERED STATUS
 ////////////////////////////////////////////////////////////////////////
 
-unsigned long SoundGetBytesBuffered(void)
+static int oss_busy(void)
 {
  audio_buf_info info;
  unsigned long l;
 
- if(oss_audio_fd == -1) return SOUNDSIZE;
+ if(oss_audio_fd == -1) return 1;
  if(ioctl(oss_audio_fd,SNDCTL_DSP_GETOSPACE,&info)==-1)
   l=0;
  else
   {
    if(info.fragments<(info.fragstotal>>1))             // can we write in at least the half of fragments?
-        l=SOUNDSIZE;                                   // -> no? wait
+        l=1;                                           // -> no? wait
    else l=0;                                           // -> else go on
   }
 
@@ -146,8 +153,37 @@ unsigned long SoundGetBytesBuffered(void)
 // FEED SOUND DATA
 ////////////////////////////////////////////////////////////////////////
 
-void SoundFeedStreamData(unsigned char* pSound,long lBytes)
+static void oss_feed(void *buf, int bytes)
 {
+ audio_buf_info info;
+ char sbuf[4096];
+
  if(oss_audio_fd == -1) return;
- write(oss_audio_fd,pSound,lBytes);
+ if(ioctl(oss_audio_fd,SNDCTL_DSP_GETOSPACE,&info)==0)
+  {
+   // for fast forward
+   if(bytes > info.fragments * FRAGMENT_SIZE)
+    bytes = info.fragments * FRAGMENT_SIZE;
+   if(bytes == 0)
+    return;
+
+   if(info.fragments==info.fragstotal)
+    {
+     memset(sbuf, 0, sizeof(sbuf));
+     write(oss_audio_fd, sbuf, sizeof(sbuf));
+     write(oss_audio_fd, sbuf, sizeof(sbuf));
+     write(oss_audio_fd, sbuf, sizeof(sbuf));
+    }
+  }
+
+ write(oss_audio_fd, buf, bytes);
+}
+
+void out_register_oss(struct out_driver *drv)
+{
+       drv->name = "oss";
+       drv->init = oss_init;
+       drv->finish = oss_finish;
+       drv->busy = oss_busy;
+       drv->feed = oss_feed;
 }