Update to MPlayer SVN rev 29473 and FFmpeg SVN rev 19572.
[vaapi:athaifas-mplayer.git] / libao2 / .svn / text-base / ao_dxr2.c.svn-base
1 /*
2  * DXR2 audio output driver
3  *
4  * This file is part of MPlayer.
5  *
6  * MPlayer is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * MPlayer is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with MPlayer; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  */
20
21 #include <math.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <sys/ioctl.h>
25 #include <inttypes.h>
26 #include <dxr2ioctl.h>
27 #include "config.h"
28 #include "mp_msg.h"
29 #include "help_mp.h"
30 #include "libavutil/common.h"
31 #include "mpbswap.h"
32
33 #include "audio_out.h"
34 #include "audio_out_internal.h"
35 #include "libaf/af_format.h"
36 #include "libmpdemux/mpeg_packetizer.h"
37
38
39 static const ao_info_t info =
40 {
41         "DXR2 audio output",
42         "dxr2",
43         "Tobias Diedrich <ranma+mplayer@tdiedrich.de>",
44         ""
45 };
46
47 LIBAO_EXTERN(dxr2)
48
49 static int volume=19;
50 static int last_freq_id = -1;
51 extern int dxr2_fd;
52
53 // to set/get/query special features/parameters
54 static int control(int cmd,void *arg){
55   switch(cmd){
56   case AOCONTROL_GET_VOLUME:
57     if(dxr2_fd > 0) {
58       ao_control_vol_t* vol = (ao_control_vol_t*)arg;
59       vol->left = vol->right = volume * 19.0 / 100.0;
60       return CONTROL_OK;
61     }
62     return CONTROL_ERROR;
63   case AOCONTROL_SET_VOLUME:
64     if(dxr2_fd > 0) {
65       dxr2_oneArg_t v;
66       float diff;
67       ao_control_vol_t* vol = (ao_control_vol_t*)arg;
68       // We need this trick because the volume stepping is often too small
69       diff = ((vol->left+vol->right) / 2 - (volume*19.0/100.0)) * 19.0 / 100.0;
70       v.arg = volume + (diff > 0 ? ceil(diff) : floor(diff));
71       if(v.arg > 19) v.arg = 19;
72       if(v.arg < 0) v.arg = 0;
73       if(v.arg != volume) {
74         volume = v.arg;
75         if( ioctl(dxr2_fd,DXR2_IOC_SET_AUDIO_VOLUME,&v) < 0) {
76           mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_DXR2_SetVolFailed,volume);
77           return CONTROL_ERROR;
78         }
79       }
80       return CONTROL_OK;
81     }
82     return CONTROL_ERROR;
83   }
84   return CONTROL_UNKNOWN;
85 }
86
87 static int freq=0;
88 static int freq_id=0;
89
90 // open & setup audio device
91 // return: 1=success 0=fail
92 static int init(int rate,int channels,int format,int flags){
93
94         if(dxr2_fd <= 0)
95           return 0;
96
97         last_freq_id = -1;
98
99         ao_data.outburst=2048;
100         ao_data.samplerate=rate;
101         ao_data.channels=channels;
102         ao_data.buffersize=2048;
103         ao_data.bps=rate*4;
104         ao_data.format=format;
105         freq=rate;
106
107         switch(rate){
108         case 48000:
109                 freq_id=DXR2_AUDIO_FREQ_48;
110                 break;
111         case 96000:
112                 freq_id=DXR2_AUDIO_FREQ_96;
113                 break;
114         case 44100:
115                 freq_id=DXR2_AUDIO_FREQ_441;
116                 break;
117         case 32000:
118                 freq_id=DXR2_AUDIO_FREQ_32;
119                 break;
120         case 22050:
121                 freq_id=DXR2_AUDIO_FREQ_2205;
122                 break;
123 #ifdef DXR2_AUDIO_FREQ_24
124         // This is not yet in the dxr2 driver CVS
125         // you can get the patch at
126         // http://www.tdiedrich.de/~ranma/patches/dxr2.pcm1723.20020513
127         case 24000:
128                 freq_id=DXR2_AUDIO_FREQ_24;
129                 break;
130         case 64000:
131                 freq_id=DXR2_AUDIO_FREQ_64;
132                 break;
133         case 88200:
134                 freq_id=DXR2_AUDIO_FREQ_882;
135                 break;
136 #endif
137         default:
138                 mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_DXR2_UnsupSamplerate,rate);
139                 return 0;
140         }
141
142         return 1;
143 }
144
145 // close audio device
146 static void uninit(int immed){
147
148 }
149
150 // stop playing and empty buffers (for seeking/pause)
151 static void reset(void){
152
153 }
154
155 // stop playing, keep buffers (for pause)
156 static void audio_pause(void)
157 {
158     // for now, just call reset();
159     reset();
160 }
161
162 // resume playing, after audio_pause()
163 static void audio_resume(void)
164 {
165 }
166
167 extern int vo_pts;
168 // return: how many bytes can be played without blocking
169 static int get_space(void){
170     float x=(float)(vo_pts-ao_data.pts)/90000.0;
171     int y;
172     if(x<=0) return 0;
173     y=freq*4*x;y/=ao_data.outburst;y*=ao_data.outburst;
174     if(y>32768) y=32768;
175     return y;
176 }
177
178 static void dxr2_send_lpcm_packet(unsigned char* data,int len,int id,unsigned int timestamp,int freq_id)
179 {
180   int write_dxr2(const unsigned char *data, int len);
181
182   if(dxr2_fd < 0) {
183     mp_msg(MSGT_AO,MSGL_ERR,"DXR2 fd is not valid\n");
184     return;
185   }
186
187   if(last_freq_id != freq_id) {
188     ioctl(dxr2_fd, DXR2_IOC_SET_AUDIO_SAMPLE_FREQUENCY, &freq_id);
189     last_freq_id = freq_id;
190   }
191
192   send_mpeg_lpcm_packet (data, len, id, timestamp, freq_id, write_dxr2);
193 }
194
195 // plays 'len' bytes of 'data'
196 // it should round it down to outburst*n
197 // return: number of bytes played
198 static int play(void* data,int len,int flags){
199   int write_dxr2(const unsigned char *data, int len);
200
201   // MPEG and AC3 don't work :-(
202     if(ao_data.format==AF_FORMAT_MPEG2)
203       send_mpeg_ps_packet (data, len, 0xC0, ao_data.pts, 2, write_dxr2);
204     else if(ao_data.format==AF_FORMAT_AC3)
205       send_mpeg_ps_packet (data, len, 0x80, ao_data.pts, 2, write_dxr2);
206     else {
207         int i;
208         //unsigned short *s=data;
209         uint16_t *s=data;
210 #if !HAVE_BIGENDIAN
211         for(i=0;i<len/2;i++) s[i] = bswap_16(s[i]);
212 #endif
213         dxr2_send_lpcm_packet(data,len,0xA0,ao_data.pts-10000,freq_id);
214     }
215     return len;
216 }
217
218 // return: delay in seconds between first and last sample in buffer
219 static float get_delay(void){
220
221     return 0.0;
222 }
223