Mercurial > mplayer.hg
annotate libao2/ao_win32.c @ 10663:711159267b2d
clean up field flags:
1) cosmetic change, no reason these need to be mpeg2-specific
2) add a flag to tell when fields are ordered, so we don't have to
assume bff (which would usually be wrong) when field flags are not
available.
3) add other flags for future use :)
author | rfelker |
---|---|
date | Mon, 18 Aug 2003 14:49:06 +0000 |
parents | b5b7b2f4f069 |
children | 6e580b901205 |
rev | line source |
---|---|
7913 | 1 /****************************************************************************** |
2 * ao_win32.c: Windows waveOut interface for MPlayer | |
3 * Copyright (c) 2002 Sascha Sommer <saschasommer@freenet.de>. | |
4 * | |
5 * This program is free software; you can redistribute it and/or modify | |
6 * it under the terms of the GNU General Public License as published by | |
7 * the Free Software Foundation; either version 2 of the License, or | |
8 * (at your option) any later version. | |
9 * | |
10 * This program is distributed in the hope that it will be useful, | |
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 * GNU General Public License for more details. | |
14 * | |
15 * You should have received a copy of the GNU General Public License | |
16 * along with this program; if not, write to the Free Software | |
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. | |
18 * | |
19 *****************************************************************************/ | |
20 | |
21 #include <stdio.h> | |
22 #include <stdlib.h> | |
23 #include <windows.h> | |
24 #include <mmsystem.h> | |
25 | |
26 #include "afmt.h" | |
27 #include "audio_out.h" | |
28 #include "audio_out_internal.h" | |
29 #include "../mp_msg.h" | |
30 #include "../libvo/fastmemcpy.h" | |
31 | |
32 #define SAMPLESIZE 1024 | |
33 #define BUFFER_SIZE 4096 | |
34 #define BUFFER_COUNT 16 | |
35 | |
36 | |
37 static WAVEHDR* waveBlocks; //pointer to our ringbuffer memory | |
38 static HWAVEOUT hWaveOut; //handle to the waveout device | |
39 static DWORD restoredvolume; //saves the volume to restore after playing | |
40 static unsigned int buf_write=0; | |
41 static unsigned int buf_write_pos=0; | |
42 static int full_buffers=0; | |
43 static int buffered_bytes=0; | |
44 | |
45 | |
46 static ao_info_t info = | |
47 { | |
48 "Windows waveOut audio output", | |
49 "win32", | |
50 "Sascha Sommer <saschasommer@freenet.de>", | |
51 "" | |
52 }; | |
53 | |
54 LIBAO_EXTERN(win32) | |
55 | |
56 static void CALLBACK waveOutProc(HWAVEOUT hWaveOut,UINT uMsg,DWORD dwInstance, | |
57 DWORD dwParam1,DWORD dwParam2) | |
58 { | |
59 if(uMsg != WOM_DONE) | |
60 return; | |
61 if(full_buffers==0) return; //no more data buffered! | |
8657 | 62 buffered_bytes-=BUFFER_SIZE; |
7913 | 63 --full_buffers; |
64 } | |
65 | |
66 // to set/get/query special features/parameters | |
9633
12b1790038b0
64bit libao2 fix by Jens Axboe <mplayer-dev@kernel.dk>
alex
parents:
9589
diff
changeset
|
67 static int control(int cmd,void *arg) |
7913 | 68 { |
69 DWORD volume; | |
70 switch (cmd) | |
71 { | |
72 case AOCONTROL_GET_VOLUME: | |
73 { | |
74 ao_control_vol_t* vol = (ao_control_vol_t*)arg; | |
75 waveOutGetVolume(hWaveOut,&volume); | |
76 vol->left = (float)(LOWORD(volume)/655.35); | |
77 vol->right = (float)(HIWORD(volume)/655.35); | |
78 mp_msg(MSGT_AO, MSGL_DBG2,"ao_win32: volume left:%f volume right:%f\n",vol->left,vol->right); | |
79 return CONTROL_OK; | |
80 } | |
81 case AOCONTROL_SET_VOLUME: | |
82 { | |
83 ao_control_vol_t* vol = (ao_control_vol_t*)arg; | |
84 volume = MAKELONG(vol->left*655.35,vol->right*655.35); | |
85 waveOutSetVolume(hWaveOut,volume); | |
86 return CONTROL_OK; | |
87 } | |
88 } | |
89 return -1; | |
90 } | |
91 | |
92 // open & setup audio device | |
93 // return: 1=success 0=fail | |
94 static int init(int rate,int channels,int format,int flags) | |
95 { | |
96 WAVEFORMATEX wformat; | |
97 DWORD totalBufferSize = (BUFFER_SIZE + sizeof(WAVEHDR)) * BUFFER_COUNT; | |
98 MMRESULT result; | |
99 unsigned char* buffer; | |
100 int i; | |
101 | |
102 //fill global ao_data | |
103 ao_data.channels=channels; | |
104 ao_data.samplerate=rate; | |
105 ao_data.format=format; | |
106 ao_data.bps=channels*rate; | |
107 if(format != AFMT_U8 && format != AFMT_S8) | |
108 ao_data.bps*=2; | |
109 if(ao_data.buffersize==-1) | |
110 { | |
111 ao_data.buffersize=audio_out_format_bits(format)/8; | |
112 ao_data.buffersize*= channels; | |
113 ao_data.buffersize*= SAMPLESIZE; | |
114 } | |
115 mp_msg(MSGT_AO, MSGL_V,"ao_win32: Samplerate:%iHz Channels:%i Format:%s\n",rate, channels, audio_out_format_name(format)); | |
116 mp_msg(MSGT_AO, MSGL_V,"ao_win32: Buffersize:%d\n",ao_data.buffersize); | |
117 | |
118 //fill waveformatex | |
119 ZeroMemory( &wformat, sizeof(WAVEFORMATEX)); | |
120 wformat.cbSize = 0; /* size of _extra_ info */ | |
121 wformat.wFormatTag = WAVE_FORMAT_PCM; | |
122 wformat.nChannels = channels; | |
123 wformat.nSamplesPerSec = rate; | |
124 wformat.wBitsPerSample = audio_out_format_bits(format); | |
125 wformat.nBlockAlign = wformat.nChannels * (wformat.wBitsPerSample >> 3); | |
126 wformat.nAvgBytesPerSec = wformat.nSamplesPerSec * wformat.nBlockAlign; | |
127 | |
128 //open sound device | |
129 //WAVE_MAPPER always points to the default wave device on the system | |
130 result = waveOutOpen(&hWaveOut,WAVE_MAPPER,&wformat,(DWORD_PTR)waveOutProc,0,CALLBACK_FUNCTION); | |
131 if(result == WAVERR_BADFORMAT) | |
132 { | |
133 mp_msg(MSGT_AO, MSGL_ERR,"ao_win32: format not supported switching to default\n"); | |
134 ao_data.channels = wformat.nChannels = 2; | |
135 ao_data.samplerate = wformat.nSamplesPerSec = 44100; | |
136 ao_data.format = AFMT_S16_LE; | |
137 ao_data.bps=ao_data.channels * ao_data.samplerate; | |
138 ao_data.buffersize=wformat.wBitsPerSample=16; | |
139 wformat.nBlockAlign = wformat.nChannels * (wformat.wBitsPerSample >> 3); | |
140 wformat.nAvgBytesPerSec = wformat.nSamplesPerSec * wformat.nBlockAlign; | |
141 ao_data.buffersize/=8; | |
142 ao_data.buffersize*= ao_data.channels; | |
143 ao_data.buffersize*= SAMPLESIZE; | |
144 result = waveOutOpen(&hWaveOut,WAVE_MAPPER,&wformat,(DWORD_PTR)waveOutProc,0,CALLBACK_FUNCTION); | |
145 } | |
146 if(result != MMSYSERR_NOERROR) | |
147 { | |
148 mp_msg(MSGT_AO, MSGL_ERR,"ao_win32: unable to open wave mapper device\n"); | |
149 return 0; | |
150 } | |
151 //save volume | |
152 waveOutGetVolume(hWaveOut,&restoredvolume); | |
153 //allocate buffer memory as one big block | |
154 buffer = malloc(totalBufferSize); | |
9589 | 155 memset(buffer,0x0,totalBufferSize); |
7913 | 156 //and setup pointers to each buffer |
157 waveBlocks = (WAVEHDR*)buffer; | |
158 buffer += sizeof(WAVEHDR) * BUFFER_COUNT; | |
159 for(i = 0; i < BUFFER_COUNT; i++) { | |
160 waveBlocks[i].dwBufferLength = BUFFER_SIZE; | |
161 waveBlocks[i].lpData = buffer; | |
162 buffer += BUFFER_SIZE; | |
163 } | |
164 | |
165 return 1; | |
166 } | |
167 | |
168 // close audio device | |
169 static void uninit() | |
170 { | |
171 waveOutSetVolume(hWaveOut,restoredvolume); //restore volume | |
172 waveOutReset(hWaveOut); | |
173 waveOutClose(hWaveOut); | |
174 mp_msg(MSGT_AO, MSGL_V,"waveOut device closed\n"); | |
175 full_buffers=0; | |
176 free(waveBlocks); | |
177 mp_msg(MSGT_AO, MSGL_V,"buffer memory freed\n"); | |
178 } | |
179 | |
180 // stop playing and empty buffers (for seeking/pause) | |
181 static void reset() | |
182 { | |
183 waveOutReset(hWaveOut); | |
184 buf_write=0; | |
185 buf_write_pos=0; | |
186 full_buffers=0; | |
187 buffered_bytes=0; | |
188 } | |
189 | |
190 // stop playing, keep buffers (for pause) | |
191 static void audio_pause() | |
192 { | |
193 waveOutPause(hWaveOut); | |
194 } | |
195 | |
196 // resume playing, after audio_pause() | |
197 static void audio_resume() | |
198 { | |
199 waveOutRestart(hWaveOut); | |
200 } | |
201 | |
202 // return: how many bytes can be played without blocking | |
203 static int get_space() | |
204 { | |
205 return (BUFFER_COUNT-full_buffers)*BUFFER_SIZE - buf_write_pos; | |
206 } | |
207 | |
208 //writes data into buffer, based on ringbuffer code in ao_sdl.c | |
209 static int write_waveOutBuffer(unsigned char* data,int len){ | |
210 WAVEHDR* current; | |
211 int len2=0; | |
212 int x; | |
213 while(len>0){ | |
214 current = &waveBlocks[buf_write]; | |
215 if(full_buffers==BUFFER_COUNT) break; | |
216 //unprepare the header if it is prepared | |
217 if(current->dwFlags & WHDR_PREPARED) | |
218 waveOutUnprepareHeader(hWaveOut, current, sizeof(WAVEHDR)); | |
219 x=BUFFER_SIZE-buf_write_pos; | |
220 if(x>len) x=len; | |
221 memcpy(current->lpData+buf_write_pos,data+len2,x); | |
222 len2+=x; len-=x; | |
223 buffered_bytes+=x; buf_write_pos+=x; | |
224 //prepare header and write data to device | |
225 waveOutPrepareHeader(hWaveOut, current, sizeof(WAVEHDR)); | |
226 waveOutWrite(hWaveOut, current, sizeof(WAVEHDR)); | |
227 | |
228 if(buf_write_pos>=BUFFER_SIZE){ //buffer is full find next | |
229 // block is full, find next! | |
230 buf_write=(buf_write+1)%BUFFER_COUNT; | |
231 ++full_buffers; | |
232 buf_write_pos=0; | |
233 } | |
234 } | |
235 return len2; | |
236 } | |
237 | |
238 // plays 'len' bytes of 'data' | |
239 // it should round it down to outburst*n | |
240 // return: number of bytes played | |
241 static int play(void* data,int len,int flags) | |
242 { | |
243 return write_waveOutBuffer(data,len); | |
244 } | |
10106 | 245 |
7913 | 246 // return: delay in seconds between first and last sample in buffer |
247 static float get_delay() | |
248 { | |
249 return (float)(buffered_bytes + ao_data.buffersize)/(float)ao_data.bps; | |
250 } |