psx_gpu: convert to UAL, load everything from context
[pcsx_rearmed.git] / plugins / dfsound / oss.c
1 /***************************************************************************
2                             oss.c  -  description
3                              -------------------
4     begin                : Wed May 15 2002
5     copyright            : (C) 2002 by Pete Bernert
6     email                : BlackDove@addcom.de
7  ***************************************************************************/
8 /***************************************************************************
9  *                                                                         *
10  *   This program is free software; you can redistribute it and/or modify  *
11  *   it under the terms of the GNU General Public License as published by  *
12  *   the Free Software Foundation; either version 2 of the License, or     *
13  *   (at your option) any later version. See also the license.txt file for *
14  *   additional informations.                                              *
15  *                                                                         *
16  ***************************************************************************/
17
18 #include <stdio.h>
19 #include <sys/types.h>
20 #include <sys/stat.h>
21 #include <fcntl.h>
22 #include <sys/ioctl.h>
23 #include <unistd.h>
24 #include <sys/soundcard.h>
25 #include "out.h"
26
27 ////////////////////////////////////////////////////////////////////////
28 // oss globals
29 ////////////////////////////////////////////////////////////////////////
30
31 #define OSS_MODE_STEREO     1
32 #define OSS_MODE_MONO       0
33
34 #define OSS_SPEED_44100     44100
35
36 static int oss_audio_fd = -1;
37 extern int errno;
38
39 ////////////////////////////////////////////////////////////////////////
40 // SETUP SOUND
41 ////////////////////////////////////////////////////////////////////////
42
43 static int oss_init(void)
44 {
45  int pspeed=44100;
46  int pstereo;
47  int format;
48  int fragsize = 0;
49  int myfrag;
50  int oss_speed, oss_stereo;
51
52  pstereo = OSS_MODE_STEREO;
53  oss_speed = pspeed;
54  oss_stereo = pstereo;
55
56  if((oss_audio_fd=open("/dev/dsp",O_WRONLY,0))==-1)
57   {
58    printf("OSS device not available\n");
59    return -1;
60   }
61
62  if(ioctl(oss_audio_fd,SNDCTL_DSP_RESET,0)==-1)
63   {
64    printf("Sound reset failed\n");
65    return -1;
66   }
67
68  // we use 64 fragments with 1024 bytes each
69  // rearmed: now using 10*4096 for better latency
70
71  fragsize=12;
72  myfrag=(10<<16)|fragsize;
73
74  if(ioctl(oss_audio_fd,SNDCTL_DSP_SETFRAGMENT,&myfrag)==-1)
75   {
76    printf("Sound set fragment failed!\n");
77    return -1;
78   }
79
80  format = AFMT_S16_NE;
81
82  if(ioctl(oss_audio_fd,SNDCTL_DSP_SETFMT,&format) == -1)
83   {
84    printf("Sound format not supported!\n");
85    return -1;
86   }
87
88  if(format!=AFMT_S16_NE)
89   {
90    printf("Sound format not supported!\n");
91    return -1;
92   }
93
94  if(ioctl(oss_audio_fd,SNDCTL_DSP_STEREO,&oss_stereo)==-1 || !oss_stereo)
95   {
96    printf("Stereo mode not supported!\n");
97    return -1;
98   }
99
100  if(ioctl(oss_audio_fd,SNDCTL_DSP_SPEED,&oss_speed)==-1)
101   {
102    printf("Sound frequency not supported\n");
103    return -1;
104   }
105
106  if(oss_speed!=pspeed)
107   {
108    printf("Sound frequency not supported\n");
109    return -1;
110   }
111
112  return 0;
113 }
114
115 ////////////////////////////////////////////////////////////////////////
116 // REMOVE SOUND
117 ////////////////////////////////////////////////////////////////////////
118
119 static void oss_finish(void)
120 {
121  if(oss_audio_fd != -1 )
122   {
123    close(oss_audio_fd);
124    oss_audio_fd = -1;
125   }
126 }
127
128 ////////////////////////////////////////////////////////////////////////
129 // GET BUFFERED STATUS
130 ////////////////////////////////////////////////////////////////////////
131
132 static int oss_busy(void)
133 {
134  audio_buf_info info;
135  unsigned long l;
136
137  if(oss_audio_fd == -1) return 1;
138  if(ioctl(oss_audio_fd,SNDCTL_DSP_GETOSPACE,&info)==-1)
139   l=0;
140  else
141   {
142    if(info.fragments<(info.fragstotal>>1))             // can we write in at least the half of fragments?
143         l=1;                                           // -> no? wait
144    else l=0;                                           // -> else go on
145   }
146
147  return l;
148 }
149
150 ////////////////////////////////////////////////////////////////////////
151 // FEED SOUND DATA
152 ////////////////////////////////////////////////////////////////////////
153
154 static void oss_feed(void *buf, int bytes)
155 {
156  if(oss_audio_fd == -1) return;
157  write(oss_audio_fd, buf, bytes);
158 }
159
160 void out_register_oss(struct out_driver *drv)
161 {
162         drv->name = "oss";
163         drv->init = oss_init;
164         drv->finish = oss_finish;
165         drv->busy = oss_busy;
166         drv->feed = oss_feed;
167 }