/*
Copyright (C) 2010-2012 Florian Jung
This file is part of flo's FM synth.
flo's FM synth is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
flo's FM synth is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with flo's FM synth. If not, see .
*/
#include
#include
#include
#include
#include "in_synth_cli.h"
#include "util.h"
#include "communication.h"
#include "globals.h"
#include "load.h"
#include "lfos.h"
#ifdef WATCHFILES
#include "watch_files.h"
#endif
using namespace std;
#define PROMPT "> "
pthread_mutex_t prog_load_mutex;
void signal_handler(int sig)
{
cout << endl << PROMPT << flush;
}
void lock_and_load_program(int prg_no, string file)
{
pthread_mutex_lock(&prog_load_mutex);
#ifdef WATCHFILES
remove_watch(prg_no);
#endif
do_request(request_t(request_t::SUSPEND_PROGRAM, prg_no));
if (load_program(file,program_settings[prg_no]))
{
cout << "success" << endl;
programfile[prg_no]=file;
#ifdef WATCHFILES
add_watch(prg_no);
#endif
}
else
cout << "failed" << endl;
for (int i=0;imaybe_reload_program(prg_no);
do_request(request_t(request_t::RESUME_PROGRAM, prg_no));
pthread_mutex_unlock(&prog_load_mutex);
}
//only use this, if you don't want the file-watches to be updated
//i.e., only when reloading a program!
void lock_and_load_program_no_watch_updates(int prg_no, string file)
{
pthread_mutex_lock(&prog_load_mutex);
do_request(request_t(request_t::SUSPEND_PROGRAM, prg_no));
if (load_program(file,program_settings[prg_no]))
{
cout << "success" << endl;
programfile[prg_no]=file;
}
else
cout << "failed" << endl;
for (int i=0;imaybe_reload_program(prg_no);
do_request(request_t(request_t::RESUME_PROGRAM, prg_no));
pthread_mutex_unlock(&prog_load_mutex);
}
void lock_and_change_lfo(int lfo_no, float freq)
{
do_request(request_t(request_t::SUSPEND_PROGRAM, -1));
uninit_lfo(lfo_no);
lfo_freq_hz[lfo_no]=freq;
init_lfo(lfo_no);
do_request(request_t(request_t::RESUME_PROGRAM, -1));
}
void do_in_synth_cli()
{
string input;
string command;
string params;
int num;
pthread_mutex_init(&prog_load_mutex, NULL);
if (signal(2,signal_handler)==SIG_ERR)
output_warning("WARNING: failed to set signal handler in the in-synth-cli. pressing ctrl+c will\n"
" kill the synth, so be careful. this is not fatal");
fatal_warnings=false;
while (cin.good())
{
cout << PROMPT << flush;
getline(cin,input);
input=trim_spaces(input);
command=trim_spaces(str_before(input,' ',input));
params=trim_spaces(str_after(input,' ',""));
if ((command=="exit") || (command=="quit"))
break;
else if (command=="reload")
{
if ((!isnum(params)) || (params==""))
cout << "error: expected program-number, found '"<=0) && (num<128))
lock_and_load_program(num, programfile[num]);
else
cout << "error: program-number must be one of 0..127" << endl;
}
}
else if (command=="load")
{
string prgstr, file;
prgstr=trim_spaces(str_before(params,' ',params));
file=trim_spaces(str_after(params,' ',""));
if ((!isnum(prgstr)) || (prgstr==""))
cout << "error: expected program-number, found '"<=0) && (num<128))
{
lock_and_load_program(num, file);
programfile[num]=file;
}
else
cout << "error: program-number must be one of 0..127" << endl;
}
}
else if (command=="panic")
{
if ((params=="") || (params=="all"))
do_request(request_t(request_t::PANIC, -1));
else if (isnum(params))
{
num=atoi(params.c_str());
if ((num>=0) && (num=0) && (num=0) && (num<128))
{
if (chanstr=="")
for (int i=0;ikill_program(num);
else
{
int num2=atoi(chanstr.c_str());
if ((num2>=0)&&(num2kill_program(num);
else
cout << "error: channel-number must be one of 0.."<=0) && (num=0)
channel[num]->set_n_voices(num2);
else
cout << "error: limit must be a positive number, zero or 'all'"<reset_controllers();
else if (isnum(params))
{
num=atoi(params.c_str());
if ((num>=0) && (numreset_controllers();
else
cout << "error: channel-number must be one of 0.."<=0) && (num=0) && (num2<128))
channel[num]->set_program(num2);
else
cout << "error: program must be one of 0..127"<=0) && (num=0) && (num2<128)))
cout << "error: controller must be one of 0..127"<=0) && (val<128)))
cout << "error: value must be one of 0..127"<set_controller(num2,val);
}
else
cout << "error: channel-number must be one of 0.."<=0) && (num=0)
channel[num]->set_portamento_time_sec(num2);
else
cout << "error: portamento time must be positive"<=0) && (numset_portamento(127);
else //off
channel[num]->set_portamento(0);
}
else
cout << "error: channel-number must be one of 0.."<=0) && (num=0) && (num2<128))
channel[num]->set_volume(num2);
else
cout << "error: volume must be one of 0..127"<=0) && (num=0) && (num2<128))
channel[num]->set_balance(num2);
else
cout << "error: balance must be one of 0..127"<=0) && (numset_hold_pedal(onstr=="on");
else
cout << "error: channel-number must be one of 0.."<=0) && (numset_sostenuto_pedal(onstr=="on");
else
cout << "error: channel-number must be one of 0.."<=0) && (numset_soft_pedal(onstr=="on");
else
cout << "error: channel-number must be one of 0.."<=0) && (numset_legato_pedal(onstr=="on");
else
cout << "error: channel-number must be one of 0.."<=0) && (num0)
lock_and_change_lfo(num,freq);
else
cout << "error: frequency must be a positive number"<=0)
{
snh_freq_hz=freq;
init_snh(); //no uninit necessary, as this only calculates an integer
//no lock necessary, as a race-condition would only cause
// the snh be calculated some times more
}
else
cout << "error: sample-and-hold-frequency must be greater than zero"<