Credit Andrew - fix vorbis audio which was scratchy and ensure aging plugin does...
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / audiooss.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5  * Copyright (C) 2003-2016 Cinelerra CV contributors
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  *
21  */
22
23 #include "audioconfig.h"
24 #include "audiodevice.h"
25 #include "audiooss.h"
26 #include "clip.h"
27 #include "condition.h"
28 #include "errno.h"
29 #include "language.h"
30 #include "playbackconfig.h"
31 #include "preferences.h"
32 #include "recordconfig.h"
33 #include "mutex.h"
34
35 #include <string.h>
36
37 #ifdef HAVE_OSS
38
39 // These are only available in commercial OSS
40
41 #ifndef AFMT_S32_LE
42 #define AFMT_S32_LE      0x00001000
43 #define AFMT_S32_BE      0x00002000
44 #endif
45
46
47 // Synchronie multiple devices by using threads
48
49 OSSThread::OSSThread(AudioOSS *device)
50  : Thread(1, 0, 0)
51 {
52         rd = 0;
53         wr = 0;
54         done = 0;
55         this->device = device;
56         input_lock = new Condition(0, "OSSThread::input_lock");
57         output_lock = new Condition(1, "OSSThread::output_lock");
58         read_lock = new Condition(0, "OSSThread::read_lock");
59         write_lock = new Condition(0, "OSSThread::write_lock");
60
61         // delay / timing
62         bytes_written = 0;
63         timer = new Timer;
64         delay = 0;
65         timer_lock = new Mutex("OSSThread::timer_lock");
66         timer->update();
67 }
68
69 OSSThread::~OSSThread()
70 {
71         done = 1;
72         input_lock->unlock();
73         Thread::join();
74         delete input_lock;
75         delete output_lock;
76         delete read_lock;
77         delete write_lock;
78         delete timer_lock;
79         delete timer;
80 }
81
82 void OSSThread::run()
83 {
84 // this makes the longest (blocking) write 1024 samples
85 //  if this is not done, the video can be jerky
86         AudioDevice *audio_device = device->device;
87         int frame_size = audio_device->get_ochannels() * audio_device->get_obits()/8;
88         int maxsz = 1024*frame_size, blksz = maxsz;
89         ioctl(fd, SNDCTL_DSP_GETBLKSIZE, &blksz);
90         if( blksz > maxsz ) blksz = maxsz;
91
92         while(!done) {
93                 input_lock->lock("OSSThread::run 1");
94                 if(done) return;
95                 if(rd) {
96                         read(fd, data, bytes);
97                         read_lock->unlock();
98                 }
99                 else if(wr) {
100                         if( !bytes_written )
101                                 timer->update();
102                         int count = bytes;
103                         unsigned char *bp = data;
104                         while( count > 0 && !done ) {
105                                 Thread::enable_cancel();
106                                 int len = count>blksz ? blksz : count;
107                                 int ret = write(fd, bp, len);
108                                 Thread::disable_cancel();
109                                 if( ret < 0 ) break;
110                                 bp += ret;
111                                 count -= ret;
112                                 int delay = 0;
113                                 timer_lock->lock("OSSThread::run");
114                                 if( !ioctl(fd, SNDCTL_DSP_GETODELAY, &delay) )
115                                         this->delay = delay;
116                                 bytes_written += ret;
117                                 timer->update();
118                                 timer_lock->unlock();
119                         }
120                         write_lock->unlock();
121                 }
122                 output_lock->unlock();
123         }
124 }
125
126 void OSSThread::write_data(int fd, unsigned char *data, int bytes)
127 {
128         output_lock->lock("OSSThread::write_data");
129         wr = 1;
130         rd = 0;
131         this->data = data;
132         this->bytes = bytes;
133         this->fd = fd;
134         input_lock->unlock();
135 }
136
137 void OSSThread::read_data(int fd, unsigned char *data, int bytes)
138 {
139         output_lock->lock("OSSThread::read_data");
140         wr = 0;
141         rd = 1;
142         this->data = data;
143         this->bytes = bytes;
144         this->fd = fd;
145         input_lock->unlock();
146 }
147
148 void OSSThread::wait_read()
149 {
150         read_lock->lock("OSSThread::wait_read");
151 }
152
153 void OSSThread::wait_write()
154 {
155         write_lock->lock("OSSThread::wait_write");
156 }
157
158
159 // bytes not samples
160 int64_t OSSThread::device_position()
161 {
162         timer_lock->lock("OSSThread::device_position");
163         int64_t ret = bytes_written - delay;
164         timer_lock->unlock();
165         return ret;
166 }
167
168
169 AudioOSS::AudioOSS(AudioDevice *device)
170  : AudioLowLevel(device)
171 {
172         for(int i = 0; i < MAXDEVICES; i++) {
173                 dsp_in[i] = dsp_out[i] = -1;
174                 thread[i] = 0;
175                 data[i] = 0;
176                 data_allocated[i] = 0;
177         }
178 }
179
180 AudioOSS::~AudioOSS()
181 {
182 }
183
184 int AudioOSS::open_input()
185 {
186         device->in_bits = device->in_config->oss_in_bits;
187 // 24 bits not available in OSS
188         if(device->in_bits == 24) device->in_bits = 32;
189
190         for(int i = 0; i < MAXDEVICES; i++) {
191                 if(device->in_config->oss_enable[i]) {
192 //printf("AudioOSS::open_input 10\n");
193                         dsp_in[i] = open(device->in_config->oss_in_device[i], O_RDONLY/* | O_NDELAY*/);
194 //printf("AudioOSS::open_input 20\n");
195                         if(dsp_in[i] < 0) {
196                                 fprintf(stderr, "AudioOSS::open_input %s: %s\n",
197                                         device->in_config->oss_in_device[i], strerror(errno));
198                                 close_all();
199                                 return 1;
200                         }
201
202                         int format = get_fmt(device->in_config->oss_in_bits);
203                         int buffer_info = sizetofrag(device->in_samples,
204                                 device->get_ichannels(),
205                                 device->in_config->oss_in_bits);
206
207                         set_cloexec_flag(dsp_in[i], 1);
208
209 // For the ice1712 the buffer must be maximum or no space will be allocated.
210                         if(device->idriver == AUDIO_OSS_ENVY24)
211                                 buffer_info = 0x7fff000f;
212                         int ret = 1;
213                         if(ioctl(dsp_in[i], SNDCTL_DSP_SETFRAGMENT, &buffer_info))
214                                 fprintf(stderr, _("%s failed\n"), "SNDCTL_DSP_SETFRAGMENT");
215                         else if(ioctl(dsp_in[i], SNDCTL_DSP_SETFMT, &format) < 0)
216                                 fprintf(stderr, _("%s failed\n"), "SNDCTL_DSP_SETFMT");
217                         else {
218                                 int channels = device->get_ichannels();
219                                 if(ioctl(dsp_in[i], SNDCTL_DSP_CHANNELS, &channels) < 0)
220                                         fprintf(stderr, _("%s failed\n"), "SNDCTL_DSP_CHANNELS");
221                                 else if(ioctl(dsp_in[i], SNDCTL_DSP_SPEED, &device->in_samplerate) < 0)
222                                         fprintf(stderr, _("%s failed\n"), "SNDCTL_DSP_SPEED");
223                                 else
224                                         ret = 0;
225                         }
226                         if( ret ) {
227                                 close_all();
228                                 return ret;
229                         }
230
231                         audio_buf_info recinfo;
232                         ioctl(dsp_in[i], SNDCTL_DSP_GETISPACE, &recinfo);
233
234 //printf("AudioOSS::open_input fragments=%d fragstotal=%d fragsize=%d bytes=%d\n",
235 //      recinfo.fragments, recinfo.fragstotal, recinfo.fragsize, recinfo.bytes);
236
237                         thread[i] = new OSSThread(this);
238                         thread[i]->start();
239                 }
240         }
241         return 0;
242 }
243
244 int AudioOSS::open_output()
245 {
246         device->out_bits = device->out_config->oss_out_bits;
247 // OSS only supports 8, 16, and 32
248         if(device->out_bits == 24) device->out_bits = 32;
249
250         for(int i = 0; i < MAXDEVICES; i++) {
251                 if(device->out_config->oss_enable[i]) {
252 // Linux 2.4.18 no longer supports allocating the maximum buffer size.
253 // Need the shrink fragment size in preferences until it works.
254                         dsp_out[i] =
255                                 open(device->out_config->oss_out_device[i],
256                                         O_WRONLY /*| O_NDELAY*/);
257                         if(dsp_out[i] < 0) {
258                                 perror("AudioOSS::open_output");
259                                 close_all();
260                                 return 1;
261                         }
262
263                         int format = get_fmt(device->out_config->oss_out_bits);
264                         int buffer_info = sizetofrag(device->out_samples,
265                                 device->get_ochannels(),
266                                 device->out_config->oss_out_bits);
267
268                         set_cloexec_flag(dsp_out[i], 1);
269
270 // For the ice1712 the buffer must be maximum or no space will be allocated.
271                         if(device->odriver == AUDIO_OSS_ENVY24)
272                                 buffer_info = 0x7fff000f;
273                         int ret = 1;
274                         if(ioctl(dsp_out[i], SNDCTL_DSP_SETFRAGMENT, &buffer_info))
275                                 fprintf(stderr,"SNDCTL_DSP_SETFRAGMENT 2 failed.\n");
276                         else if(ioctl(dsp_out[i], SNDCTL_DSP_SETFMT, &format) < 0)
277                                 fprintf(stderr,"SNDCTL_DSP_SETFMT 2 failed\n");
278                         else {
279                                 int channels = device->get_ochannels();
280                                 if(ioctl(dsp_out[i], SNDCTL_DSP_CHANNELS, &channels) < 0)
281                                         fprintf(stderr,"SNDCTL_DSP_CHANNELS 2 failed\n");
282                                 else if(ioctl(dsp_out[i], SNDCTL_DSP_SPEED, &device->out_samplerate) < 0)
283                                         fprintf(stderr,"SNDCTL_DSP_SPEED 2 failed\n");
284                                 else
285                                         ret = 0;
286                         }
287                         if( ret ) {
288                                 close_all();
289                                 return ret;
290                         }
291
292                         audio_buf_info playinfo;
293                         ioctl(dsp_out[i], SNDCTL_DSP_GETOSPACE, &playinfo);
294 // printf("AudioOSS::open_output fragments=%d fragstotal=%d fragsize=%d bytes=%d\n",
295 // playinfo.fragments, playinfo.fragstotal, playinfo.fragsize, playinfo.bytes);
296                         device->device_buffer = playinfo.bytes;
297                         thread[i] = new OSSThread(this);
298                         thread[i]->start();
299                 }
300         }
301         return 0;
302 }
303
304 int AudioOSS::sizetofrag(int samples, int channels, int bits)
305 {
306         int testfrag = 2, fragsize = 1, grain = 4;
307         samples *= channels * bits / (8 * grain);
308         while(testfrag < samples) {
309                 fragsize++;
310                 testfrag *= 2;
311         }
312 //printf("AudioOSS::sizetofrag %d\n", fragsize);
313         return (grain << 16) | fragsize;
314 }
315
316 int AudioOSS::get_fmt(int bits)
317 {
318         switch(bits) {
319         case 32: return AFMT_S32_LE; break;
320         case 16: return AFMT_S16_LE; break;
321         case 8:  return AFMT_S8;  break;
322         }
323         return AFMT_S16_LE;
324 }
325
326
327 int AudioOSS::close_all()
328 {
329 //printf("AudioOSS::close_all 1\n");
330         for(int i = 0; i < MAXDEVICES; i++) {
331                 if(dsp_in[i] >= 0) {
332                         ioctl(dsp_in[i], SNDCTL_DSP_RESET, 0);
333                         close(dsp_in[i]);
334                         dsp_in[i] = -1;
335                 }
336
337                 if(dsp_out[i] >= 0) {
338 //printf("AudioOSS::close_all 2\n");
339                         ioctl(dsp_out[i], SNDCTL_DSP_RESET, 0);
340                         close(dsp_out[i]);
341                         dsp_out[i] = -1;
342                 }
343
344                 if(thread[i]) delete thread[i];
345                 if(data[i]) delete [] data[i];
346         }
347         return 0;
348 }
349
350 int AudioOSS::set_cloexec_flag(int desc, int value)
351 {
352         int oldflags = fcntl (desc, F_GETFD, 0);
353         if (oldflags < 0) return oldflags;
354         if(value != 0)
355                 oldflags |= FD_CLOEXEC;
356         else
357                 oldflags &= ~FD_CLOEXEC;
358         return fcntl(desc, F_SETFD, oldflags);
359 }
360
361 int64_t AudioOSS::device_position()
362 {
363         for (int i = 0; i < MAXDEVICES; i++) {
364                 if( thread[i] ) {
365                         int frame_size = device->get_ochannels() * device->get_obits()/8;
366                         int64_t pos = thread[i]->device_position() / frame_size;
367                         int64_t tmr = thread[i]->timer->get_scaled_difference(device->out_samplerate);
368                         return pos + tmr;
369                 }
370         }
371         count_info info;
372         if(!ioctl(get_output(0), SNDCTL_DSP_GETOPTR, &info))
373         {
374 //printf("AudioOSS::device_position %d %d %d\n", info.bytes, device->get_obits(), device->get_ochannels());
375 // workaround for ALSA OSS emulation driver's bug
376 // the problem is that if the first write to sound device was not full lenght fragment then
377 // _GETOPTR returns insanely large numbers at first moments of play
378                 if (info.bytes > 2100000000) return 0;
379                 int frame_size = device->get_ochannels() * device->get_obits()/8;
380                 return info.bytes / frame_size;
381         }
382         return 0;
383 }
384
385 int AudioOSS::interrupt_playback()
386 {
387 //printf("AudioOSS::interrupt_playback 1\n");
388         for(int i = 0; i < MAXDEVICES; i++) {
389                 if(thread[i]) {
390                         thread[i]->done = 1;
391                         thread[i]->input_lock->unlock();
392                         thread[i]->write_lock->unlock();
393                         thread[i]->cancel();
394                 }
395         }
396 //printf("AudioOSS::interrupt_playback 100\n");
397         return 0;
398 }
399
400 int64_t AudioOSS::samples_output()
401 {
402         for( int i=0; i<MAXDEVICES; ++i ) {
403                 if( thread[i] ) {
404                         int frame_size = device->get_ochannels() * device->get_obits()/8;
405                         return thread[i]->bytes_written / frame_size;
406                 }
407         }
408         return 0;
409 }
410
411 int AudioOSS::read_buffer(char *buffer, int bytes)
412 {
413         int sample_size = device->get_ibits() / 8;
414         int out_frame_size = device->get_ichannels() * sample_size;
415         int samples = bytes / out_frame_size;
416
417 //printf("AudioOSS::read_buffer 1 %d\n", bytes);
418 // Fill temp buffers
419         for(int i = 0; i < MAXDEVICES; i++) {
420                 if(thread[i]) {
421                         int in_frame_size = device->get_ichannels() * sample_size;
422
423                         if(data[i] && data_allocated[i] < bytes) {
424                                 delete [] data[i];
425                                 data[i] = 0;
426                         }
427                         if(!data[i]) {
428                                 data[i] = new unsigned char[bytes];
429                                 data_allocated[i] = bytes;
430                         }
431
432                         thread[i]->read_data(get_input(i), data[i], samples * in_frame_size);
433                 }
434         }
435
436 //printf("AudioOSS::read_buffer 1 %d\n", device->get_ibits());
437         for(int i = 0, out_channel = 0; i < MAXDEVICES; i++) {
438                 if(thread[i]) {
439                         thread[i]->wait_read();
440
441                         for(int in_channel = 0;
442                                 in_channel < device->get_ichannels();
443                                 in_channel++) {
444                                 int in_frame_size = device->get_ichannels() * sample_size;
445
446                                 for(int k = 0; k < samples; k++) {
447                                         for(int l = 0;
448                                                 l < sample_size;
449                                                 l++) {
450                                                 buffer[out_channel * sample_size + k * out_frame_size + l] =
451                                                         data[i][in_channel * sample_size + k * in_frame_size + l];
452                                         }
453                                 }
454                                 out_channel++;
455                         }
456                 }
457         }
458 //printf("AudioOSS::read_buffer 2\n");
459         return 0;
460 }
461
462 int AudioOSS::write_buffer(char *buffer, int bytes)
463 {
464         int sample_size = device->get_obits() / 8;
465         int in_frame_size = device->get_ochannels() * sample_size;
466         int samples = bytes / in_frame_size;
467
468         for(int i = 0, in_channel = 0; i < MAXDEVICES; i++) {
469                 if( thread[i] ) {
470                         int out_frame_size = device->get_ochannels() * sample_size;
471                         if(data[i] && data_allocated[i] < bytes) {
472                                 delete [] data[i];
473                                 data[i] = 0;
474                         }
475                         if(!data[i]) {
476                                 data[i] = new unsigned char[bytes];
477                                 data_allocated[i] = bytes;
478                         }
479
480                         for(int out_channel = 0;
481                                 out_channel < device->get_ochannels();
482                                 out_channel++) {
483
484                                 for(int k = 0; k < samples; k++) {
485                                         for(int l = 0; l < sample_size; l++) {
486                                                 data[i][out_channel * sample_size + k * out_frame_size + l] =
487                                                         buffer[in_channel * sample_size + k * in_frame_size + l];
488                                         }
489                                 }
490                                 in_channel++;
491                         }
492
493                         thread[i]->write_data(get_output(i), data[i], samples * out_frame_size);
494                 }
495         }
496         for(int i = 0; i < MAXDEVICES; i++) {
497                 if( thread[i] ) thread[i]->wait_write();
498         }
499         return 0;
500 }
501
502 int AudioOSS::flush_device()
503 {
504         for(int i = 0; i < MAXDEVICES; i++)
505                 if(thread[i]) ioctl(get_output(i), SNDCTL_DSP_SYNC, 0);
506         return 0;
507 }
508
509 int AudioOSS::get_output(int number)
510 {
511         return device->w ? dsp_out[number] : -1;
512 }
513
514 int AudioOSS::get_input(int number)
515 {
516         return device->r ? dsp_in[number] : -1;
517 }
518
519 #endif // HAVE_OSS