1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122

use {
    std::sync::{Arc, Mutex},
    self::super::{
        alsa_audio::AlsaAudioAccess,
        pulse_audio::PulseAudioAccess,
        alsa_midi::*,
    },
    crate::{
        cx::Cx,
        event::Event,
        thread::Signal,
        audio::*,
        midi::*,
        video::*,
        media_api::CxMediaApi,
    }
};

impl Cx {
    pub (crate) fn handle_media_signals(&mut self) {
        if self.os.media.audio_change.check_and_clear() {
            // alright so. if we 'failed' opening a device here
            // what do we do. we could flag our device as 'failed' on the desc
            let mut descs = self.os.media.alsa_audio().lock().unwrap().get_updated_descs();
            let descs2 = self.os.media.pulse_audio().lock().unwrap().get_updated_descs();
            descs.extend(descs2);
            self.call_event_handler(&Event::AudioDevices(AudioDevicesEvent {
                descs
            }));
        }
        if self.os.media.alsa_midi_change.check_and_clear() {
            let descs = self.os.media.alsa_midi().lock().unwrap().get_updated_descs();
            self.call_event_handler(&Event::MidiPorts(MidiPortsEvent {
                descs,
            }));
        }
    }
}

#[derive(Default)]
pub struct CxLinuxMedia {
    pub (crate) pulse_audio: Option<Arc<Mutex<PulseAudioAccess >> >,
    pub (crate) alsa_audio: Option<Arc<Mutex<AlsaAudioAccess >> >,
    pub (crate) audio_change: Signal,
    pub (crate) alsa_midi: Option<Arc<Mutex<AlsaMidiAccess >> >,
    pub (crate) alsa_midi_change: Signal,
}

impl CxLinuxMedia {
    pub fn pulse_audio(&mut self) -> Arc<Mutex<PulseAudioAccess >> {
        if self.pulse_audio.is_none() {
            self.pulse_audio = Some(PulseAudioAccess::new(self.audio_change.clone(), &self.alsa_audio().lock().unwrap()));
        }
        self.pulse_audio.as_ref().unwrap().clone()
    }
    
    pub fn alsa_audio(&mut self) -> Arc<Mutex<AlsaAudioAccess >> {
        if self.alsa_audio.is_none() {
            self.alsa_audio = Some(AlsaAudioAccess::new(self.audio_change.clone()));
        }
        self.alsa_audio.as_ref().unwrap().clone()
    }
    
    pub fn alsa_midi(&mut self) -> Arc<Mutex<AlsaMidiAccess >> {
        if self.alsa_midi.is_none() {
            self.alsa_midi = Some(AlsaMidiAccess::new(self.alsa_midi_change.clone()));
        }
        self.alsa_midi.as_ref().unwrap().clone()
    }


}

impl CxMediaApi for Cx { 
    
    fn midi_input(&mut self) -> MidiInput {
        self.os.media.alsa_midi().lock().unwrap().create_midi_input()
    }
    
    fn midi_output(&mut self) -> MidiOutput {
        MidiOutput(Some(OsMidiOutput(self.os.media.alsa_midi())))
    }
    
    fn midi_reset(&mut self) {
    }
    
    fn use_midi_inputs(&mut self, ports: &[MidiPortId]) {
        self.os.media.alsa_midi().lock().unwrap().use_midi_inputs(ports);
    }
    
    fn use_midi_outputs(&mut self, ports: &[MidiPortId]) {
        self.os.media.alsa_midi().lock().unwrap().use_midi_outputs(ports);
    }
    
    fn use_audio_inputs(&mut self, devices: &[AudioDeviceId]) {
        self.os.media.alsa_audio().lock().unwrap().use_audio_inputs(devices);
        self.os.media.pulse_audio().lock().unwrap().use_audio_inputs(devices);
    }
    
    fn use_audio_outputs(&mut self, devices: &[AudioDeviceId]) {
        self.os.media.alsa_audio().lock().unwrap().use_audio_outputs(devices);
        self.os.media.pulse_audio().lock().unwrap().use_audio_outputs(devices);
    }
    
    fn audio_output_box(&mut self, index: usize, f: AudioOutputFn){
        *self.os.media.alsa_audio().lock().unwrap().audio_output_cb[index].lock().unwrap() = Some(f);
    }
    
    fn audio_input_box(&mut self, index: usize, f: AudioInputFn){
        *self.os.media.alsa_audio().lock().unwrap().audio_input_cb[index].lock().unwrap() = Some(f);
    }    
    
    fn video_input_box(&mut self, _index: usize, _f: VideoInputFn){
    }
    
    fn use_video_input(&mut self, _inputs: &[(VideoInputId, VideoFormatId)]) {
    }
}