summaryrefslogtreecommitdiff
path: root/src/main.rs
blob: 38c2e78ea6ec2915f8220dca8ce1647db24c5ab4 (plain)
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
123
124
125
126
127
128
129
130
131
132
133
134
135
use std::collections::VecDeque;
use std::fs::File;
use std::io::Read;
use std::net::*;
use std::sync::*;
use std::{env, iter, thread, ffi};

extern crate portaudio;
use portaudio as pa;
use synfone::client::*;
use synfone::lang::*;
use synfone::proto::*;
use synfone::synth::*;
use synfone::*;

fn main() -> Result<(), std::io::Error> {
    let cmd = env::args_os().nth(1).expect("Please pass a command as the first argument; use `help` as a command for more information.");
    let cmds = cmd.into_string().expect("Couldn't parse command");

    let new_args: Vec<ffi::OsString> = env::args_os().skip(1).collect();

    match &*cmds {
        "help" => eprintln!("TODO! Commands are help, client."),
        "client" => main_client(new_args)?,
        _ => eprintln!("Unknown command; `help` for help."),
    }
    Ok(())
}


fn main_client(args: Vec<ffi::OsString>) -> Result<(), std::io::Error> {
    let env = Environment::default();

    let mut genfile = File::open(args.iter().nth(1).expect("Need first argument to be a file with a generator vector")).expect("Failed to open file");
    let mut genstr = String::new();
    genfile.read_to_string(&mut genstr)?;

    let gens = Parser::new(Tokenizer::new(genstr.chars()), env.clone())
        .expect("Failed to get first token")
        .parse_gen_vec()
        .expect("Failed to compile generators");
    let sock = UdpSocket::bind("0.0.0.0:13676").expect("Failed to bind socket");

    eprintln!("Parsed {} generator definitions", gens.len());

    let client = Arc::new(Mutex::new(
        Client::new(
            sock.try_clone().expect("Failed to clone socket"),
            gens,
            env.clone(),
        )
        .expect("Failed to create client"),
    ));
    let last_buffer = Arc::new(Mutex::new(<VecDeque<Sample>>::with_capacity(
        env.default_buffer_size * 9,
    )));
    let last_buffer_lim = env.default_buffer_size * 8;
    last_buffer
        .lock()
        .expect("Failed to init shared buffer")
        .append(&mut iter::repeat(0.0f32).take(last_buffer_lim).collect());

    let pa_inst = pa::PortAudio::new().expect("Failed to create PortAudio interface");
    let settings = pa_inst
        .default_output_stream_settings(1, env.sample_rate as f64, env.default_buffer_size as u32)
        .expect("Failed to instantiate stream settings");
    let mut stream;
    {
        let client = client.clone();
        let last_buffer = last_buffer.clone();
        let mut ring: VecDeque<Sample> = VecDeque::new();
        ring.reserve_exact(2 * env.default_buffer_size);
        stream = pa_inst
            .open_non_blocking_stream(
                settings,
                move |pa::OutputStreamCallbackArgs { buffer, frames, .. }| {
                    while frames > ring.len() {
                        let mut cli = client.lock().unwrap();
                        cli.next_frames();
                        {
                            let mut buf = last_buffer
                                .lock()
                                .expect("Failed to acquire shared buffer in audio callback");
                            buf.append(&mut cli.buffer().samples.iter().map(|&x| x).collect());
                            let len = buf.len();
                            if len > last_buffer_lim {
                                buf.drain(..(len - last_buffer_lim));
                            }
                        }
                        ring.append(&mut cli.buffer().iter().map(|&x| x).collect());
                    }
                    let samps = ring.drain(..frames).collect::<Vec<f32>>();
                    buffer.copy_from_slice(&samps);
                    pa::Continue
                },
            )
            .expect("Failed to create stream");
    }

    eprintln!("Starting.");

    stream.start().expect("Failed to start stream");

    eprintln!("Audio stream started.");

    let net_thread = {
        let client = client.clone();
        let net_thread = thread::spawn(move || {
            let mut buffer: [u8; Command::SIZE] = [0u8; Command::SIZE];
            loop {
                let (bytes, sender) = sock.recv_from(&mut buffer).unwrap();
                if bytes < Command::SIZE {
                    continue;
                }

                let cmd = Command::from(&buffer);
                {
                    let mut cli = client.lock().unwrap();
                    if !cli.handle_command(cmd, sender) {
                        break;
                    }
                }
            }
        });
        net_thread
    };

    eprintln!("Network thread started.");
    
    net_thread.join().expect("Network thread panicked");

    eprintln!("Exiting.");

    Ok(())
}