r827: Fix a crash when no audio output device can be opened.
[cinelerra_cv.git] / cinelerra / audiodevice.C
blob0e47e84db0716825d21e07d7144bca8ae0f8f0cf
1 #ifdef HAVE_FIREWIRE
2 #include "audio1394.h"
3 #endif
4 #include "audioalsa.h"
5 #include "audiodevice.h"
6 #include "audioesound.h"
7 #include "audiooss.h"
8 #include "condition.h"
9 #include "dcoffset.h"
10 #include "mutex.h"
11 #include "playbackconfig.h"
12 #include "preferences.h"
13 #include "recordconfig.h"
14 #include "sema.h"
18 AudioLowLevel::AudioLowLevel(AudioDevice *device)
20         this->device = device;
23 AudioLowLevel::~AudioLowLevel()
32 AudioDevice::AudioDevice()
33  : Thread(1, 0, 0)
35         initialize();
36         this->out_config = new AudioOutConfig(0);
37         this->in_config = new AudioInConfig;
38         this->vconfig = new VideoInConfig;
39         startup_lock = new Condition(0, "AudioDevice::startup_lock");
40         duplex_lock = new Condition(0, "AudioDevice::duplex_lock");
41         timer_lock = new Mutex("AudioDevice::timer_lock");
42         for(int i = 0; i < TOTAL_BUFFERS; i++)
43         {
44                 play_lock[i] = new Sema(0, "AudioDevice::play_lock");
45                 arm_lock[i] = new Sema(1, "AudioDevice::arm_lock");
46         }
47         dc_offset_thread = new DC_Offset;
50 AudioDevice::~AudioDevice()
52         delete out_config;
53         delete in_config;
54         delete vconfig;
55         delete startup_lock;
56         delete duplex_lock;
57         delete timer_lock;
58         for(int i = 0; i < TOTAL_BUFFERS; i++)
59         {
60                 delete play_lock[i];
61                 delete arm_lock[i];
62         }
63         delete dc_offset_thread;
66 int AudioDevice::initialize()
68         record_before_play = 0;
69         r = w = d = 0;
71         for(int i = 0; i < TOTAL_BUFFERS; i++)
72         {
73                 buffer[i] = 0;
74                 buffer_size[i] = 0;
75                 last_buffer[i] = 0;
76         }
78         input_buffer = 0;
79         duplex_init = 0;
80         rec_dither = play_dither = 0;
81         software_position_info = 0;
82         arm_buffer_num = 0;
83         is_playing_back = 0;
84         is_recording = 0;
85         last_buffer_size = total_samples = position_correction = 0;
86         last_position = 0;
87         interrupt = 0;
88         lowlevel_in = lowlevel_out = lowlevel_duplex = 0;
89         vdevice = 0;
90         sharing = 0;
91         total_samples_read = 0;
92         out_realtime = 0;
93         duplex_realtime = 0;
94         return 0;
97 int AudioDevice::create_lowlevel(AudioLowLevel* &lowlevel, int driver)
99         this->driver = driver;
102         if(!lowlevel)
103         {
104                 switch(driver)
105                 {
106 #ifdef HAVE_OSS
107                         case AUDIO_OSS:
108                         case AUDIO_OSS_ENVY24:
109                                 lowlevel = new AudioOSS(this);
110                                 break;
111 #endif
113 #ifdef HAVE_ESOUND
114                         case AUDIO_ESOUND:
115                                 lowlevel = new AudioESound(this);
116                                 break;
117 #endif
118                         case AUDIO_NAS:
119                                 break;
121 #ifdef HAVE_ALSA
122                         case AUDIO_ALSA:
123                                 lowlevel = new AudioALSA(this);
124                                 break;
125 #endif
127 #ifdef HAVE_FIREWIRE    
128                         case AUDIO_1394:
129                         case AUDIO_DV1394:
130                         case AUDIO_IEC61883:
131                                 lowlevel = new Audio1394(this);
132                                 break;
133 #endif
134                 }
135         }
136         return 0;
139 int AudioDevice::open_input(AudioInConfig *config, 
140         VideoInConfig *vconfig, 
141         int rate, 
142         int samples)
144         r = 1;
145         duplex_init = 0;
146         this->in_config->copy_from(config);
147         this->vconfig->copy_from(vconfig);
148 //printf("AudioDevice::open_input %s\n", this->in_config->oss_in_device[0]);
149         in_samplerate = rate;
150         in_samples = samples;
151         create_lowlevel(lowlevel_in, config->driver);
152         lowlevel_in->open_input();
153         record_timer.update();
154         return 0;
157 int AudioDevice::open_output(AudioOutConfig *config, 
158         int rate, 
159         int samples, 
160         int realtime)
162         w = 1;
163         duplex_init = 0;
164         *this->out_config = *config;
165         out_samplerate = rate;
166         out_samples = samples;
167         out_realtime = realtime;
168         create_lowlevel(lowlevel_out, config->driver);
169         return lowlevel_out == 0 || lowlevel_out->open_output();
172 int AudioDevice::open_duplex(AudioOutConfig *out_config, int rate, int samples, int realtime)
174         d = 1;
175         duplex_init = 1;        // notify playback routines to test the duplex lock
176         *this->out_config = *out_config;
177         duplex_samplerate = rate;
178         duplex_samples = samples;
179         duplex_channels = 0;
180         duplex_realtime = realtime;
181         for(int i = 0; i < MAXDEVICES; i++)
182         {
183                 duplex_channels += out_config->oss_out_channels[i];
184         }
185         create_lowlevel(lowlevel_duplex, out_config->driver);
186         lowlevel_duplex->open_duplex();
187         playback_timer.update();
188         record_timer.update();
189         return 0;
193 int AudioDevice::interrupt_crash()
195         if(lowlevel_in) return lowlevel_in->interrupt_crash();
196         return 0;
200 int AudioDevice::close_all()
202         if(lowlevel_in) lowlevel_in->close_all();
203         if(lowlevel_out) lowlevel_out->close_all();
204         if(lowlevel_duplex) lowlevel_duplex->close_all();
206         reset_output();
207         if(input_buffer) 
208         {
209                 delete [] input_buffer; 
210                 input_buffer = 0; 
211         }
212         
213         is_recording = 0;
214         rec_dither = play_dither = 0;
215         software_position_info = position_correction = last_buffer_size = 0;
216         r = w = d = 0;
217         duplex_init = 0;
218         vdevice = 0;
219         sharing = 0;
221         if(lowlevel_in)
222         {
223                 delete lowlevel_in;
224                 lowlevel_in = 0;
225         }
226         if(lowlevel_out)
227         {
228                 delete lowlevel_out;
229                 lowlevel_out = 0;
230         }
231         if(lowlevel_duplex)
232         {
233                 delete lowlevel_duplex;
234                 lowlevel_duplex = 0;
235         }
236         return 0;
239 int AudioDevice::set_vdevice(VideoDevice *vdevice)
241         this->vdevice = vdevice;
242         return 0;
246 int AudioDevice::get_ichannels()
248         if(r) return in_channels;
249         else if(d) return duplex_channels;
250         else return 0;
253 int AudioDevice::get_ibits()
255         if(r) return in_bits;
256         else if(d) return duplex_bits;
257         return 0;
261 int AudioDevice::get_obits()
263         if(w) return out_bits;
264         else if(d) return duplex_bits;
265         return 0;
268 int AudioDevice::get_ochannels()
270         if(w) return out_channels;
271         else if(d) return duplex_channels;
272         return 0;
275 AudioLowLevel* AudioDevice::get_lowlevel_out()
277         if(w) return lowlevel_out;
278         else if(d) return lowlevel_duplex;
279         return 0;
282 AudioLowLevel* AudioDevice::get_lowlevel_in()
284         if(r) return lowlevel_in;
285         else if(d) return lowlevel_duplex;
286         return 0;
289 int AudioDevice::get_irate()
291         if(r) return in_samplerate;
292         else
293         if(d) return duplex_samplerate;
296 int AudioDevice::get_orealtime()
298         if(w) return out_realtime;
299         else if(d) return duplex_realtime;
300         return 0;
304 int AudioDevice::get_orate()
306         if(w) return out_samplerate;
307         else if(d) return duplex_samplerate;
308         return 0;
311 int AudioDevice::get_interrupted()
313         return interrupt;
316 int AudioDevice::get_device_buffer()
318         return device_buffer;