Get rid of nuppelvideo.h and its ugly packed struct and instead write the
[mplayer/glamo.git] / libao2 / ao_dxr2.c
blob7f9594fb4de26fb39b3a0fdbc6eab6c30cea8880
1 /*
2 * DXR2 audio output driver
4 * This file is part of MPlayer.
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.
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.
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.
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"
33 #include "audio_out.h"
34 #include "audio_out_internal.h"
35 #include "libaf/af_format.h"
36 #include "libmpdemux/mpeg_packetizer.h"
39 static const ao_info_t info =
41 "DXR2 audio output",
42 "dxr2",
43 "Tobias Diedrich <ranma+mplayer@tdiedrich.de>",
47 LIBAO_EXTERN(dxr2)
49 static int volume=19;
50 static int last_freq_id = -1;
51 extern int dxr2_fd;
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;
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;
80 return CONTROL_OK;
82 return CONTROL_ERROR;
84 return CONTROL_UNKNOWN;
87 static int freq=0;
88 static int freq_id=0;
90 // open & setup audio device
91 // return: 1=success 0=fail
92 static int init(int rate,int channels,int format,int flags){
94 if(dxr2_fd <= 0)
95 return 0;
97 last_freq_id = -1;
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;
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;
142 return 1;
145 // close audio device
146 static void uninit(int immed){
150 // stop playing and empty buffers (for seeking/pause)
151 static void reset(void){
155 // stop playing, keep buffers (for pause)
156 static void audio_pause(void)
158 // for now, just call reset();
159 reset();
162 // resume playing, after audio_pause()
163 static void audio_resume(void)
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;
178 static void dxr2_send_lpcm_packet(unsigned char* data,int len,int id,unsigned int timestamp,int freq_id)
180 int write_dxr2(const unsigned char *data, int len);
182 if(dxr2_fd < 0) {
183 mp_msg(MSGT_AO,MSGL_ERR,"DXR2 fd is not valid\n");
184 return;
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;
192 send_mpeg_lpcm_packet (data, len, id, timestamp, freq_id, write_dxr2);
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);
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 #ifndef WORDS_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);
215 return len;
218 // return: delay in seconds between first and last sample in buffer
219 static float get_delay(void){
221 return 0.0;