mirror of
https://github.com/vale981/openAV-Luppp
synced 2025-03-04 08:41:39 -05:00
astyle: global restyle of codebase (fixes #153)
This to bring common fomatting to the whole project, including submissions. To format a file to this style: astyle --style=linux -t8 <file> Future patches / pull-requests should be in this format.
This commit is contained in:
parent
0020d9a672
commit
01f71ec5e4
93 changed files with 11792 additions and 11466 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -5,6 +5,7 @@ src/*.o
|
|||
luppp
|
||||
|
||||
*.zip
|
||||
*.orig
|
||||
|
||||
build/*
|
||||
buildTest/*
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -22,95 +22,94 @@
|
|||
|
||||
AudioBuffer::AudioBuffer()
|
||||
{
|
||||
ID = privateID++;
|
||||
init();
|
||||
ID = privateID++;
|
||||
init();
|
||||
}
|
||||
|
||||
AudioBuffer::AudioBuffer(unsigned long size)
|
||||
{
|
||||
// FIXME recorded buffers don't get an ID, using garbage IDs
|
||||
/// no ID assigned: it *takes* the one from the previous buffer!
|
||||
init();
|
||||
buffer.resize(size);
|
||||
// FIXME recorded buffers don't get an ID, using garbage IDs
|
||||
/// no ID assigned: it *takes* the one from the previous buffer!
|
||||
init();
|
||||
buffer.resize(size);
|
||||
}
|
||||
|
||||
|
||||
void AudioBuffer::init()
|
||||
{
|
||||
numBeats = 0;
|
||||
audioFrames = 0;
|
||||
memset( name, 0, sizeof(char)*20 );
|
||||
//sprintf( name, "%i", ID );
|
||||
numBeats = 0;
|
||||
audioFrames = 0;
|
||||
memset( name, 0, sizeof(char)*20 );
|
||||
//sprintf( name, "%i", ID );
|
||||
}
|
||||
|
||||
/// this function is used for "resizing" an exisiting buffer, and should
|
||||
/// not be called for any other reason.
|
||||
void AudioBuffer::setID(int id)
|
||||
{
|
||||
ID = id;
|
||||
ID = id;
|
||||
}
|
||||
|
||||
int AudioBuffer::getID()
|
||||
{
|
||||
return ID;
|
||||
return ID;
|
||||
}
|
||||
|
||||
void AudioBuffer::setName(const char* n)
|
||||
{
|
||||
memcpy( name, n, sizeof(char)* 19 );
|
||||
|
||||
if ( strlen(n) > 19 )
|
||||
{
|
||||
memcpy( name, n, sizeof(char)* 19 );
|
||||
|
||||
if ( strlen(n) > 19 ) {
|
||||
#ifdef DEBUG_BUFFER
|
||||
cout << "AudioBuffer setName too long, truncating." << endl;
|
||||
cout << "AudioBuffer setName too long, truncating." << endl;
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
char* AudioBuffer::getName()
|
||||
{
|
||||
return name;
|
||||
return name;
|
||||
}
|
||||
|
||||
int AudioBuffer::getBeats()
|
||||
{
|
||||
return numBeats;
|
||||
return numBeats;
|
||||
}
|
||||
|
||||
void AudioBuffer::setBeats(int b)
|
||||
{
|
||||
#ifdef DEBUG_BUFFER
|
||||
cout << "AudioBuffer now has " << b << " beats\n" << endl;
|
||||
cout << "AudioBuffer now has " << b << " beats\n" << endl;
|
||||
#endif
|
||||
numBeats = b;
|
||||
numBeats = b;
|
||||
}
|
||||
|
||||
void AudioBuffer::setAudioFrames(long af)
|
||||
{
|
||||
audioFrames = af;
|
||||
audioFrames = af;
|
||||
#ifdef DEBUG_BUFFER
|
||||
cout << "AudioBuffer " << ID << " has " << audioFrames << " audioFrames\n" << endl;
|
||||
cout << "AudioBuffer " << ID << " has " << audioFrames << " audioFrames\n" << endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
long AudioBuffer::getAudioFrames()
|
||||
{
|
||||
return audioFrames;
|
||||
return audioFrames;
|
||||
}
|
||||
|
||||
std::vector<float>& AudioBuffer::getData()
|
||||
{
|
||||
return buffer;
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void AudioBuffer::nonRtSetSample(std::vector<float>& sample)
|
||||
{
|
||||
buffer.swap(sample);
|
||||
buffer.swap(sample);
|
||||
}
|
||||
void AudioBuffer::nonRtResize(unsigned long size)
|
||||
{
|
||||
buffer.resize(size);
|
||||
buffer.resize(size);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -30,49 +30,49 @@ using namespace std;
|
|||
/// AudioBuffer stores float samples in a big vector.
|
||||
class AudioBuffer
|
||||
{
|
||||
public:
|
||||
AudioBuffer();
|
||||
AudioBuffer(unsigned long size);
|
||||
|
||||
void init();
|
||||
|
||||
/// this function is used for "resizing" an exisiting buffer, and should
|
||||
/// not be called for any other reason.
|
||||
void setID(int id);
|
||||
|
||||
int getID();
|
||||
void setName(const char* n);
|
||||
|
||||
char* getName();
|
||||
int getBeats();
|
||||
|
||||
void setBeats(int b);
|
||||
|
||||
void setAudioFrames(long af);
|
||||
|
||||
long getAudioFrames();
|
||||
|
||||
std::vector<float>& getData();
|
||||
|
||||
void nonRtSetSample(std::vector<float>& sample);
|
||||
|
||||
void nonRtResize(unsigned long size);
|
||||
|
||||
//friend ostream& operator<<(ostream& o, const AudioBuffer& a);
|
||||
|
||||
protected:
|
||||
static int privateID;
|
||||
int ID;
|
||||
|
||||
int numBeats;
|
||||
|
||||
/// holds the number of samples that are usable audio, as opposed to
|
||||
/// buffer.size(), which also has non-used space at the end.
|
||||
long audioFrames;
|
||||
|
||||
char name[20];
|
||||
|
||||
std::vector<float> buffer;
|
||||
public:
|
||||
AudioBuffer();
|
||||
AudioBuffer(unsigned long size);
|
||||
|
||||
void init();
|
||||
|
||||
/// this function is used for "resizing" an exisiting buffer, and should
|
||||
/// not be called for any other reason.
|
||||
void setID(int id);
|
||||
|
||||
int getID();
|
||||
void setName(const char* n);
|
||||
|
||||
char* getName();
|
||||
int getBeats();
|
||||
|
||||
void setBeats(int b);
|
||||
|
||||
void setAudioFrames(long af);
|
||||
|
||||
long getAudioFrames();
|
||||
|
||||
std::vector<float>& getData();
|
||||
|
||||
void nonRtSetSample(std::vector<float>& sample);
|
||||
|
||||
void nonRtResize(unsigned long size);
|
||||
|
||||
//friend ostream& operator<<(ostream& o, const AudioBuffer& a);
|
||||
|
||||
protected:
|
||||
static int privateID;
|
||||
int ID;
|
||||
|
||||
int numBeats;
|
||||
|
||||
/// holds the number of samples that are usable audio, as opposed to
|
||||
/// buffer.size(), which also has non-used space at the end.
|
||||
long audioFrames;
|
||||
|
||||
char name[20];
|
||||
|
||||
std::vector<float> buffer;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -25,25 +25,28 @@
|
|||
|
||||
class AudioProcessor
|
||||
{
|
||||
public:
|
||||
AudioProcessor(){}
|
||||
|
||||
/// copies the track output to master buffer, sidechain & post-side buffer
|
||||
virtual void process(unsigned int nframes, Buffers* buffers){printf("AudioProcessor::process() not derived\n");}
|
||||
|
||||
/// set main mix, 0-1
|
||||
virtual void setMaster(float value){}
|
||||
|
||||
/// set sidechain mix, 0-1
|
||||
virtual void setSidechain(float value){}
|
||||
|
||||
/// set post sidechain mix, 0-1
|
||||
virtual void setPostSidechain(float value){}
|
||||
|
||||
/// set reverb mix, 0-1
|
||||
virtual void setReverb(float value){}
|
||||
|
||||
virtual ~AudioProcessor(){};
|
||||
public:
|
||||
AudioProcessor() {}
|
||||
|
||||
/// copies the track output to master buffer, sidechain & post-side buffer
|
||||
virtual void process(unsigned int nframes, Buffers* buffers)
|
||||
{
|
||||
printf("AudioProcessor::process() not derived\n");
|
||||
}
|
||||
|
||||
/// set main mix, 0-1
|
||||
virtual void setMaster(float value) {}
|
||||
|
||||
/// set sidechain mix, 0-1
|
||||
virtual void setSidechain(float value) {}
|
||||
|
||||
/// set post sidechain mix, 0-1
|
||||
virtual void setPostSidechain(float value) {}
|
||||
|
||||
/// set reverb mix, 0-1
|
||||
virtual void setReverb(float value) {}
|
||||
|
||||
virtual ~AudioProcessor() {};
|
||||
};
|
||||
|
||||
#endif // LUPPP_AUDIO_PROCESSOR_H
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -32,134 +32,129 @@ namespace Avtk
|
|||
// FIXME: Refactor to .hxx .cxx
|
||||
class Background : public Fl_Widget
|
||||
{
|
||||
public:
|
||||
Background(int _x, int _y, int _w, int _h, const char *_label = 0):
|
||||
Fl_Widget(_x, _y, _w, _h, _label)
|
||||
{
|
||||
x = _x;
|
||||
y = _y;
|
||||
w = _w;
|
||||
h = _h;
|
||||
|
||||
label = strdup(_label);
|
||||
|
||||
highlight = false;
|
||||
}
|
||||
bool highlight;
|
||||
int x, y, w, h;
|
||||
const char* label;
|
||||
|
||||
void setLabel(const char* l)
|
||||
{
|
||||
if( label )
|
||||
free( (char*) label);
|
||||
|
||||
label = strdup( l );
|
||||
redraw();
|
||||
}
|
||||
const char* getLabel()
|
||||
{
|
||||
return label;
|
||||
}
|
||||
|
||||
void draw()
|
||||
{
|
||||
if (damage() & FL_DAMAGE_ALL)
|
||||
{
|
||||
cairo_t *cr = Fl::cairo_cc();
|
||||
|
||||
cairo_save( cr );
|
||||
|
||||
cairo_set_line_width(cr, 1.5);
|
||||
|
||||
|
||||
// fill background
|
||||
cairo_rectangle( cr, x, y, w, h);
|
||||
cairo_set_source_rgba( cr, 28 / 255.f, 28 / 255.f , 28 / 255.f , 1 );
|
||||
cairo_fill( cr );
|
||||
|
||||
// draw header
|
||||
// backing
|
||||
cairo_rectangle(cr, x, y, w, 20);
|
||||
cairo_set_source_rgb( cr, 28 / 255.f, 28 / 255.f , 28 / 255.f );
|
||||
cairo_fill( cr );
|
||||
|
||||
// text
|
||||
cairo_move_to( cr, x + 10, y + 14 );
|
||||
cairo_set_source_rgba( cr, 0 / 255.f, 153 / 255.f , 255 / 255.f , 1 );
|
||||
cairo_set_font_size( cr, 10 );
|
||||
cairo_show_text( cr, label );
|
||||
|
||||
// lower stripe
|
||||
cairo_move_to( cr, x , y + 20 );
|
||||
cairo_line_to( cr, x + w, y + 20 );
|
||||
cairo_stroke( cr );
|
||||
|
||||
|
||||
// stroke rim
|
||||
cairo_rectangle(cr, x, y, w, h);
|
||||
cairo_set_source_rgba( cr, 66 / 255.f, 66 / 255.f , 66 / 255.f , 1 );
|
||||
cairo_stroke( cr );
|
||||
|
||||
|
||||
cairo_restore( cr );
|
||||
}
|
||||
}
|
||||
|
||||
void resize(int X, int Y, int W, int H)
|
||||
{
|
||||
Fl_Widget::resize(X,Y,W,H);
|
||||
x = X;
|
||||
y = Y;
|
||||
w = W;
|
||||
h = H;
|
||||
redraw();
|
||||
}
|
||||
|
||||
int handle(int event)
|
||||
{
|
||||
switch(event)
|
||||
{
|
||||
case FL_PUSH:
|
||||
if ( Fl::event_state(FL_BUTTON3) && Fl::event_y() < y + 20 )
|
||||
{
|
||||
const char* name = fl_input( "Track name: ", "" );
|
||||
if ( name )
|
||||
{
|
||||
free( (char*) label );
|
||||
label = strdup( name );
|
||||
redraw();
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
redraw();
|
||||
return 1;
|
||||
case FL_DRAG: {
|
||||
int t = Fl::event_inside(this);
|
||||
if (t != highlight) {
|
||||
redraw();
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
case FL_RELEASE:
|
||||
if (highlight) {
|
||||
highlight = 0;
|
||||
redraw();
|
||||
do_callback();
|
||||
}
|
||||
return 1;
|
||||
case FL_SHORTCUT:
|
||||
if ( test_shortcut() )
|
||||
{
|
||||
do_callback();
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
default:
|
||||
return Fl_Widget::handle(event);
|
||||
}
|
||||
}
|
||||
public:
|
||||
Background(int _x, int _y, int _w, int _h, const char *_label = 0):
|
||||
Fl_Widget(_x, _y, _w, _h, _label)
|
||||
{
|
||||
x = _x;
|
||||
y = _y;
|
||||
w = _w;
|
||||
h = _h;
|
||||
|
||||
label = strdup(_label);
|
||||
|
||||
highlight = false;
|
||||
}
|
||||
bool highlight;
|
||||
int x, y, w, h;
|
||||
const char* label;
|
||||
|
||||
void setLabel(const char* l)
|
||||
{
|
||||
if( label )
|
||||
free( (char*) label);
|
||||
|
||||
label = strdup( l );
|
||||
redraw();
|
||||
}
|
||||
const char* getLabel()
|
||||
{
|
||||
return label;
|
||||
}
|
||||
|
||||
void draw()
|
||||
{
|
||||
if (damage() & FL_DAMAGE_ALL) {
|
||||
cairo_t *cr = Fl::cairo_cc();
|
||||
|
||||
cairo_save( cr );
|
||||
|
||||
cairo_set_line_width(cr, 1.5);
|
||||
|
||||
|
||||
// fill background
|
||||
cairo_rectangle( cr, x, y, w, h);
|
||||
cairo_set_source_rgba( cr, 28 / 255.f, 28 / 255.f , 28 / 255.f , 1 );
|
||||
cairo_fill( cr );
|
||||
|
||||
// draw header
|
||||
// backing
|
||||
cairo_rectangle(cr, x, y, w, 20);
|
||||
cairo_set_source_rgb( cr, 28 / 255.f, 28 / 255.f , 28 / 255.f );
|
||||
cairo_fill( cr );
|
||||
|
||||
// text
|
||||
cairo_move_to( cr, x + 10, y + 14 );
|
||||
cairo_set_source_rgba( cr, 0 / 255.f, 153 / 255.f , 255 / 255.f , 1 );
|
||||
cairo_set_font_size( cr, 10 );
|
||||
cairo_show_text( cr, label );
|
||||
|
||||
// lower stripe
|
||||
cairo_move_to( cr, x , y + 20 );
|
||||
cairo_line_to( cr, x + w, y + 20 );
|
||||
cairo_stroke( cr );
|
||||
|
||||
|
||||
// stroke rim
|
||||
cairo_rectangle(cr, x, y, w, h);
|
||||
cairo_set_source_rgba( cr, 66 / 255.f, 66 / 255.f , 66 / 255.f , 1 );
|
||||
cairo_stroke( cr );
|
||||
|
||||
|
||||
cairo_restore( cr );
|
||||
}
|
||||
}
|
||||
|
||||
void resize(int X, int Y, int W, int H)
|
||||
{
|
||||
Fl_Widget::resize(X,Y,W,H);
|
||||
x = X;
|
||||
y = Y;
|
||||
w = W;
|
||||
h = H;
|
||||
redraw();
|
||||
}
|
||||
|
||||
int handle(int event)
|
||||
{
|
||||
switch(event) {
|
||||
case FL_PUSH:
|
||||
if ( Fl::event_state(FL_BUTTON3) && Fl::event_y() < y + 20 ) {
|
||||
const char* name = fl_input( "Track name: ", "" );
|
||||
if ( name ) {
|
||||
free( (char*) label );
|
||||
label = strdup( name );
|
||||
redraw();
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
redraw();
|
||||
return 1;
|
||||
case FL_DRAG: {
|
||||
int t = Fl::event_inside(this);
|
||||
if (t != highlight) {
|
||||
redraw();
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
case FL_RELEASE:
|
||||
if (highlight) {
|
||||
highlight = 0;
|
||||
redraw();
|
||||
do_callback();
|
||||
}
|
||||
return 1;
|
||||
case FL_SHORTCUT:
|
||||
if ( test_shortcut() ) {
|
||||
do_callback();
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
default:
|
||||
return Fl_Widget::handle(event);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // Avtk
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -28,84 +28,83 @@ namespace Avtk
|
|||
// FIXME: Refactor to .hxx .cxx
|
||||
class Box : public Fl_Widget
|
||||
{
|
||||
public:
|
||||
Box(int _x, int _y, int _w, int _h, const char *_label = 0):
|
||||
Fl_Widget(_x, _y, _w, _h, _label)
|
||||
{
|
||||
x = _x;
|
||||
y = _y;
|
||||
w = _w;
|
||||
h = _h;
|
||||
|
||||
r = g = b = 0;
|
||||
|
||||
label = strdup(_label);
|
||||
|
||||
highlight = false;
|
||||
}
|
||||
bool highlight;
|
||||
int x, y, w, h;
|
||||
const char* label;
|
||||
|
||||
int r,g,b;
|
||||
|
||||
void setLabel(const char* l)
|
||||
{
|
||||
if( label )
|
||||
free( (char*) label);
|
||||
|
||||
label = strdup( l );
|
||||
redraw();
|
||||
}
|
||||
const char* getLabel()
|
||||
{
|
||||
return label;
|
||||
}
|
||||
|
||||
void setColor( int red, int green, int blue )
|
||||
{
|
||||
r = red;
|
||||
g = green;
|
||||
b = blue;
|
||||
|
||||
redraw();
|
||||
}
|
||||
|
||||
void draw()
|
||||
{
|
||||
if (damage() & FL_DAMAGE_ALL)
|
||||
{
|
||||
cairo_t *cr = Fl::cairo_cc();
|
||||
|
||||
cairo_save( cr );
|
||||
|
||||
cairo_set_line_width(cr, 1.5);
|
||||
|
||||
// fill background
|
||||
cairo_rectangle( cr, x, y, w, h);
|
||||
cairo_set_source_rgba( cr, r, g, b, 1 );
|
||||
cairo_fill( cr );
|
||||
|
||||
/*
|
||||
// stroke rim
|
||||
cairo_rectangle(cr, x, y, w, h);
|
||||
cairo_set_source_rgba( cr, 66 / 255.f, 66 / 255.f , 66 / 255.f , 1 );
|
||||
cairo_stroke( cr );
|
||||
*/
|
||||
|
||||
cairo_restore( cr );
|
||||
}
|
||||
}
|
||||
|
||||
void resize(int X, int Y, int W, int H)
|
||||
{
|
||||
Fl_Widget::resize(X,Y,W,H);
|
||||
x = X;
|
||||
y = Y;
|
||||
w = W;
|
||||
h = H;
|
||||
redraw();
|
||||
}
|
||||
public:
|
||||
Box(int _x, int _y, int _w, int _h, const char *_label = 0):
|
||||
Fl_Widget(_x, _y, _w, _h, _label)
|
||||
{
|
||||
x = _x;
|
||||
y = _y;
|
||||
w = _w;
|
||||
h = _h;
|
||||
|
||||
r = g = b = 0;
|
||||
|
||||
label = strdup(_label);
|
||||
|
||||
highlight = false;
|
||||
}
|
||||
bool highlight;
|
||||
int x, y, w, h;
|
||||
const char* label;
|
||||
|
||||
int r,g,b;
|
||||
|
||||
void setLabel(const char* l)
|
||||
{
|
||||
if( label )
|
||||
free( (char*) label);
|
||||
|
||||
label = strdup( l );
|
||||
redraw();
|
||||
}
|
||||
const char* getLabel()
|
||||
{
|
||||
return label;
|
||||
}
|
||||
|
||||
void setColor( int red, int green, int blue )
|
||||
{
|
||||
r = red;
|
||||
g = green;
|
||||
b = blue;
|
||||
|
||||
redraw();
|
||||
}
|
||||
|
||||
void draw()
|
||||
{
|
||||
if (damage() & FL_DAMAGE_ALL) {
|
||||
cairo_t *cr = Fl::cairo_cc();
|
||||
|
||||
cairo_save( cr );
|
||||
|
||||
cairo_set_line_width(cr, 1.5);
|
||||
|
||||
// fill background
|
||||
cairo_rectangle( cr, x, y, w, h);
|
||||
cairo_set_source_rgba( cr, r, g, b, 1 );
|
||||
cairo_fill( cr );
|
||||
|
||||
/*
|
||||
// stroke rim
|
||||
cairo_rectangle(cr, x, y, w, h);
|
||||
cairo_set_source_rgba( cr, 66 / 255.f, 66 / 255.f , 66 / 255.f , 1 );
|
||||
cairo_stroke( cr );
|
||||
*/
|
||||
|
||||
cairo_restore( cr );
|
||||
}
|
||||
}
|
||||
|
||||
void resize(int X, int Y, int W, int H)
|
||||
{
|
||||
Fl_Widget::resize(X,Y,W,H);
|
||||
x = X;
|
||||
y = Y;
|
||||
w = W;
|
||||
h = H;
|
||||
redraw();
|
||||
}
|
||||
};
|
||||
|
||||
} // Avtk
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -27,174 +27,170 @@ namespace Avtk
|
|||
|
||||
class Button : public Fl_Button
|
||||
{
|
||||
public:
|
||||
Button(int _x, int _y, int _w, int _h, const char *_label):
|
||||
Fl_Button(_x, _y, _w, _h, _label)
|
||||
{
|
||||
x = _x;
|
||||
y = _y;
|
||||
w = _w;
|
||||
h = _h;
|
||||
|
||||
labelMe = _label;
|
||||
setLabel( labelMe );
|
||||
|
||||
_r = 1.0;
|
||||
_g = 0.48;
|
||||
_b = 0.0;
|
||||
|
||||
_bgr = 0.11;
|
||||
_bgg = 0.11;
|
||||
_bgb = 0.11;
|
||||
|
||||
highlight = false;
|
||||
mouseOver = false;
|
||||
|
||||
greyedOut = false;
|
||||
}
|
||||
|
||||
void setGreyOut( bool g )
|
||||
{
|
||||
greyedOut = g;
|
||||
}
|
||||
|
||||
bool greyedOut;
|
||||
|
||||
bool mouseOver;
|
||||
bool highlight;
|
||||
int x, y, w, h;
|
||||
const char* labelMe;
|
||||
|
||||
void setLabel( const char* l)
|
||||
{
|
||||
labelMe = l;
|
||||
label( labelMe );
|
||||
redraw();
|
||||
}
|
||||
|
||||
float _r, _g, _b; // foreground colour
|
||||
float _bgr, _bgg, _bgb; // background colour
|
||||
float _outr, _outg, _outb; // outline colour
|
||||
|
||||
void setColor(float r, float g, float b)
|
||||
{
|
||||
_r = r;
|
||||
_g = g;
|
||||
_b = b;
|
||||
}
|
||||
|
||||
void setBgColor(float r, float g, float b)
|
||||
{
|
||||
_bgr = r;
|
||||
_bgg = g;
|
||||
_bgb = b;
|
||||
}
|
||||
|
||||
void setHighlight(bool b)
|
||||
{
|
||||
highlight = b; redraw();
|
||||
}
|
||||
|
||||
void draw()
|
||||
{
|
||||
if (damage() & FL_DAMAGE_ALL)
|
||||
{
|
||||
cairo_t *cr = Fl::cairo_cc();
|
||||
|
||||
cairo_save( cr );
|
||||
|
||||
cairo_rectangle( cr, x+1, y+1, w-2, h-2 );
|
||||
if ( !greyedOut )
|
||||
cairo_set_source_rgb( cr, _bgr, _bgg, _bgb );
|
||||
else
|
||||
{
|
||||
float grey = (_bgr + _bgg + _bgb) / 3;
|
||||
cairo_set_source_rgb( cr, grey, grey, grey );
|
||||
}
|
||||
cairo_fill_preserve(cr);
|
||||
|
||||
cairo_set_line_width(cr, 1.3);
|
||||
cairo_rectangle( cr, x+1, y+1, w-2, h-2 );
|
||||
|
||||
if ( highlight && !greyedOut )
|
||||
{
|
||||
cairo_set_source_rgba(cr, _r, _g, _b, 0.4);
|
||||
cairo_fill_preserve(cr);
|
||||
}
|
||||
|
||||
float alpha = 0.6;
|
||||
if (mouseOver)
|
||||
alpha = 1;
|
||||
|
||||
if ( !greyedOut )
|
||||
cairo_set_source_rgba(cr, _r, _g, _b, alpha);
|
||||
else
|
||||
{
|
||||
float grey = (_r + _g + _b) / 3;
|
||||
cairo_set_source_rgb( cr, grey, grey, grey );
|
||||
}
|
||||
|
||||
if ( highlight && !greyedOut )
|
||||
cairo_set_line_width(cr, 2.2);
|
||||
cairo_stroke(cr);
|
||||
|
||||
cairo_restore( cr );
|
||||
|
||||
draw_label();
|
||||
}
|
||||
}
|
||||
|
||||
void resize(int X, int Y, int W, int H)
|
||||
{
|
||||
Fl_Widget::resize(X,Y,W,H);
|
||||
x = X;
|
||||
y = Y;
|
||||
w = W;
|
||||
h = H;
|
||||
redraw();
|
||||
}
|
||||
|
||||
int handle(int event)
|
||||
{
|
||||
switch(event) {
|
||||
case FL_PUSH:
|
||||
highlight = 1;
|
||||
redraw();
|
||||
return 1;
|
||||
case FL_DRAG: {
|
||||
int t = Fl::event_inside(this);
|
||||
if (t != highlight) {
|
||||
highlight = t;
|
||||
redraw();
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
case FL_ENTER:
|
||||
mouseOver = true;
|
||||
redraw();
|
||||
return 1;
|
||||
case FL_LEAVE:
|
||||
mouseOver = false;
|
||||
redraw();
|
||||
return 1;
|
||||
case FL_RELEASE:
|
||||
if (highlight) {
|
||||
highlight = 0;
|
||||
redraw();
|
||||
do_callback();
|
||||
}
|
||||
return 1;
|
||||
case FL_SHORTCUT:
|
||||
if ( test_shortcut() )
|
||||
{
|
||||
do_callback();
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
default:
|
||||
return Fl_Widget::handle(event);
|
||||
}
|
||||
}
|
||||
public:
|
||||
Button(int _x, int _y, int _w, int _h, const char *_label):
|
||||
Fl_Button(_x, _y, _w, _h, _label)
|
||||
{
|
||||
x = _x;
|
||||
y = _y;
|
||||
w = _w;
|
||||
h = _h;
|
||||
|
||||
labelMe = _label;
|
||||
setLabel( labelMe );
|
||||
|
||||
_r = 1.0;
|
||||
_g = 0.48;
|
||||
_b = 0.0;
|
||||
|
||||
_bgr = 0.11;
|
||||
_bgg = 0.11;
|
||||
_bgb = 0.11;
|
||||
|
||||
highlight = false;
|
||||
mouseOver = false;
|
||||
|
||||
greyedOut = false;
|
||||
}
|
||||
|
||||
void setGreyOut( bool g )
|
||||
{
|
||||
greyedOut = g;
|
||||
}
|
||||
|
||||
bool greyedOut;
|
||||
|
||||
bool mouseOver;
|
||||
bool highlight;
|
||||
int x, y, w, h;
|
||||
const char* labelMe;
|
||||
|
||||
void setLabel( const char* l)
|
||||
{
|
||||
labelMe = l;
|
||||
label( labelMe );
|
||||
redraw();
|
||||
}
|
||||
|
||||
float _r, _g, _b; // foreground colour
|
||||
float _bgr, _bgg, _bgb; // background colour
|
||||
float _outr, _outg, _outb; // outline colour
|
||||
|
||||
void setColor(float r, float g, float b)
|
||||
{
|
||||
_r = r;
|
||||
_g = g;
|
||||
_b = b;
|
||||
}
|
||||
|
||||
void setBgColor(float r, float g, float b)
|
||||
{
|
||||
_bgr = r;
|
||||
_bgg = g;
|
||||
_bgb = b;
|
||||
}
|
||||
|
||||
void setHighlight(bool b)
|
||||
{
|
||||
highlight = b;
|
||||
redraw();
|
||||
}
|
||||
|
||||
void draw()
|
||||
{
|
||||
if (damage() & FL_DAMAGE_ALL) {
|
||||
cairo_t *cr = Fl::cairo_cc();
|
||||
|
||||
cairo_save( cr );
|
||||
|
||||
cairo_rectangle( cr, x+1, y+1, w-2, h-2 );
|
||||
if ( !greyedOut )
|
||||
cairo_set_source_rgb( cr, _bgr, _bgg, _bgb );
|
||||
else {
|
||||
float grey = (_bgr + _bgg + _bgb) / 3;
|
||||
cairo_set_source_rgb( cr, grey, grey, grey );
|
||||
}
|
||||
cairo_fill_preserve(cr);
|
||||
|
||||
cairo_set_line_width(cr, 1.3);
|
||||
cairo_rectangle( cr, x+1, y+1, w-2, h-2 );
|
||||
|
||||
if ( highlight && !greyedOut ) {
|
||||
cairo_set_source_rgba(cr, _r, _g, _b, 0.4);
|
||||
cairo_fill_preserve(cr);
|
||||
}
|
||||
|
||||
float alpha = 0.6;
|
||||
if (mouseOver)
|
||||
alpha = 1;
|
||||
|
||||
if ( !greyedOut )
|
||||
cairo_set_source_rgba(cr, _r, _g, _b, alpha);
|
||||
else {
|
||||
float grey = (_r + _g + _b) / 3;
|
||||
cairo_set_source_rgb( cr, grey, grey, grey );
|
||||
}
|
||||
|
||||
if ( highlight && !greyedOut )
|
||||
cairo_set_line_width(cr, 2.2);
|
||||
cairo_stroke(cr);
|
||||
|
||||
cairo_restore( cr );
|
||||
|
||||
draw_label();
|
||||
}
|
||||
}
|
||||
|
||||
void resize(int X, int Y, int W, int H)
|
||||
{
|
||||
Fl_Widget::resize(X,Y,W,H);
|
||||
x = X;
|
||||
y = Y;
|
||||
w = W;
|
||||
h = H;
|
||||
redraw();
|
||||
}
|
||||
|
||||
int handle(int event)
|
||||
{
|
||||
switch(event) {
|
||||
case FL_PUSH:
|
||||
highlight = 1;
|
||||
redraw();
|
||||
return 1;
|
||||
case FL_DRAG: {
|
||||
int t = Fl::event_inside(this);
|
||||
if (t != highlight) {
|
||||
highlight = t;
|
||||
redraw();
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
case FL_ENTER:
|
||||
mouseOver = true;
|
||||
redraw();
|
||||
return 1;
|
||||
case FL_LEAVE:
|
||||
mouseOver = false;
|
||||
redraw();
|
||||
return 1;
|
||||
case FL_RELEASE:
|
||||
if (highlight) {
|
||||
highlight = 0;
|
||||
redraw();
|
||||
do_callback();
|
||||
}
|
||||
return 1;
|
||||
case FL_SHORTCUT:
|
||||
if ( test_shortcut() ) {
|
||||
do_callback();
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
default:
|
||||
return Fl_Widget::handle(event);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // Avtk
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -29,174 +29,168 @@ namespace Avtk
|
|||
|
||||
class Dial : public Fl_Slider
|
||||
{
|
||||
public:
|
||||
Dial(int _x, int _y, int _w, int _h, const char* _lab=0):
|
||||
Fl_Slider(_x, _y, _w, _h, _lab)
|
||||
{
|
||||
x = _x;
|
||||
y = _y;
|
||||
w = _w;
|
||||
h = _h;
|
||||
|
||||
drawLabel = true;
|
||||
|
||||
mouseClickedY = 0;
|
||||
mouseClicked = false;
|
||||
|
||||
highlight = false;
|
||||
_label = strdup( _lab );
|
||||
}
|
||||
|
||||
~Dial()
|
||||
{
|
||||
if( _label )
|
||||
free( _label );
|
||||
}
|
||||
|
||||
bool highlight;
|
||||
int x, y, w, h;
|
||||
char* _label;
|
||||
|
||||
float radius;
|
||||
float lineWidth;
|
||||
|
||||
int mouseClickedY;
|
||||
bool mouseClicked;
|
||||
|
||||
bool drawLabel;
|
||||
|
||||
void setLabel( const char* newLabel )
|
||||
{
|
||||
if( _label )
|
||||
free( _label );
|
||||
|
||||
_label = strdup( newLabel );
|
||||
|
||||
label( _label );
|
||||
redraw();
|
||||
}
|
||||
|
||||
void draw()
|
||||
{
|
||||
if (damage() & FL_DAMAGE_ALL)
|
||||
{
|
||||
if ( drawLabel )
|
||||
{
|
||||
draw_label();
|
||||
}
|
||||
|
||||
// * 0.9 for line width to remain inside redraw area
|
||||
if ( w > h )
|
||||
radius = (h / 2.f)*0.9;
|
||||
else
|
||||
radius = (w / 2.f)*0.9;
|
||||
|
||||
lineWidth = 1.4 + radius / 12.f;
|
||||
|
||||
cairo_t *cr = Fl::cairo_cc();
|
||||
|
||||
cairo_save( cr );
|
||||
|
||||
cairo_rectangle( cr, x, y, w, h );
|
||||
cairo_set_source_rgba(cr, 1.1, 0.1, 0.1, 0 );
|
||||
cairo_fill(cr);
|
||||
|
||||
cairo_set_line_join(cr, CAIRO_LINE_JOIN_ROUND);
|
||||
cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);
|
||||
|
||||
cairo_set_line_width(cr, lineWidth-0.2);
|
||||
cairo_move_to( cr, x+w/2,y+h/2);
|
||||
cairo_line_to( cr, x+w/2,y+h/2);
|
||||
cairo_set_source_rgba(cr, 0.1, 0.1, 0.1, 0 );
|
||||
cairo_stroke(cr);
|
||||
|
||||
cairo_arc(cr, x+w/2,y+h/2, radius, 2.46, 0.75 );
|
||||
cairo_set_source_rgb(cr, 0.1, 0.1, 0.1 );
|
||||
cairo_stroke(cr);
|
||||
|
||||
float angle = 2.46 + ( 4.54 * value() );
|
||||
cairo_set_line_width(cr, lineWidth);
|
||||
cairo_arc(cr, x+w/2,y+h/2, radius, 2.46, angle );
|
||||
cairo_line_to(cr, x+w/2,y+h/2);
|
||||
cairo_set_source_rgba(cr, 1.0, 0.48, 0, 0.8);
|
||||
cairo_stroke(cr);
|
||||
|
||||
cairo_restore( cr );
|
||||
}
|
||||
}
|
||||
|
||||
void resize(int X, int Y, int W, int H)
|
||||
{
|
||||
Fl_Slider::resize(X,Y,W,H);
|
||||
x = X;
|
||||
y = Y;
|
||||
w = W;
|
||||
h = H;
|
||||
redraw();
|
||||
}
|
||||
|
||||
int handle(int event)
|
||||
{
|
||||
//cout << "handle event type = " << event << " value = " << value() << endl;
|
||||
|
||||
//Fl_Slider::handle( event );
|
||||
|
||||
switch(event) {
|
||||
case FL_PUSH:
|
||||
highlight = 1;
|
||||
redraw();
|
||||
return 1;
|
||||
case FL_DRAG:
|
||||
{
|
||||
if ( Fl::event_state(FL_BUTTON1) )
|
||||
{
|
||||
if ( mouseClicked == false ) // catch the "click" event
|
||||
{
|
||||
mouseClickedY = Fl::event_y();
|
||||
mouseClicked = true;
|
||||
}
|
||||
|
||||
float deltaY = mouseClickedY - Fl::event_y();
|
||||
|
||||
float val = value();
|
||||
val += deltaY / 100.f;
|
||||
|
||||
if ( val > 1.0 ) val = 1.0;
|
||||
if ( val < 0.0 ) val = 0.0;
|
||||
|
||||
set_value( val );
|
||||
|
||||
mouseClickedY = Fl::event_y();
|
||||
redraw();
|
||||
do_callback(); // makes FLTK call "extra" code entered in FLUID
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
case FL_MOUSEWHEEL:
|
||||
{
|
||||
float val = value() - Fl::event_dy() * 0.1;
|
||||
//printf("dial scroll event: %f\n", val);
|
||||
if ( val > 1.0 ) val = 1.0;
|
||||
if ( val < 0.0 ) val = 0.0;
|
||||
set_value( val );
|
||||
redraw();
|
||||
do_callback();
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case FL_RELEASE:
|
||||
if (highlight) {
|
||||
highlight = 0;
|
||||
redraw();
|
||||
// never do anything after a callback, as the callback
|
||||
// may delete the widget!
|
||||
}
|
||||
mouseClicked = false;
|
||||
return 1;
|
||||
default:
|
||||
return Fl_Widget::handle(event);
|
||||
}
|
||||
}
|
||||
public:
|
||||
Dial(int _x, int _y, int _w, int _h, const char* _lab=0):
|
||||
Fl_Slider(_x, _y, _w, _h, _lab)
|
||||
{
|
||||
x = _x;
|
||||
y = _y;
|
||||
w = _w;
|
||||
h = _h;
|
||||
|
||||
drawLabel = true;
|
||||
|
||||
mouseClickedY = 0;
|
||||
mouseClicked = false;
|
||||
|
||||
highlight = false;
|
||||
_label = strdup( _lab );
|
||||
}
|
||||
|
||||
~Dial()
|
||||
{
|
||||
if( _label )
|
||||
free( _label );
|
||||
}
|
||||
|
||||
bool highlight;
|
||||
int x, y, w, h;
|
||||
char* _label;
|
||||
|
||||
float radius;
|
||||
float lineWidth;
|
||||
|
||||
int mouseClickedY;
|
||||
bool mouseClicked;
|
||||
|
||||
bool drawLabel;
|
||||
|
||||
void setLabel( const char* newLabel )
|
||||
{
|
||||
if( _label )
|
||||
free( _label );
|
||||
|
||||
_label = strdup( newLabel );
|
||||
|
||||
label( _label );
|
||||
redraw();
|
||||
}
|
||||
|
||||
void draw()
|
||||
{
|
||||
if (damage() & FL_DAMAGE_ALL) {
|
||||
if ( drawLabel ) {
|
||||
draw_label();
|
||||
}
|
||||
|
||||
// * 0.9 for line width to remain inside redraw area
|
||||
if ( w > h )
|
||||
radius = (h / 2.f)*0.9;
|
||||
else
|
||||
radius = (w / 2.f)*0.9;
|
||||
|
||||
lineWidth = 1.4 + radius / 12.f;
|
||||
|
||||
cairo_t *cr = Fl::cairo_cc();
|
||||
|
||||
cairo_save( cr );
|
||||
|
||||
cairo_rectangle( cr, x, y, w, h );
|
||||
cairo_set_source_rgba(cr, 1.1, 0.1, 0.1, 0 );
|
||||
cairo_fill(cr);
|
||||
|
||||
cairo_set_line_join(cr, CAIRO_LINE_JOIN_ROUND);
|
||||
cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);
|
||||
|
||||
cairo_set_line_width(cr, lineWidth-0.2);
|
||||
cairo_move_to( cr, x+w/2,y+h/2);
|
||||
cairo_line_to( cr, x+w/2,y+h/2);
|
||||
cairo_set_source_rgba(cr, 0.1, 0.1, 0.1, 0 );
|
||||
cairo_stroke(cr);
|
||||
|
||||
cairo_arc(cr, x+w/2,y+h/2, radius, 2.46, 0.75 );
|
||||
cairo_set_source_rgb(cr, 0.1, 0.1, 0.1 );
|
||||
cairo_stroke(cr);
|
||||
|
||||
float angle = 2.46 + ( 4.54 * value() );
|
||||
cairo_set_line_width(cr, lineWidth);
|
||||
cairo_arc(cr, x+w/2,y+h/2, radius, 2.46, angle );
|
||||
cairo_line_to(cr, x+w/2,y+h/2);
|
||||
cairo_set_source_rgba(cr, 1.0, 0.48, 0, 0.8);
|
||||
cairo_stroke(cr);
|
||||
|
||||
cairo_restore( cr );
|
||||
}
|
||||
}
|
||||
|
||||
void resize(int X, int Y, int W, int H)
|
||||
{
|
||||
Fl_Slider::resize(X,Y,W,H);
|
||||
x = X;
|
||||
y = Y;
|
||||
w = W;
|
||||
h = H;
|
||||
redraw();
|
||||
}
|
||||
|
||||
int handle(int event)
|
||||
{
|
||||
//cout << "handle event type = " << event << " value = " << value() << endl;
|
||||
|
||||
//Fl_Slider::handle( event );
|
||||
|
||||
switch(event) {
|
||||
case FL_PUSH:
|
||||
highlight = 1;
|
||||
redraw();
|
||||
return 1;
|
||||
case FL_DRAG: {
|
||||
if ( Fl::event_state(FL_BUTTON1) ) {
|
||||
if ( mouseClicked == false ) { // catch the "click" event
|
||||
mouseClickedY = Fl::event_y();
|
||||
mouseClicked = true;
|
||||
}
|
||||
|
||||
float deltaY = mouseClickedY - Fl::event_y();
|
||||
|
||||
float val = value();
|
||||
val += deltaY / 100.f;
|
||||
|
||||
if ( val > 1.0 ) val = 1.0;
|
||||
if ( val < 0.0 ) val = 0.0;
|
||||
|
||||
set_value( val );
|
||||
|
||||
mouseClickedY = Fl::event_y();
|
||||
redraw();
|
||||
do_callback(); // makes FLTK call "extra" code entered in FLUID
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
case FL_MOUSEWHEEL: {
|
||||
float val = value() - Fl::event_dy() * 0.1;
|
||||
//printf("dial scroll event: %f\n", val);
|
||||
if ( val > 1.0 ) val = 1.0;
|
||||
if ( val < 0.0 ) val = 0.0;
|
||||
set_value( val );
|
||||
redraw();
|
||||
do_callback();
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case FL_RELEASE:
|
||||
if (highlight) {
|
||||
highlight = 0;
|
||||
redraw();
|
||||
// never do anything after a callback, as the callback
|
||||
// may delete the widget!
|
||||
}
|
||||
mouseClicked = false;
|
||||
return 1;
|
||||
default:
|
||||
return Fl_Widget::handle(event);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // Avtk
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -38,78 +38,74 @@ namespace Avtk
|
|||
|
||||
class Image : public Fl_Widget
|
||||
{
|
||||
public:
|
||||
Image(int _x, int _y, int _w, int _h, const char *_label=0 ):
|
||||
Fl_Widget(_x, _y, _w, _h, _label)
|
||||
{
|
||||
x = _x;
|
||||
y = _y;
|
||||
w = _w;
|
||||
h = _h;
|
||||
|
||||
label = _label;
|
||||
|
||||
bits = -1;
|
||||
imageDataPtr = 0;
|
||||
|
||||
stickToRight = false;
|
||||
}
|
||||
|
||||
// used to keep images on the right hand side of the window
|
||||
bool stickToRight;
|
||||
|
||||
void setPixbuf(const unsigned char* data, int b )
|
||||
{
|
||||
bits = b;
|
||||
imageDataPtr = data;
|
||||
}
|
||||
|
||||
int x, y, w, h;
|
||||
const char* label;
|
||||
|
||||
int bits;
|
||||
const unsigned char* imageDataPtr;
|
||||
|
||||
void draw()
|
||||
{
|
||||
if ( damage() & FL_DAMAGE_ALL && imageDataPtr != 0 )
|
||||
{
|
||||
fl_draw_image((const uchar*)imageDataPtr, x, y, w, h, bits, w*bits);
|
||||
}
|
||||
}
|
||||
|
||||
void resize(int X, int Y, int W, int H)
|
||||
{
|
||||
if ( stickToRight )
|
||||
{
|
||||
x = gui->getWindowWidth() - w;
|
||||
}
|
||||
|
||||
redraw();
|
||||
}
|
||||
|
||||
int handle(int event)
|
||||
{
|
||||
switch(event)
|
||||
{
|
||||
case FL_PUSH:
|
||||
do_callback();
|
||||
return 1;
|
||||
case FL_DRAG:
|
||||
return 1;
|
||||
case FL_RELEASE:
|
||||
return 1;
|
||||
case FL_SHORTCUT:
|
||||
if ( test_shortcut() )
|
||||
{
|
||||
do_callback();
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
default:
|
||||
return Fl_Widget::handle(event);
|
||||
}
|
||||
}
|
||||
public:
|
||||
Image(int _x, int _y, int _w, int _h, const char *_label=0 ):
|
||||
Fl_Widget(_x, _y, _w, _h, _label)
|
||||
{
|
||||
x = _x;
|
||||
y = _y;
|
||||
w = _w;
|
||||
h = _h;
|
||||
|
||||
label = _label;
|
||||
|
||||
bits = -1;
|
||||
imageDataPtr = 0;
|
||||
|
||||
stickToRight = false;
|
||||
}
|
||||
|
||||
// used to keep images on the right hand side of the window
|
||||
bool stickToRight;
|
||||
|
||||
void setPixbuf(const unsigned char* data, int b )
|
||||
{
|
||||
bits = b;
|
||||
imageDataPtr = data;
|
||||
}
|
||||
|
||||
int x, y, w, h;
|
||||
const char* label;
|
||||
|
||||
int bits;
|
||||
const unsigned char* imageDataPtr;
|
||||
|
||||
void draw()
|
||||
{
|
||||
if ( damage() & FL_DAMAGE_ALL && imageDataPtr != 0 ) {
|
||||
fl_draw_image((const uchar*)imageDataPtr, x, y, w, h, bits, w*bits);
|
||||
}
|
||||
}
|
||||
|
||||
void resize(int X, int Y, int W, int H)
|
||||
{
|
||||
if ( stickToRight ) {
|
||||
x = gui->getWindowWidth() - w;
|
||||
}
|
||||
|
||||
redraw();
|
||||
}
|
||||
|
||||
int handle(int event)
|
||||
{
|
||||
switch(event) {
|
||||
case FL_PUSH:
|
||||
do_callback();
|
||||
return 1;
|
||||
case FL_DRAG:
|
||||
return 1;
|
||||
case FL_RELEASE:
|
||||
return 1;
|
||||
case FL_SHORTCUT:
|
||||
if ( test_shortcut() ) {
|
||||
do_callback();
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
default:
|
||||
return Fl_Widget::handle(event);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // Avtk
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -27,152 +27,144 @@ namespace Avtk
|
|||
|
||||
class LightButton : public Fl_Button
|
||||
{
|
||||
public:
|
||||
LightButton(int _x, int _y, int _w, int _h, const char *_label):
|
||||
Fl_Button(_x, _y, _w, _h, _label)
|
||||
{
|
||||
x = _x;
|
||||
y = _y;
|
||||
w = _w;
|
||||
h = _h;
|
||||
|
||||
_r = 1.0;
|
||||
_g = 0.48;
|
||||
_b = 0.0;
|
||||
|
||||
_bgr = 0.11;
|
||||
_bgg = 0.11;
|
||||
_bgb = 0.11;
|
||||
|
||||
_outr = _r;
|
||||
_outg = _g;
|
||||
_outb = _b;
|
||||
|
||||
label = _label;
|
||||
|
||||
_highlight = false;
|
||||
mouseOver = false;
|
||||
}
|
||||
|
||||
bool mouseOver;
|
||||
bool _highlight;
|
||||
int x, y, w, h;
|
||||
const char* label;
|
||||
float _r, _g, _b; // foreground colour
|
||||
float _bgr, _bgg, _bgb; // background colour
|
||||
float _outr, _outg, _outb; // outline colour
|
||||
|
||||
void setColor(float r, float g, float b)
|
||||
{
|
||||
_r = r;
|
||||
_g = g;
|
||||
_b = b;
|
||||
}
|
||||
|
||||
void setBgColor(float r, float g, float b)
|
||||
{
|
||||
_bgr = r;
|
||||
_bgg = g;
|
||||
_bgb = b;
|
||||
}
|
||||
|
||||
void draw()
|
||||
{
|
||||
if (damage() & FL_DAMAGE_ALL)
|
||||
{
|
||||
if ( value() )
|
||||
{
|
||||
_highlight = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
_highlight = false;
|
||||
}
|
||||
|
||||
cairo_t *cr = Fl::cairo_cc();
|
||||
|
||||
cairo_save( cr );
|
||||
|
||||
cairo_rectangle( cr, x+1, y+1, w-2, h-2 );
|
||||
cairo_set_source_rgba( cr, _bgr, _bgg, _bgb, 0.4 );
|
||||
cairo_fill_preserve(cr);
|
||||
|
||||
cairo_set_line_width(cr, 1.5);
|
||||
cairo_rectangle( cr, x+1, y+1, w-2, h-2 );
|
||||
|
||||
if ( _highlight )
|
||||
{
|
||||
cairo_set_source_rgba(cr, _r, _g, _b, 0.4);
|
||||
cairo_fill_preserve(cr);
|
||||
}
|
||||
|
||||
float alpha = 0.7;
|
||||
if (mouseOver)
|
||||
alpha = 1;
|
||||
cairo_set_source_rgba(cr, _r, _g, _b, alpha);
|
||||
cairo_stroke(cr);
|
||||
|
||||
cairo_restore( cr );
|
||||
|
||||
draw_label();
|
||||
}
|
||||
}
|
||||
|
||||
void resize(int X, int Y, int W, int H)
|
||||
{
|
||||
Fl_Widget::resize(X,Y,W,H);
|
||||
x = X;
|
||||
y = Y;
|
||||
w = W;
|
||||
h = H;
|
||||
redraw();
|
||||
}
|
||||
|
||||
|
||||
|
||||
int handle(int event)
|
||||
{
|
||||
switch(event) {
|
||||
case FL_ACTIVATE:
|
||||
{
|
||||
}
|
||||
case FL_DEACTIVATE:
|
||||
{
|
||||
}
|
||||
return 1;
|
||||
case FL_PUSH:
|
||||
|
||||
do_callback();
|
||||
return 1;
|
||||
case FL_DRAG: {
|
||||
int t = Fl::event_inside(this);
|
||||
if (t != _highlight) {
|
||||
_highlight = t;
|
||||
redraw();
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
case FL_ENTER:
|
||||
mouseOver = true;
|
||||
redraw();
|
||||
return 1;
|
||||
case FL_LEAVE:
|
||||
mouseOver = false;
|
||||
redraw();
|
||||
return 1;
|
||||
case FL_RELEASE:
|
||||
return 1;
|
||||
case FL_SHORTCUT:
|
||||
if ( test_shortcut() )
|
||||
{
|
||||
do_callback();
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
default:
|
||||
return Fl_Widget::handle(event);
|
||||
}
|
||||
}
|
||||
public:
|
||||
LightButton(int _x, int _y, int _w, int _h, const char *_label):
|
||||
Fl_Button(_x, _y, _w, _h, _label)
|
||||
{
|
||||
x = _x;
|
||||
y = _y;
|
||||
w = _w;
|
||||
h = _h;
|
||||
|
||||
_r = 1.0;
|
||||
_g = 0.48;
|
||||
_b = 0.0;
|
||||
|
||||
_bgr = 0.11;
|
||||
_bgg = 0.11;
|
||||
_bgb = 0.11;
|
||||
|
||||
_outr = _r;
|
||||
_outg = _g;
|
||||
_outb = _b;
|
||||
|
||||
label = _label;
|
||||
|
||||
_highlight = false;
|
||||
mouseOver = false;
|
||||
}
|
||||
|
||||
bool mouseOver;
|
||||
bool _highlight;
|
||||
int x, y, w, h;
|
||||
const char* label;
|
||||
float _r, _g, _b; // foreground colour
|
||||
float _bgr, _bgg, _bgb; // background colour
|
||||
float _outr, _outg, _outb; // outline colour
|
||||
|
||||
void setColor(float r, float g, float b)
|
||||
{
|
||||
_r = r;
|
||||
_g = g;
|
||||
_b = b;
|
||||
}
|
||||
|
||||
void setBgColor(float r, float g, float b)
|
||||
{
|
||||
_bgr = r;
|
||||
_bgg = g;
|
||||
_bgb = b;
|
||||
}
|
||||
|
||||
void draw()
|
||||
{
|
||||
if (damage() & FL_DAMAGE_ALL) {
|
||||
if ( value() ) {
|
||||
_highlight = true;
|
||||
} else {
|
||||
_highlight = false;
|
||||
}
|
||||
|
||||
cairo_t *cr = Fl::cairo_cc();
|
||||
|
||||
cairo_save( cr );
|
||||
|
||||
cairo_rectangle( cr, x+1, y+1, w-2, h-2 );
|
||||
cairo_set_source_rgba( cr, _bgr, _bgg, _bgb, 0.4 );
|
||||
cairo_fill_preserve(cr);
|
||||
|
||||
cairo_set_line_width(cr, 1.5);
|
||||
cairo_rectangle( cr, x+1, y+1, w-2, h-2 );
|
||||
|
||||
if ( _highlight ) {
|
||||
cairo_set_source_rgba(cr, _r, _g, _b, 0.4);
|
||||
cairo_fill_preserve(cr);
|
||||
}
|
||||
|
||||
float alpha = 0.7;
|
||||
if (mouseOver)
|
||||
alpha = 1;
|
||||
cairo_set_source_rgba(cr, _r, _g, _b, alpha);
|
||||
cairo_stroke(cr);
|
||||
|
||||
cairo_restore( cr );
|
||||
|
||||
draw_label();
|
||||
}
|
||||
}
|
||||
|
||||
void resize(int X, int Y, int W, int H)
|
||||
{
|
||||
Fl_Widget::resize(X,Y,W,H);
|
||||
x = X;
|
||||
y = Y;
|
||||
w = W;
|
||||
h = H;
|
||||
redraw();
|
||||
}
|
||||
|
||||
|
||||
|
||||
int handle(int event)
|
||||
{
|
||||
switch(event) {
|
||||
case FL_ACTIVATE: {
|
||||
}
|
||||
case FL_DEACTIVATE: {
|
||||
}
|
||||
return 1;
|
||||
case FL_PUSH:
|
||||
|
||||
do_callback();
|
||||
return 1;
|
||||
case FL_DRAG: {
|
||||
int t = Fl::event_inside(this);
|
||||
if (t != _highlight) {
|
||||
_highlight = t;
|
||||
redraw();
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
case FL_ENTER:
|
||||
mouseOver = true;
|
||||
redraw();
|
||||
return 1;
|
||||
case FL_LEAVE:
|
||||
mouseOver = false;
|
||||
redraw();
|
||||
return 1;
|
||||
case FL_RELEASE:
|
||||
return 1;
|
||||
case FL_SHORTCUT:
|
||||
if ( test_shortcut() ) {
|
||||
do_callback();
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
default:
|
||||
return Fl_Widget::handle(event);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // Avtk
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -27,173 +27,172 @@ namespace Avtk
|
|||
|
||||
class RadialStatus : public Fl_Slider
|
||||
{
|
||||
public:
|
||||
RadialStatus(int _x, int _y, int _w, int _h, const char *_label = 0):
|
||||
Fl_Slider(_x, _y, _w, _h, _label)
|
||||
{
|
||||
x = _x;
|
||||
y = _y;
|
||||
w = _w;
|
||||
h = _h;
|
||||
|
||||
label = _label;
|
||||
|
||||
previousAngle = -1;
|
||||
|
||||
_r = 1.0;
|
||||
_g = 0.48;
|
||||
_b = 0.0;
|
||||
|
||||
_bgr = 0.11;
|
||||
_bgg = 0.11;
|
||||
_bgb = 0.11;
|
||||
|
||||
highlight = false;
|
||||
mouseOver = false;
|
||||
|
||||
_recording = false;
|
||||
}
|
||||
|
||||
bool _recording;
|
||||
void recording(bool r){_recording = r; redraw();}
|
||||
|
||||
bool mouseOver;
|
||||
bool highlight;
|
||||
int x, y, w, h;
|
||||
const char* label;
|
||||
|
||||
int previousAngle;
|
||||
|
||||
float _r, _g, _b; // foreground colour
|
||||
float _bgr, _bgg, _bgb; // background colour
|
||||
float _outr, _outg, _outb; // outline colour
|
||||
|
||||
void setColor(float r, float g, float b)
|
||||
{
|
||||
_r = r;
|
||||
_g = g;
|
||||
_b = b;
|
||||
}
|
||||
|
||||
void setBgColor(float r, float g, float b)
|
||||
{
|
||||
_bgr = r;
|
||||
_bgg = g;
|
||||
_bgb = b;
|
||||
}
|
||||
|
||||
void draw()
|
||||
{
|
||||
// check that its a new "segment" to redraw
|
||||
int newAngle = (value() * 16);
|
||||
|
||||
if (damage() & FL_DAMAGE_ALL &&
|
||||
previousAngle != newAngle )
|
||||
{
|
||||
cairo_t *cr = Fl::cairo_cc();
|
||||
|
||||
cairo_save( cr );
|
||||
|
||||
int xc = (w) / 2.f;
|
||||
int yc = (h) / 2.f;
|
||||
|
||||
int radius = xc > yc ? yc : xc;
|
||||
radius -= 10;
|
||||
|
||||
float angle = newAngle / 16.f;
|
||||
|
||||
cairo_set_line_cap ( cr, CAIRO_LINE_CAP_ROUND );
|
||||
//cairo_move_to( cr, x + xc, y + yc );
|
||||
cairo_arc( cr, x + xc, y + yc, radius, -(3.1415/2), angle * 6.28 - (3.1415/2) );
|
||||
cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.5 );
|
||||
cairo_set_line_width(cr, 12);
|
||||
cairo_stroke_preserve(cr);
|
||||
|
||||
cairo_set_source_rgba (cr, 1.0, 0.48, 0.0, 1 );
|
||||
cairo_set_line_width(cr, 8.2);
|
||||
cairo_stroke(cr);
|
||||
|
||||
|
||||
// recording?
|
||||
if ( _recording )
|
||||
{
|
||||
cairo_set_source_rgba(cr,1.0,0.0,0.0, 0.8);
|
||||
cairo_arc(cr, x + xc, y + yc, radius-4, 0, 2 * 3.1415);
|
||||
cairo_fill_preserve(cr);
|
||||
cairo_set_source_rgba(cr,0.0,0.0,0.0, 0.8);
|
||||
cairo_set_line_width(cr, 2.2);
|
||||
cairo_stroke(cr);
|
||||
|
||||
// color of internal dot depending on rec state
|
||||
cairo_set_source_rgba(cr,0.0,0.0,0.0, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
cairo_set_source_rgba(cr,0.3,0.3,0.3, 1);
|
||||
}
|
||||
|
||||
// inside circle
|
||||
cairo_arc(cr, x + xc, y + yc, 10, 0, 2 * 3.1415);
|
||||
cairo_set_line_width(cr, 4.2);
|
||||
cairo_fill(cr);
|
||||
|
||||
cairo_restore( cr );
|
||||
|
||||
draw_label();
|
||||
}
|
||||
}
|
||||
|
||||
void resize(int X, int Y, int W, int H)
|
||||
{
|
||||
Fl_Widget::resize(X,Y,W,H);
|
||||
x = X;
|
||||
y = Y;
|
||||
w = W;
|
||||
h = H;
|
||||
redraw();
|
||||
}
|
||||
|
||||
int handle(int event)
|
||||
{
|
||||
switch(event) {
|
||||
case FL_PUSH:
|
||||
highlight = 1;
|
||||
redraw();
|
||||
return 1;
|
||||
case FL_DRAG: {
|
||||
int t = Fl::event_inside(this);
|
||||
if (t != highlight) {
|
||||
highlight = t;
|
||||
redraw();
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
case FL_ENTER:
|
||||
mouseOver = true;
|
||||
redraw();
|
||||
return 1;
|
||||
case FL_LEAVE:
|
||||
mouseOver = false;
|
||||
redraw();
|
||||
return 1;
|
||||
case FL_RELEASE:
|
||||
if (highlight) {
|
||||
highlight = 0;
|
||||
redraw();
|
||||
do_callback();
|
||||
}
|
||||
return 1;
|
||||
case FL_SHORTCUT:
|
||||
if ( test_shortcut() )
|
||||
{
|
||||
do_callback();
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
default:
|
||||
return Fl_Widget::handle(event);
|
||||
}
|
||||
}
|
||||
public:
|
||||
RadialStatus(int _x, int _y, int _w, int _h, const char *_label = 0):
|
||||
Fl_Slider(_x, _y, _w, _h, _label)
|
||||
{
|
||||
x = _x;
|
||||
y = _y;
|
||||
w = _w;
|
||||
h = _h;
|
||||
|
||||
label = _label;
|
||||
|
||||
previousAngle = -1;
|
||||
|
||||
_r = 1.0;
|
||||
_g = 0.48;
|
||||
_b = 0.0;
|
||||
|
||||
_bgr = 0.11;
|
||||
_bgg = 0.11;
|
||||
_bgb = 0.11;
|
||||
|
||||
highlight = false;
|
||||
mouseOver = false;
|
||||
|
||||
_recording = false;
|
||||
}
|
||||
|
||||
bool _recording;
|
||||
void recording(bool r)
|
||||
{
|
||||
_recording = r;
|
||||
redraw();
|
||||
}
|
||||
|
||||
bool mouseOver;
|
||||
bool highlight;
|
||||
int x, y, w, h;
|
||||
const char* label;
|
||||
|
||||
int previousAngle;
|
||||
|
||||
float _r, _g, _b; // foreground colour
|
||||
float _bgr, _bgg, _bgb; // background colour
|
||||
float _outr, _outg, _outb; // outline colour
|
||||
|
||||
void setColor(float r, float g, float b)
|
||||
{
|
||||
_r = r;
|
||||
_g = g;
|
||||
_b = b;
|
||||
}
|
||||
|
||||
void setBgColor(float r, float g, float b)
|
||||
{
|
||||
_bgr = r;
|
||||
_bgg = g;
|
||||
_bgb = b;
|
||||
}
|
||||
|
||||
void draw()
|
||||
{
|
||||
// check that its a new "segment" to redraw
|
||||
int newAngle = (value() * 16);
|
||||
|
||||
if (damage() & FL_DAMAGE_ALL &&
|
||||
previousAngle != newAngle ) {
|
||||
cairo_t *cr = Fl::cairo_cc();
|
||||
|
||||
cairo_save( cr );
|
||||
|
||||
int xc = (w) / 2.f;
|
||||
int yc = (h) / 2.f;
|
||||
|
||||
int radius = xc > yc ? yc : xc;
|
||||
radius -= 10;
|
||||
|
||||
float angle = newAngle / 16.f;
|
||||
|
||||
cairo_set_line_cap ( cr, CAIRO_LINE_CAP_ROUND );
|
||||
//cairo_move_to( cr, x + xc, y + yc );
|
||||
cairo_arc( cr, x + xc, y + yc, radius, -(3.1415/2), angle * 6.28 - (3.1415/2) );
|
||||
cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.5 );
|
||||
cairo_set_line_width(cr, 12);
|
||||
cairo_stroke_preserve(cr);
|
||||
|
||||
cairo_set_source_rgba (cr, 1.0, 0.48, 0.0, 1 );
|
||||
cairo_set_line_width(cr, 8.2);
|
||||
cairo_stroke(cr);
|
||||
|
||||
|
||||
// recording?
|
||||
if ( _recording ) {
|
||||
cairo_set_source_rgba(cr,1.0,0.0,0.0, 0.8);
|
||||
cairo_arc(cr, x + xc, y + yc, radius-4, 0, 2 * 3.1415);
|
||||
cairo_fill_preserve(cr);
|
||||
cairo_set_source_rgba(cr,0.0,0.0,0.0, 0.8);
|
||||
cairo_set_line_width(cr, 2.2);
|
||||
cairo_stroke(cr);
|
||||
|
||||
// color of internal dot depending on rec state
|
||||
cairo_set_source_rgba(cr,0.0,0.0,0.0, 1);
|
||||
} else {
|
||||
cairo_set_source_rgba(cr,0.3,0.3,0.3, 1);
|
||||
}
|
||||
|
||||
// inside circle
|
||||
cairo_arc(cr, x + xc, y + yc, 10, 0, 2 * 3.1415);
|
||||
cairo_set_line_width(cr, 4.2);
|
||||
cairo_fill(cr);
|
||||
|
||||
cairo_restore( cr );
|
||||
|
||||
draw_label();
|
||||
}
|
||||
}
|
||||
|
||||
void resize(int X, int Y, int W, int H)
|
||||
{
|
||||
Fl_Widget::resize(X,Y,W,H);
|
||||
x = X;
|
||||
y = Y;
|
||||
w = W;
|
||||
h = H;
|
||||
redraw();
|
||||
}
|
||||
|
||||
int handle(int event)
|
||||
{
|
||||
switch(event) {
|
||||
case FL_PUSH:
|
||||
highlight = 1;
|
||||
redraw();
|
||||
return 1;
|
||||
case FL_DRAG: {
|
||||
int t = Fl::event_inside(this);
|
||||
if (t != highlight) {
|
||||
highlight = t;
|
||||
redraw();
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
case FL_ENTER:
|
||||
mouseOver = true;
|
||||
redraw();
|
||||
return 1;
|
||||
case FL_LEAVE:
|
||||
mouseOver = false;
|
||||
redraw();
|
||||
return 1;
|
||||
case FL_RELEASE:
|
||||
if (highlight) {
|
||||
highlight = 0;
|
||||
redraw();
|
||||
do_callback();
|
||||
}
|
||||
return 1;
|
||||
case FL_SHORTCUT:
|
||||
if ( test_shortcut() ) {
|
||||
do_callback();
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
default:
|
||||
return Fl_Widget::handle(event);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // Avtk
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -27,190 +27,212 @@ namespace Avtk
|
|||
|
||||
class Reverb : public Fl_Slider
|
||||
{
|
||||
public:
|
||||
Reverb(int _x, int _y, int _w, int _h, const char *_label =0):
|
||||
Fl_Slider(_x, _y, _w, _h, _label)
|
||||
{
|
||||
x = _x;
|
||||
y = _y;
|
||||
w = _w;
|
||||
h = _h;
|
||||
|
||||
amp = 0.5;
|
||||
s = 0.5;
|
||||
damp= 0.5;
|
||||
|
||||
active = false;
|
||||
|
||||
label = _label;
|
||||
|
||||
highlight = false;
|
||||
mouseOver = false;
|
||||
}
|
||||
|
||||
void size(float v) { s = v; redraw(); }
|
||||
void wet(float v) { amp = v; redraw(); }
|
||||
void damping(float v){damp = v; redraw();}
|
||||
|
||||
float size(){return s;}
|
||||
float wet (){return amp;}
|
||||
float damping(){return damp;}
|
||||
|
||||
bool getActive(){return active;}
|
||||
void setActive(bool a){active = a; redraw();}
|
||||
|
||||
float s;
|
||||
float amp;
|
||||
float damp;
|
||||
|
||||
bool active;
|
||||
|
||||
bool mouseOver;
|
||||
bool highlight;
|
||||
int x, y, w, h;
|
||||
const char* label;
|
||||
|
||||
void draw()
|
||||
{
|
||||
if (damage() & FL_DAMAGE_ALL)
|
||||
{
|
||||
cairo_t *cr = Fl::cairo_cc();
|
||||
|
||||
cairo_save( cr );
|
||||
|
||||
// graph
|
||||
cairo_rectangle( cr, x, y, w, h );
|
||||
cairo_set_source_rgb( cr,28 / 255.f, 28 / 255.f , 28 / 255.f );
|
||||
cairo_fill(cr);
|
||||
|
||||
|
||||
// set up dashed lines, 1 px off, 1 px on
|
||||
double dashes[1];
|
||||
dashes[0] = 2.0;
|
||||
|
||||
cairo_set_dash ( cr, dashes, 1, 0.0);
|
||||
|
||||
// loop over each 2nd line, drawing dots
|
||||
cairo_set_line_width(cr, 1.0);
|
||||
cairo_set_source_rgb(cr, 0.4,0.4,0.4);
|
||||
for ( int i = 0; i < 4; i++ )
|
||||
{
|
||||
cairo_move_to( cr, x + ((w / 4.f)*i), y );
|
||||
cairo_line_to( cr, x + ((w / 4.f)*i), y + h );
|
||||
}
|
||||
for ( int i = 0; i < 4; i++ )
|
||||
{
|
||||
cairo_move_to( cr, x , y + ((h / 4.f)*i) );
|
||||
cairo_line_to( cr, x + w, y + ((h / 4.f)*i) );
|
||||
}
|
||||
cairo_set_source_rgba( cr, 66 / 255.f, 66 / 255.f , 66 / 255.f , 0.5 );
|
||||
cairo_stroke(cr);
|
||||
cairo_set_dash ( cr, dashes, 0, 0.0);
|
||||
|
||||
// draw "damping" control
|
||||
cairo_move_to( cr, x+w*0.1 , y + h*0.85 - (h*0.7*amp));
|
||||
cairo_line_to( cr, x+w*0.1 + (w-20)*damp, y + h*0.85 - (h*0.7*amp));
|
||||
cairo_set_source_rgba(cr, 1.0, 0.48, 0, 1);
|
||||
cairo_set_line_join( cr, CAIRO_LINE_JOIN_ROUND);
|
||||
cairo_set_line_cap ( cr, CAIRO_LINE_CAP_ROUND);
|
||||
cairo_set_line_width(cr, 1.9);
|
||||
cairo_stroke( cr );
|
||||
|
||||
// draw reverb triangle
|
||||
cairo_move_to( cr, x , y + h*0.99 );
|
||||
cairo_line_to( cr, x + w*0.1, y + h*0.85 - (h*0.7*amp));
|
||||
cairo_line_to( cr, x + w*0.3+w*0.7*s, y + (h*0.99));
|
||||
|
||||
// stroke
|
||||
cairo_set_source_rgba( cr, 0 / 255.f, 153 / 255.f , 255 / 255.f , 0.21 );
|
||||
cairo_fill_preserve(cr);
|
||||
cairo_set_source_rgba( cr, 0 / 255.f, 153 / 255.f , 255 / 255.f , 1 );
|
||||
cairo_set_line_width(cr, 1.2);
|
||||
cairo_stroke( cr );
|
||||
|
||||
// stroke rim
|
||||
cairo_rectangle(cr, x, y, w, h);
|
||||
//cairo_set_source_rgba( cr, 0 / 255.f, 153 / 255.f , 255 / 255.f , 1 );
|
||||
cairo_set_source_rgba( cr, 126 / 255.f, 126 / 255.f , 126 / 255.f , 0.8 );
|
||||
cairo_set_line_width(cr, 0.9);
|
||||
cairo_stroke( cr );
|
||||
|
||||
if ( !active )
|
||||
{
|
||||
// big grey X
|
||||
cairo_set_line_width(cr, 12.0);
|
||||
cairo_set_source_rgba(cr, 0.0,0.0,0.0, 1.0);
|
||||
|
||||
cairo_move_to( cr, x + (3 * w / 4.f), y + ( h / 4.f ) );
|
||||
cairo_line_to( cr, x + (w / 4.f), y + ( 3 *h / 4.f ) );
|
||||
|
||||
cairo_move_to( cr, x + (w / 4.f), y + ( h / 4.f ) );
|
||||
cairo_line_to( cr, x + (3 * w / 4.f), y + ( 3 *h / 4.f ) );
|
||||
cairo_set_line_cap ( cr, CAIRO_LINE_CAP_BUTT);
|
||||
cairo_stroke( cr );
|
||||
}
|
||||
|
||||
cairo_restore( cr );
|
||||
|
||||
draw_label();
|
||||
}
|
||||
}
|
||||
|
||||
void resize(int X, int Y, int W, int H)
|
||||
{
|
||||
Fl_Widget::resize(X,Y,W,H);
|
||||
x = X;
|
||||
y = Y;
|
||||
w = W;
|
||||
h = H;
|
||||
redraw();
|
||||
}
|
||||
|
||||
int handle(int event)
|
||||
{
|
||||
switch(event) {
|
||||
case FL_PUSH:
|
||||
highlight = 1;
|
||||
if ( Fl::event_button() == FL_RIGHT_MOUSE )
|
||||
{
|
||||
active = !active;
|
||||
redraw();
|
||||
do_callback();
|
||||
}
|
||||
return 1;
|
||||
case FL_DRAG: {
|
||||
int t = Fl::event_inside(this);
|
||||
if (t != highlight) {
|
||||
highlight = t;
|
||||
redraw();
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
case FL_ENTER:
|
||||
mouseOver = true;
|
||||
redraw();
|
||||
return 1;
|
||||
case FL_LEAVE:
|
||||
mouseOver = false;
|
||||
redraw();
|
||||
return 1;
|
||||
case FL_RELEASE:
|
||||
if (highlight) {
|
||||
highlight = 0;
|
||||
redraw();
|
||||
}
|
||||
return 1;
|
||||
case FL_SHORTCUT:
|
||||
if ( test_shortcut() )
|
||||
{
|
||||
do_callback();
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
default:
|
||||
return Fl_Widget::handle(event);
|
||||
}
|
||||
}
|
||||
public:
|
||||
Reverb(int _x, int _y, int _w, int _h, const char *_label =0):
|
||||
Fl_Slider(_x, _y, _w, _h, _label)
|
||||
{
|
||||
x = _x;
|
||||
y = _y;
|
||||
w = _w;
|
||||
h = _h;
|
||||
|
||||
amp = 0.5;
|
||||
s = 0.5;
|
||||
damp= 0.5;
|
||||
|
||||
active = false;
|
||||
|
||||
label = _label;
|
||||
|
||||
highlight = false;
|
||||
mouseOver = false;
|
||||
}
|
||||
|
||||
void size(float v)
|
||||
{
|
||||
s = v;
|
||||
redraw();
|
||||
}
|
||||
void wet(float v)
|
||||
{
|
||||
amp = v;
|
||||
redraw();
|
||||
}
|
||||
void damping(float v)
|
||||
{
|
||||
damp = v;
|
||||
redraw();
|
||||
}
|
||||
|
||||
float size()
|
||||
{
|
||||
return s;
|
||||
}
|
||||
float wet ()
|
||||
{
|
||||
return amp;
|
||||
}
|
||||
float damping()
|
||||
{
|
||||
return damp;
|
||||
}
|
||||
|
||||
bool getActive()
|
||||
{
|
||||
return active;
|
||||
}
|
||||
void setActive(bool a)
|
||||
{
|
||||
active = a;
|
||||
redraw();
|
||||
}
|
||||
|
||||
float s;
|
||||
float amp;
|
||||
float damp;
|
||||
|
||||
bool active;
|
||||
|
||||
bool mouseOver;
|
||||
bool highlight;
|
||||
int x, y, w, h;
|
||||
const char* label;
|
||||
|
||||
void draw()
|
||||
{
|
||||
if (damage() & FL_DAMAGE_ALL) {
|
||||
cairo_t *cr = Fl::cairo_cc();
|
||||
|
||||
cairo_save( cr );
|
||||
|
||||
// graph
|
||||
cairo_rectangle( cr, x, y, w, h );
|
||||
cairo_set_source_rgb( cr,28 / 255.f, 28 / 255.f , 28 / 255.f );
|
||||
cairo_fill(cr);
|
||||
|
||||
|
||||
// set up dashed lines, 1 px off, 1 px on
|
||||
double dashes[1];
|
||||
dashes[0] = 2.0;
|
||||
|
||||
cairo_set_dash ( cr, dashes, 1, 0.0);
|
||||
|
||||
// loop over each 2nd line, drawing dots
|
||||
cairo_set_line_width(cr, 1.0);
|
||||
cairo_set_source_rgb(cr, 0.4,0.4,0.4);
|
||||
for ( int i = 0; i < 4; i++ ) {
|
||||
cairo_move_to( cr, x + ((w / 4.f)*i), y );
|
||||
cairo_line_to( cr, x + ((w / 4.f)*i), y + h );
|
||||
}
|
||||
for ( int i = 0; i < 4; i++ ) {
|
||||
cairo_move_to( cr, x , y + ((h / 4.f)*i) );
|
||||
cairo_line_to( cr, x + w, y + ((h / 4.f)*i) );
|
||||
}
|
||||
cairo_set_source_rgba( cr, 66 / 255.f, 66 / 255.f , 66 / 255.f , 0.5 );
|
||||
cairo_stroke(cr);
|
||||
cairo_set_dash ( cr, dashes, 0, 0.0);
|
||||
|
||||
// draw "damping" control
|
||||
cairo_move_to( cr, x+w*0.1 , y + h*0.85 - (h*0.7*amp));
|
||||
cairo_line_to( cr, x+w*0.1 + (w-20)*damp, y + h*0.85 - (h*0.7*amp));
|
||||
cairo_set_source_rgba(cr, 1.0, 0.48, 0, 1);
|
||||
cairo_set_line_join( cr, CAIRO_LINE_JOIN_ROUND);
|
||||
cairo_set_line_cap ( cr, CAIRO_LINE_CAP_ROUND);
|
||||
cairo_set_line_width(cr, 1.9);
|
||||
cairo_stroke( cr );
|
||||
|
||||
// draw reverb triangle
|
||||
cairo_move_to( cr, x , y + h*0.99 );
|
||||
cairo_line_to( cr, x + w*0.1, y + h*0.85 - (h*0.7*amp));
|
||||
cairo_line_to( cr, x + w*0.3+w*0.7*s, y + (h*0.99));
|
||||
|
||||
// stroke
|
||||
cairo_set_source_rgba( cr, 0 / 255.f, 153 / 255.f , 255 / 255.f , 0.21 );
|
||||
cairo_fill_preserve(cr);
|
||||
cairo_set_source_rgba( cr, 0 / 255.f, 153 / 255.f , 255 / 255.f , 1 );
|
||||
cairo_set_line_width(cr, 1.2);
|
||||
cairo_stroke( cr );
|
||||
|
||||
// stroke rim
|
||||
cairo_rectangle(cr, x, y, w, h);
|
||||
//cairo_set_source_rgba( cr, 0 / 255.f, 153 / 255.f , 255 / 255.f , 1 );
|
||||
cairo_set_source_rgba( cr, 126 / 255.f, 126 / 255.f , 126 / 255.f , 0.8 );
|
||||
cairo_set_line_width(cr, 0.9);
|
||||
cairo_stroke( cr );
|
||||
|
||||
if ( !active ) {
|
||||
// big grey X
|
||||
cairo_set_line_width(cr, 12.0);
|
||||
cairo_set_source_rgba(cr, 0.0,0.0,0.0, 1.0);
|
||||
|
||||
cairo_move_to( cr, x + (3 * w / 4.f), y + ( h / 4.f ) );
|
||||
cairo_line_to( cr, x + (w / 4.f), y + ( 3 *h / 4.f ) );
|
||||
|
||||
cairo_move_to( cr, x + (w / 4.f), y + ( h / 4.f ) );
|
||||
cairo_line_to( cr, x + (3 * w / 4.f), y + ( 3 *h / 4.f ) );
|
||||
cairo_set_line_cap ( cr, CAIRO_LINE_CAP_BUTT);
|
||||
cairo_stroke( cr );
|
||||
}
|
||||
|
||||
cairo_restore( cr );
|
||||
|
||||
draw_label();
|
||||
}
|
||||
}
|
||||
|
||||
void resize(int X, int Y, int W, int H)
|
||||
{
|
||||
Fl_Widget::resize(X,Y,W,H);
|
||||
x = X;
|
||||
y = Y;
|
||||
w = W;
|
||||
h = H;
|
||||
redraw();
|
||||
}
|
||||
|
||||
int handle(int event)
|
||||
{
|
||||
switch(event) {
|
||||
case FL_PUSH:
|
||||
highlight = 1;
|
||||
if ( Fl::event_button() == FL_RIGHT_MOUSE ) {
|
||||
active = !active;
|
||||
redraw();
|
||||
do_callback();
|
||||
}
|
||||
return 1;
|
||||
case FL_DRAG: {
|
||||
int t = Fl::event_inside(this);
|
||||
if (t != highlight) {
|
||||
highlight = t;
|
||||
redraw();
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
case FL_ENTER:
|
||||
mouseOver = true;
|
||||
redraw();
|
||||
return 1;
|
||||
case FL_LEAVE:
|
||||
mouseOver = false;
|
||||
redraw();
|
||||
return 1;
|
||||
case FL_RELEASE:
|
||||
if (highlight) {
|
||||
highlight = 0;
|
||||
redraw();
|
||||
}
|
||||
return 1;
|
||||
case FL_SHORTCUT:
|
||||
if ( test_shortcut() ) {
|
||||
do_callback();
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
default:
|
||||
return Fl_Widget::handle(event);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // Avtk
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -29,185 +29,198 @@
|
|||
|
||||
namespace Avtk
|
||||
{
|
||||
|
||||
|
||||
class SidechainGain : public Fl_Slider
|
||||
{
|
||||
public:
|
||||
SidechainGain(int _x, int _y, int _w, int _h, const char *_label = 0):
|
||||
Fl_Slider(_x, _y, _w, _h, _label)
|
||||
{
|
||||
x = _x;
|
||||
y = _y;
|
||||
w = _w;
|
||||
h = _h;
|
||||
|
||||
label = _label;
|
||||
|
||||
mouseClickedX = 0;
|
||||
mouseClickedY = 0;
|
||||
mouseClicked = false;
|
||||
|
||||
active = true;
|
||||
highlight = false;
|
||||
|
||||
_threshold = 1.0;
|
||||
_target = 1.f;
|
||||
_reduce = 1.f;
|
||||
_release = 0.5;
|
||||
|
||||
_sidechainAmp = 0;
|
||||
}
|
||||
|
||||
void threshold(float t) {_threshold = t; redraw();}
|
||||
void reduce (float r) {_reduce = r; redraw();}
|
||||
void release (float r) {_release = r; redraw();}
|
||||
|
||||
/// sets the sidechain amplitude
|
||||
void sidechain(float s) {_sidechainAmp = s; redraw();}
|
||||
|
||||
bool active;
|
||||
bool highlight;
|
||||
int x, y, w, h;
|
||||
const char* label;
|
||||
|
||||
int mouseClickedX;
|
||||
int mouseClickedY;
|
||||
bool mouseClicked;
|
||||
bool mouseRightClicked;
|
||||
|
||||
float _threshold;
|
||||
float _target;
|
||||
float _reduce;
|
||||
float _release;
|
||||
|
||||
float _sidechainAmp;
|
||||
|
||||
void set_active(bool a)
|
||||
{
|
||||
active = a;
|
||||
redraw();
|
||||
}
|
||||
|
||||
void draw()
|
||||
{
|
||||
if (damage() & FL_DAMAGE_ALL)
|
||||
{
|
||||
cairo_t *cr = Fl::cairo_cc();
|
||||
|
||||
cairo_save( cr );
|
||||
|
||||
cairo_set_line_width(cr, 1.5);
|
||||
|
||||
|
||||
// fill background
|
||||
cairo_rectangle( cr, x, y, w, h);
|
||||
cairo_set_source_rgb( cr, 28 / 255.f, 28 / 255.f , 28 / 255.f );
|
||||
cairo_fill_preserve( cr );
|
||||
cairo_clip( cr );
|
||||
|
||||
|
||||
// set up dashed lines, 1 px off, 1 px on
|
||||
double dashes[1];
|
||||
dashes[0] = 2.0;
|
||||
|
||||
cairo_set_dash ( cr, dashes, 1, 0.0);
|
||||
cairo_set_line_width( cr, 1.0);
|
||||
|
||||
// loop over each 2nd line, drawing dots
|
||||
cairo_set_line_width(cr, 1.0);
|
||||
cairo_set_source_rgb(cr, 0.4,0.4,0.4);
|
||||
for ( int i = 0; i < 4; i++ )
|
||||
{
|
||||
cairo_move_to( cr, x + ((w / 4.f)*i), y );
|
||||
cairo_line_to( cr, x + ((w / 4.f)*i), y + h );
|
||||
}
|
||||
for ( int i = 0; i < 4; i++ )
|
||||
{
|
||||
cairo_move_to( cr, x , y + ((h / 4.f)*i) );
|
||||
cairo_line_to( cr, x + w, y + ((h / 4.f)*i) );
|
||||
}
|
||||
|
||||
cairo_set_source_rgba( cr, 66 / 255.f, 66 / 255.f , 66 / 255.f , 0.5 );
|
||||
cairo_stroke(cr);
|
||||
cairo_set_dash ( cr, dashes, 0, 0.0);
|
||||
|
||||
|
||||
// draw threshold / ducked line
|
||||
cairo_move_to( cr, x + w * 0.750 - (w * 0.5 * (1-_threshold)), y );
|
||||
|
||||
cairo_line_to( cr, x + w * 0.750 - (w * 0.5 * (1-_threshold)) + _sidechainAmp* _reduce*( w * 0.5 ), y + h / 2 );
|
||||
|
||||
cairo_line_to( cr, x + w * 0.750 - (w * 0.5 * (1-_threshold)), y + h );
|
||||
|
||||
cairo_line_to( cr, x + w , y + h );
|
||||
cairo_line_to( cr, x + w , y );
|
||||
cairo_close_path( cr );
|
||||
cairo_set_source_rgba( cr, 0 / 255.f, 153 / 255.f , 255 / 255.f , 0.21 );
|
||||
cairo_fill_preserve( cr );
|
||||
cairo_set_source_rgba( cr, 0 / 255.f, 153 / 255.f , 255 / 255.f , 1 );
|
||||
cairo_stroke( cr );
|
||||
|
||||
// _sidechainAmp => arrow
|
||||
cairo_move_to( cr, x + w * 0.00 * _sidechainAmp, y + h * 0.4 - (h*0.1*_sidechainAmp) );
|
||||
cairo_line_to( cr, x + w * 0.65 * _sidechainAmp, y + h * 0.4 );
|
||||
cairo_line_to( cr, x + w * 0.1 + w * 0.65 * _sidechainAmp, y + h * 0.5 );
|
||||
cairo_line_to( cr, x + w * 0.65 * _sidechainAmp, y + h * 0.6 );
|
||||
cairo_line_to( cr, x + w * 0.00 * _sidechainAmp, y + h * 0.6 + (h*0.1*_sidechainAmp) );
|
||||
cairo_close_path( cr );
|
||||
cairo_set_source_rgba( cr, 1.0, 0.48, 0.f , 0.21 );
|
||||
cairo_fill_preserve( cr );
|
||||
cairo_set_source_rgba( cr, 1.0, 0.48, 0.f , 1 );
|
||||
cairo_stroke( cr );
|
||||
|
||||
|
||||
// _release horizontal line
|
||||
cairo_move_to( cr, x , y + h * 0.25 + h/2 * _release );
|
||||
cairo_line_to( cr, x + w, y + h * 0.25 + h/2 * _release );
|
||||
cairo_set_source_rgba( cr, 1.0, 0.0, 0.f , 1 );
|
||||
cairo_stroke( cr );
|
||||
|
||||
// stroke outline
|
||||
cairo_rectangle(cr, x, y, w, h);
|
||||
cairo_set_source_rgba( cr, 126 / 255.f, 126 / 255.f , 126 / 255.f , 0.8 );
|
||||
cairo_set_line_width(cr, 1.9);
|
||||
cairo_stroke( cr );
|
||||
|
||||
if ( !active )
|
||||
{
|
||||
// big grey X
|
||||
cairo_set_line_width(cr, 20.0);
|
||||
cairo_set_source_rgba(cr, 0.4,0.4,0.4, 0.7);
|
||||
|
||||
cairo_move_to( cr, x + (3 * w / 4.f), y + ( h / 4.f ) );
|
||||
cairo_line_to( cr, x + (w / 4.f), y + ( 3 *h / 4.f ) );
|
||||
|
||||
cairo_move_to( cr, x + (w / 4.f), y + ( h / 4.f ) );
|
||||
cairo_line_to( cr, x + (3 * w / 4.f), y + ( 3 *h / 4.f ) );
|
||||
cairo_set_line_cap ( cr, CAIRO_LINE_CAP_BUTT);
|
||||
cairo_stroke( cr );
|
||||
}
|
||||
|
||||
cairo_restore( cr );
|
||||
}
|
||||
}
|
||||
|
||||
void resize(int X, int Y, int W, int H)
|
||||
{
|
||||
Fl_Widget::resize(X,Y,W,H);
|
||||
x = X;
|
||||
y = Y;
|
||||
w = W;
|
||||
h = H;
|
||||
redraw();
|
||||
}
|
||||
|
||||
int handle(int event)
|
||||
{ //TODO needed?
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private:
|
||||
public:
|
||||
SidechainGain(int _x, int _y, int _w, int _h, const char *_label = 0):
|
||||
Fl_Slider(_x, _y, _w, _h, _label)
|
||||
{
|
||||
x = _x;
|
||||
y = _y;
|
||||
w = _w;
|
||||
h = _h;
|
||||
|
||||
label = _label;
|
||||
|
||||
mouseClickedX = 0;
|
||||
mouseClickedY = 0;
|
||||
mouseClicked = false;
|
||||
|
||||
active = true;
|
||||
highlight = false;
|
||||
|
||||
_threshold = 1.0;
|
||||
_target = 1.f;
|
||||
_reduce = 1.f;
|
||||
_release = 0.5;
|
||||
|
||||
_sidechainAmp = 0;
|
||||
}
|
||||
|
||||
void threshold(float t)
|
||||
{
|
||||
_threshold = t;
|
||||
redraw();
|
||||
}
|
||||
void reduce (float r)
|
||||
{
|
||||
_reduce = r;
|
||||
redraw();
|
||||
}
|
||||
void release (float r)
|
||||
{
|
||||
_release = r;
|
||||
redraw();
|
||||
}
|
||||
|
||||
/// sets the sidechain amplitude
|
||||
void sidechain(float s)
|
||||
{
|
||||
_sidechainAmp = s;
|
||||
redraw();
|
||||
}
|
||||
|
||||
bool active;
|
||||
bool highlight;
|
||||
int x, y, w, h;
|
||||
const char* label;
|
||||
|
||||
int mouseClickedX;
|
||||
int mouseClickedY;
|
||||
bool mouseClicked;
|
||||
bool mouseRightClicked;
|
||||
|
||||
float _threshold;
|
||||
float _target;
|
||||
float _reduce;
|
||||
float _release;
|
||||
|
||||
float _sidechainAmp;
|
||||
|
||||
void set_active(bool a)
|
||||
{
|
||||
active = a;
|
||||
redraw();
|
||||
}
|
||||
|
||||
void draw()
|
||||
{
|
||||
if (damage() & FL_DAMAGE_ALL) {
|
||||
cairo_t *cr = Fl::cairo_cc();
|
||||
|
||||
cairo_save( cr );
|
||||
|
||||
cairo_set_line_width(cr, 1.5);
|
||||
|
||||
|
||||
// fill background
|
||||
cairo_rectangle( cr, x, y, w, h);
|
||||
cairo_set_source_rgb( cr, 28 / 255.f, 28 / 255.f , 28 / 255.f );
|
||||
cairo_fill_preserve( cr );
|
||||
cairo_clip( cr );
|
||||
|
||||
|
||||
// set up dashed lines, 1 px off, 1 px on
|
||||
double dashes[1];
|
||||
dashes[0] = 2.0;
|
||||
|
||||
cairo_set_dash ( cr, dashes, 1, 0.0);
|
||||
cairo_set_line_width( cr, 1.0);
|
||||
|
||||
// loop over each 2nd line, drawing dots
|
||||
cairo_set_line_width(cr, 1.0);
|
||||
cairo_set_source_rgb(cr, 0.4,0.4,0.4);
|
||||
for ( int i = 0; i < 4; i++ ) {
|
||||
cairo_move_to( cr, x + ((w / 4.f)*i), y );
|
||||
cairo_line_to( cr, x + ((w / 4.f)*i), y + h );
|
||||
}
|
||||
for ( int i = 0; i < 4; i++ ) {
|
||||
cairo_move_to( cr, x , y + ((h / 4.f)*i) );
|
||||
cairo_line_to( cr, x + w, y + ((h / 4.f)*i) );
|
||||
}
|
||||
|
||||
cairo_set_source_rgba( cr, 66 / 255.f, 66 / 255.f , 66 / 255.f , 0.5 );
|
||||
cairo_stroke(cr);
|
||||
cairo_set_dash ( cr, dashes, 0, 0.0);
|
||||
|
||||
|
||||
// draw threshold / ducked line
|
||||
cairo_move_to( cr, x + w * 0.750 - (w * 0.5 * (1-_threshold)), y );
|
||||
|
||||
cairo_line_to( cr, x + w * 0.750 - (w * 0.5 * (1-_threshold)) + _sidechainAmp* _reduce*( w * 0.5 ), y + h / 2 );
|
||||
|
||||
cairo_line_to( cr, x + w * 0.750 - (w * 0.5 * (1-_threshold)), y + h );
|
||||
|
||||
cairo_line_to( cr, x + w , y + h );
|
||||
cairo_line_to( cr, x + w , y );
|
||||
cairo_close_path( cr );
|
||||
cairo_set_source_rgba( cr, 0 / 255.f, 153 / 255.f , 255 / 255.f , 0.21 );
|
||||
cairo_fill_preserve( cr );
|
||||
cairo_set_source_rgba( cr, 0 / 255.f, 153 / 255.f , 255 / 255.f , 1 );
|
||||
cairo_stroke( cr );
|
||||
|
||||
// _sidechainAmp => arrow
|
||||
cairo_move_to( cr, x + w * 0.00 * _sidechainAmp, y + h * 0.4 - (h*0.1*_sidechainAmp) );
|
||||
cairo_line_to( cr, x + w * 0.65 * _sidechainAmp, y + h * 0.4 );
|
||||
cairo_line_to( cr, x + w * 0.1 + w * 0.65 * _sidechainAmp, y + h * 0.5 );
|
||||
cairo_line_to( cr, x + w * 0.65 * _sidechainAmp, y + h * 0.6 );
|
||||
cairo_line_to( cr, x + w * 0.00 * _sidechainAmp, y + h * 0.6 + (h*0.1*_sidechainAmp) );
|
||||
cairo_close_path( cr );
|
||||
cairo_set_source_rgba( cr, 1.0, 0.48, 0.f , 0.21 );
|
||||
cairo_fill_preserve( cr );
|
||||
cairo_set_source_rgba( cr, 1.0, 0.48, 0.f , 1 );
|
||||
cairo_stroke( cr );
|
||||
|
||||
|
||||
// _release horizontal line
|
||||
cairo_move_to( cr, x , y + h * 0.25 + h/2 * _release );
|
||||
cairo_line_to( cr, x + w, y + h * 0.25 + h/2 * _release );
|
||||
cairo_set_source_rgba( cr, 1.0, 0.0, 0.f , 1 );
|
||||
cairo_stroke( cr );
|
||||
|
||||
// stroke outline
|
||||
cairo_rectangle(cr, x, y, w, h);
|
||||
cairo_set_source_rgba( cr, 126 / 255.f, 126 / 255.f , 126 / 255.f , 0.8 );
|
||||
cairo_set_line_width(cr, 1.9);
|
||||
cairo_stroke( cr );
|
||||
|
||||
if ( !active ) {
|
||||
// big grey X
|
||||
cairo_set_line_width(cr, 20.0);
|
||||
cairo_set_source_rgba(cr, 0.4,0.4,0.4, 0.7);
|
||||
|
||||
cairo_move_to( cr, x + (3 * w / 4.f), y + ( h / 4.f ) );
|
||||
cairo_line_to( cr, x + (w / 4.f), y + ( 3 *h / 4.f ) );
|
||||
|
||||
cairo_move_to( cr, x + (w / 4.f), y + ( h / 4.f ) );
|
||||
cairo_line_to( cr, x + (3 * w / 4.f), y + ( 3 *h / 4.f ) );
|
||||
cairo_set_line_cap ( cr, CAIRO_LINE_CAP_BUTT);
|
||||
cairo_stroke( cr );
|
||||
}
|
||||
|
||||
cairo_restore( cr );
|
||||
}
|
||||
}
|
||||
|
||||
void resize(int X, int Y, int W, int H)
|
||||
{
|
||||
Fl_Widget::resize(X,Y,W,H);
|
||||
x = X;
|
||||
y = Y;
|
||||
w = W;
|
||||
h = H;
|
||||
redraw();
|
||||
}
|
||||
|
||||
int handle(int event)
|
||||
{
|
||||
//TODO needed?
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
} // Avtk
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -29,171 +29,166 @@ namespace Avtk
|
|||
|
||||
class UnitState
|
||||
{
|
||||
public:
|
||||
enum State {
|
||||
UNIT_EMPTY = 0,
|
||||
UNIT_LOADED,
|
||||
UNIT_QUEUED,
|
||||
UNIT_PLAYING,
|
||||
UNIT_RECORDING,
|
||||
UNIT_STOPPING,
|
||||
};
|
||||
UnitState()
|
||||
{
|
||||
state = UNIT_EMPTY;
|
||||
name = "Clip";
|
||||
}
|
||||
UnitState(std::string n)
|
||||
{
|
||||
state = UNIT_EMPTY;
|
||||
name = n;
|
||||
}
|
||||
|
||||
State state;
|
||||
std::string name;
|
||||
public:
|
||||
enum State {
|
||||
UNIT_EMPTY = 0,
|
||||
UNIT_LOADED,
|
||||
UNIT_QUEUED,
|
||||
UNIT_PLAYING,
|
||||
UNIT_RECORDING,
|
||||
UNIT_STOPPING,
|
||||
};
|
||||
UnitState()
|
||||
{
|
||||
state = UNIT_EMPTY;
|
||||
name = "Clip";
|
||||
}
|
||||
UnitState(std::string n)
|
||||
{
|
||||
state = UNIT_EMPTY;
|
||||
name = n;
|
||||
}
|
||||
|
||||
State state;
|
||||
std::string name;
|
||||
};
|
||||
|
||||
class Unit : public Fl_Button
|
||||
{
|
||||
public:
|
||||
Unit(int _x, int _y, int _w, int _h, const char *_label):
|
||||
Fl_Button(_x, _y, _w, _h, _label)
|
||||
{
|
||||
x = _x;
|
||||
y = _y;
|
||||
w = _w;
|
||||
h = _h;
|
||||
|
||||
label = _label;
|
||||
|
||||
highlight = false;
|
||||
mouseOver = false;
|
||||
|
||||
clips[0].state = UnitState::UNIT_EMPTY;
|
||||
clips[1].state = UnitState::UNIT_LOADED;
|
||||
clips[2].state = UnitState::UNIT_QUEUED;
|
||||
clips[3].state = UnitState::UNIT_PLAYING;
|
||||
clips[4].state = UnitState::UNIT_RECORDING;
|
||||
clips[5].state = UnitState::UNIT_STOPPING;
|
||||
}
|
||||
|
||||
static const int numClips = 10;
|
||||
UnitState clips[numClips];
|
||||
|
||||
bool mouseOver;
|
||||
bool highlight;
|
||||
int x, y, w, h;
|
||||
const char* label;
|
||||
|
||||
void draw()
|
||||
{
|
||||
if (damage() & FL_DAMAGE_ALL)
|
||||
{
|
||||
if ( value() )
|
||||
{
|
||||
highlight = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
highlight = false;
|
||||
}
|
||||
|
||||
cairo_t *cr = Fl::cairo_cc();
|
||||
|
||||
cairo_save( cr );
|
||||
|
||||
cairo_rectangle( cr, x+2, y + 2, w - 2, h - 2 );
|
||||
cairo_set_source_rgba(cr, 66 / 255.f, 66 / 255.f , 66 / 255.f, 0.4);
|
||||
cairo_fill(cr);
|
||||
|
||||
//cairo_rectangle( cr, x+1, drawY, clipHeight - 2, clipHeight - 2 );
|
||||
/*
|
||||
cairo_rectangle( cr, x+1, drawY, clipWidth, clipHeight - 2 );
|
||||
|
||||
float alpha = 0.7;
|
||||
if (mouseOver) { alpha = 1; }
|
||||
cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, alpha);
|
||||
cairo_set_line_width( cr, 1.4);
|
||||
cairo_move_to( cr, x+clipHeight-1, drawY );
|
||||
cairo_line_to( cr, x+clipHeight-1, drawY + clipHeight - 2);
|
||||
cairo_stroke(cr);
|
||||
|
||||
// clip name
|
||||
cairo_move_to( cr, x+clipHeight-1+ 10, drawY + 15 );
|
||||
cairo_set_source_rgba( cr, 255 / 255.f, 255 / 255.f , 255 / 255.f , 1 );
|
||||
cairo_set_font_size( cr, 10 );
|
||||
cairo_show_text( cr, label );
|
||||
*/
|
||||
|
||||
// outline
|
||||
float alpha = 0.7;
|
||||
if (mouseOver) { alpha = 1; }
|
||||
cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, alpha);
|
||||
cairo_rectangle( cr, x+2, y + 2, w - 2, h - 2 );
|
||||
cairo_set_line_width( cr, 1.4);
|
||||
cairo_stroke( cr );
|
||||
|
||||
cairo_restore( cr );
|
||||
|
||||
draw_label();
|
||||
}
|
||||
}
|
||||
|
||||
void resize(int X, int Y, int W, int H)
|
||||
{
|
||||
Fl_Widget::resize(X,Y,W,H);
|
||||
x = X;
|
||||
y = Y;
|
||||
w = W;
|
||||
h = H;
|
||||
redraw();
|
||||
}
|
||||
|
||||
|
||||
|
||||
int handle(int event)
|
||||
{
|
||||
switch(event) {
|
||||
case FL_ACTIVATE:
|
||||
{
|
||||
}
|
||||
case FL_DEACTIVATE:
|
||||
{
|
||||
}
|
||||
return 1;
|
||||
case FL_PUSH:
|
||||
highlight = 1;
|
||||
do_callback();
|
||||
return 1;
|
||||
case FL_DRAG: {
|
||||
int t = Fl::event_inside(this);
|
||||
if (t != highlight) {
|
||||
highlight = t;
|
||||
redraw();
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
case FL_ENTER:
|
||||
mouseOver = true;
|
||||
redraw();
|
||||
return 1;
|
||||
case FL_LEAVE:
|
||||
mouseOver = false;
|
||||
redraw();
|
||||
return 1;
|
||||
case FL_RELEASE:
|
||||
return 1;
|
||||
case FL_SHORTCUT:
|
||||
if ( test_shortcut() )
|
||||
{
|
||||
do_callback();
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
default:
|
||||
return Fl_Widget::handle(event);
|
||||
}
|
||||
}
|
||||
public:
|
||||
Unit(int _x, int _y, int _w, int _h, const char *_label):
|
||||
Fl_Button(_x, _y, _w, _h, _label)
|
||||
{
|
||||
x = _x;
|
||||
y = _y;
|
||||
w = _w;
|
||||
h = _h;
|
||||
|
||||
label = _label;
|
||||
|
||||
highlight = false;
|
||||
mouseOver = false;
|
||||
|
||||
clips[0].state = UnitState::UNIT_EMPTY;
|
||||
clips[1].state = UnitState::UNIT_LOADED;
|
||||
clips[2].state = UnitState::UNIT_QUEUED;
|
||||
clips[3].state = UnitState::UNIT_PLAYING;
|
||||
clips[4].state = UnitState::UNIT_RECORDING;
|
||||
clips[5].state = UnitState::UNIT_STOPPING;
|
||||
}
|
||||
|
||||
static const int numClips = 10;
|
||||
UnitState clips[numClips];
|
||||
|
||||
bool mouseOver;
|
||||
bool highlight;
|
||||
int x, y, w, h;
|
||||
const char* label;
|
||||
|
||||
void draw()
|
||||
{
|
||||
if (damage() & FL_DAMAGE_ALL) {
|
||||
if ( value() ) {
|
||||
highlight = true;
|
||||
} else {
|
||||
highlight = false;
|
||||
}
|
||||
|
||||
cairo_t *cr = Fl::cairo_cc();
|
||||
|
||||
cairo_save( cr );
|
||||
|
||||
cairo_rectangle( cr, x+2, y + 2, w - 2, h - 2 );
|
||||
cairo_set_source_rgba(cr, 66 / 255.f, 66 / 255.f , 66 / 255.f, 0.4);
|
||||
cairo_fill(cr);
|
||||
|
||||
//cairo_rectangle( cr, x+1, drawY, clipHeight - 2, clipHeight - 2 );
|
||||
/*
|
||||
cairo_rectangle( cr, x+1, drawY, clipWidth, clipHeight - 2 );
|
||||
|
||||
float alpha = 0.7;
|
||||
if (mouseOver) { alpha = 1; }
|
||||
cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, alpha);
|
||||
cairo_set_line_width( cr, 1.4);
|
||||
cairo_move_to( cr, x+clipHeight-1, drawY );
|
||||
cairo_line_to( cr, x+clipHeight-1, drawY + clipHeight - 2);
|
||||
cairo_stroke(cr);
|
||||
|
||||
// clip name
|
||||
cairo_move_to( cr, x+clipHeight-1+ 10, drawY + 15 );
|
||||
cairo_set_source_rgba( cr, 255 / 255.f, 255 / 255.f , 255 / 255.f , 1 );
|
||||
cairo_set_font_size( cr, 10 );
|
||||
cairo_show_text( cr, label );
|
||||
*/
|
||||
|
||||
// outline
|
||||
float alpha = 0.7;
|
||||
if (mouseOver) {
|
||||
alpha = 1;
|
||||
}
|
||||
cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, alpha);
|
||||
cairo_rectangle( cr, x+2, y + 2, w - 2, h - 2 );
|
||||
cairo_set_line_width( cr, 1.4);
|
||||
cairo_stroke( cr );
|
||||
|
||||
cairo_restore( cr );
|
||||
|
||||
draw_label();
|
||||
}
|
||||
}
|
||||
|
||||
void resize(int X, int Y, int W, int H)
|
||||
{
|
||||
Fl_Widget::resize(X,Y,W,H);
|
||||
x = X;
|
||||
y = Y;
|
||||
w = W;
|
||||
h = H;
|
||||
redraw();
|
||||
}
|
||||
|
||||
|
||||
|
||||
int handle(int event)
|
||||
{
|
||||
switch(event) {
|
||||
case FL_ACTIVATE: {
|
||||
}
|
||||
case FL_DEACTIVATE: {
|
||||
}
|
||||
return 1;
|
||||
case FL_PUSH:
|
||||
highlight = 1;
|
||||
do_callback();
|
||||
return 1;
|
||||
case FL_DRAG: {
|
||||
int t = Fl::event_inside(this);
|
||||
if (t != highlight) {
|
||||
highlight = t;
|
||||
redraw();
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
case FL_ENTER:
|
||||
mouseOver = true;
|
||||
redraw();
|
||||
return 1;
|
||||
case FL_LEAVE:
|
||||
mouseOver = false;
|
||||
redraw();
|
||||
return 1;
|
||||
case FL_RELEASE:
|
||||
return 1;
|
||||
case FL_SHORTCUT:
|
||||
if ( test_shortcut() ) {
|
||||
do_callback();
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
default:
|
||||
return Fl_Widget::handle(event);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // Avtk
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -27,132 +27,130 @@ namespace Avtk
|
|||
{
|
||||
|
||||
Bindings::Bindings( int _x, int _y, int _w, int _h, const char *_label ) :
|
||||
Fl_Button(_x, _y, _w, _h, _label)
|
||||
Fl_Button(_x, _y, _w, _h, _label)
|
||||
{
|
||||
x = _x;
|
||||
y = _y;
|
||||
w = _w;
|
||||
h = _h;
|
||||
|
||||
label = _label;
|
||||
|
||||
bindYPx = 25;
|
||||
|
||||
highlight = false;
|
||||
mouseOver = false;
|
||||
x = _x;
|
||||
y = _y;
|
||||
w = _w;
|
||||
h = _h;
|
||||
|
||||
label = _label;
|
||||
|
||||
bindYPx = 25;
|
||||
|
||||
highlight = false;
|
||||
mouseOver = false;
|
||||
}
|
||||
|
||||
|
||||
void Bindings::draw()
|
||||
{
|
||||
if (damage() & FL_DAMAGE_ALL)
|
||||
{
|
||||
cairo_t *cr = Fl::cairo_cc();
|
||||
cairo_save( cr );
|
||||
|
||||
cairo_set_source_rgba( cr, 255 / 255.f, 255 / 255.f , 255 / 255.f , 1 );
|
||||
cairo_set_font_size( cr, 11 );
|
||||
cairo_move_to( cr, x + 7, y+15 );
|
||||
cairo_show_text( cr, "Action:" );
|
||||
|
||||
cairo_move_to( cr, x + 140, y+15 );
|
||||
cairo_show_text( cr, "T:" );
|
||||
cairo_move_to( cr, x + 160, y+15 );
|
||||
cairo_show_text( cr, "S:" );
|
||||
|
||||
|
||||
cairo_move_to( cr, x + 200, y+15 );
|
||||
cairo_show_text( cr, "B1:" );
|
||||
cairo_move_to( cr, x + 230, y+15 );
|
||||
cairo_show_text( cr, "B2:" );
|
||||
|
||||
|
||||
int drawY = y + bindYPx;
|
||||
for(unsigned int i = 0; i < binds.size(); i++) // draw each binding
|
||||
{
|
||||
cairo_rectangle( cr, x+2, drawY, 179, 23 );
|
||||
cairo_set_source_rgba(cr, 0 / 255.f, 0 / 255.f , 0 / 255.f, 0.4);
|
||||
cairo_fill(cr);
|
||||
|
||||
// action
|
||||
cairo_move_to( cr, x + 7, drawY+15 );
|
||||
cairo_set_source_rgba( cr, 255 / 255.f, 255 / 255.f , 255 / 255.f , 1 );
|
||||
cairo_set_font_size( cr, 11 );
|
||||
const char* action = Event::getPrettyName( binds.at(i)->action );
|
||||
if ( action )
|
||||
cairo_show_text( cr, action );
|
||||
|
||||
// track
|
||||
cairo_move_to( cr, x + 140, drawY+15 );
|
||||
{
|
||||
std::stringstream s;
|
||||
s << binds.at(i)->track;
|
||||
cairo_show_text( cr, s.str().c_str() );
|
||||
}
|
||||
// scene
|
||||
cairo_move_to( cr, x + 150, drawY+15 );
|
||||
{
|
||||
std::stringstream s;
|
||||
s << binds.at(i)->scene;
|
||||
cairo_show_text( cr, s.str().c_str() );
|
||||
}
|
||||
|
||||
// status
|
||||
cairo_move_to( cr, x + 165, drawY+15 );
|
||||
{
|
||||
std::stringstream s;
|
||||
s << binds.at(i)->status;
|
||||
cairo_show_text( cr, s.str().c_str() );
|
||||
}
|
||||
// data
|
||||
cairo_move_to( cr, x + 175, drawY+15 );
|
||||
{
|
||||
std::stringstream s;
|
||||
s << binds.at(i)->data;
|
||||
cairo_show_text( cr, s.str().c_str() );
|
||||
}
|
||||
// move to next line
|
||||
drawY += bindYPx;
|
||||
}
|
||||
|
||||
//printf("done drawing\n");
|
||||
|
||||
cairo_restore( cr );
|
||||
}
|
||||
if (damage() & FL_DAMAGE_ALL) {
|
||||
cairo_t *cr = Fl::cairo_cc();
|
||||
cairo_save( cr );
|
||||
|
||||
cairo_set_source_rgba( cr, 255 / 255.f, 255 / 255.f , 255 / 255.f , 1 );
|
||||
cairo_set_font_size( cr, 11 );
|
||||
cairo_move_to( cr, x + 7, y+15 );
|
||||
cairo_show_text( cr, "Action:" );
|
||||
|
||||
cairo_move_to( cr, x + 140, y+15 );
|
||||
cairo_show_text( cr, "T:" );
|
||||
cairo_move_to( cr, x + 160, y+15 );
|
||||
cairo_show_text( cr, "S:" );
|
||||
|
||||
|
||||
cairo_move_to( cr, x + 200, y+15 );
|
||||
cairo_show_text( cr, "B1:" );
|
||||
cairo_move_to( cr, x + 230, y+15 );
|
||||
cairo_show_text( cr, "B2:" );
|
||||
|
||||
|
||||
int drawY = y + bindYPx;
|
||||
for(unsigned int i = 0; i < binds.size(); i++) { // draw each binding
|
||||
cairo_rectangle( cr, x+2, drawY, 179, 23 );
|
||||
cairo_set_source_rgba(cr, 0 / 255.f, 0 / 255.f , 0 / 255.f, 0.4);
|
||||
cairo_fill(cr);
|
||||
|
||||
// action
|
||||
cairo_move_to( cr, x + 7, drawY+15 );
|
||||
cairo_set_source_rgba( cr, 255 / 255.f, 255 / 255.f , 255 / 255.f , 1 );
|
||||
cairo_set_font_size( cr, 11 );
|
||||
const char* action = Event::getPrettyName( binds.at(i)->action );
|
||||
if ( action )
|
||||
cairo_show_text( cr, action );
|
||||
|
||||
// track
|
||||
cairo_move_to( cr, x + 140, drawY+15 );
|
||||
{
|
||||
std::stringstream s;
|
||||
s << binds.at(i)->track;
|
||||
cairo_show_text( cr, s.str().c_str() );
|
||||
}
|
||||
// scene
|
||||
cairo_move_to( cr, x + 150, drawY+15 );
|
||||
{
|
||||
std::stringstream s;
|
||||
s << binds.at(i)->scene;
|
||||
cairo_show_text( cr, s.str().c_str() );
|
||||
}
|
||||
|
||||
// status
|
||||
cairo_move_to( cr, x + 165, drawY+15 );
|
||||
{
|
||||
std::stringstream s;
|
||||
s << binds.at(i)->status;
|
||||
cairo_show_text( cr, s.str().c_str() );
|
||||
}
|
||||
// data
|
||||
cairo_move_to( cr, x + 175, drawY+15 );
|
||||
{
|
||||
std::stringstream s;
|
||||
s << binds.at(i)->data;
|
||||
cairo_show_text( cr, s.str().c_str() );
|
||||
}
|
||||
// move to next line
|
||||
drawY += bindYPx;
|
||||
}
|
||||
|
||||
//printf("done drawing\n");
|
||||
|
||||
cairo_restore( cr );
|
||||
}
|
||||
}
|
||||
|
||||
void Bindings::add( Binding* b )
|
||||
{
|
||||
// FIXME: Refactor to use copy-constructor?
|
||||
Binding* tmp = new Binding();
|
||||
tmp->action = b->action;
|
||||
tmp->status = b->status;
|
||||
tmp->data = b->data;
|
||||
|
||||
tmp->active = b->active;
|
||||
tmp->track = b->track;
|
||||
tmp->scene = b->scene;
|
||||
tmp->send = b->send;
|
||||
|
||||
binds.push_back( tmp );
|
||||
|
||||
/*
|
||||
int height = binds.size() * bindYPx;
|
||||
printf("resize to %i, %i, %i, %i\n", x, y, w, height );
|
||||
resize( x, y, w, height );
|
||||
*/
|
||||
|
||||
redraw();
|
||||
// FIXME: Refactor to use copy-constructor?
|
||||
Binding* tmp = new Binding();
|
||||
tmp->action = b->action;
|
||||
tmp->status = b->status;
|
||||
tmp->data = b->data;
|
||||
|
||||
tmp->active = b->active;
|
||||
tmp->track = b->track;
|
||||
tmp->scene = b->scene;
|
||||
tmp->send = b->send;
|
||||
|
||||
binds.push_back( tmp );
|
||||
|
||||
/*
|
||||
int height = binds.size() * bindYPx;
|
||||
printf("resize to %i, %i, %i, %i\n", x, y, w, height );
|
||||
resize( x, y, w, height );
|
||||
*/
|
||||
|
||||
redraw();
|
||||
}
|
||||
|
||||
void Bindings::resize(int X, int Y, int W, int H)
|
||||
{
|
||||
Fl_Widget::resize(X,Y,W,H);
|
||||
x = X;
|
||||
y = Y;
|
||||
w = W;
|
||||
h = H;
|
||||
redraw();
|
||||
Fl_Widget::resize(X,Y,W,H);
|
||||
x = X;
|
||||
y = Y;
|
||||
w = W;
|
||||
h = H;
|
||||
redraw();
|
||||
}
|
||||
|
||||
} // namespace Avtk
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -31,23 +31,23 @@ namespace Avtk
|
|||
|
||||
class Bindings : public Fl_Button
|
||||
{
|
||||
public:
|
||||
Bindings( int _x, int _y, int _w, int _h, const char *_label = 0 );
|
||||
|
||||
bool mouseOver;
|
||||
bool highlight;
|
||||
int x, y, w, h;
|
||||
const char* label;
|
||||
|
||||
void add( Binding* b );
|
||||
|
||||
void draw();
|
||||
//int handle(int event);
|
||||
void resize(int X, int Y, int W, int H);
|
||||
|
||||
int bindYPx;
|
||||
std::vector<Binding*> binds;
|
||||
|
||||
public:
|
||||
Bindings( int _x, int _y, int _w, int _h, const char *_label = 0 );
|
||||
|
||||
bool mouseOver;
|
||||
bool highlight;
|
||||
int x, y, w, h;
|
||||
const char* label;
|
||||
|
||||
void add( Binding* b );
|
||||
|
||||
void draw();
|
||||
//int handle(int event);
|
||||
void resize(int X, int Y, int W, int H);
|
||||
|
||||
int bindYPx;
|
||||
std::vector<Binding*> binds;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -32,38 +32,36 @@ namespace Avtk
|
|||
|
||||
ClipSelector::ClipSelector( int _x, int _y, int _w, int _h,
|
||||
const char *_label, bool master ) :
|
||||
Fl_Button(_x, _y, _w, _h, _label)
|
||||
Fl_Button(_x, _y, _w, _h, _label)
|
||||
{
|
||||
x = _x;
|
||||
y = _y;
|
||||
w = _w;
|
||||
h = _h;
|
||||
|
||||
special = -1;
|
||||
|
||||
label = _label;
|
||||
_master = master;
|
||||
|
||||
if ( _master )
|
||||
{
|
||||
for(int i = 0; i < 10; i++ )
|
||||
{
|
||||
stringstream s;
|
||||
s << "Scene " << i + 1;
|
||||
clips[i].setName( s.str() );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
highlight = false;
|
||||
mouseOver = false;
|
||||
x = _x;
|
||||
y = _y;
|
||||
w = _w;
|
||||
h = _h;
|
||||
|
||||
special = -1;
|
||||
|
||||
label = _label;
|
||||
_master = master;
|
||||
|
||||
if ( _master ) {
|
||||
for(int i = 0; i < 10; i++ ) {
|
||||
stringstream s;
|
||||
s << "Scene " << i + 1;
|
||||
clips[i].setName( s.str() );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
highlight = false;
|
||||
mouseOver = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ClipSelector::setID( int id )
|
||||
{
|
||||
ID = id;
|
||||
ID = id;
|
||||
}
|
||||
|
||||
|
||||
|
@ -71,366 +69,320 @@ void ClipSelector::setID( int id )
|
|||
void ClipSelector::setState( int clipNum, GridLogic::State s )
|
||||
{
|
||||
#ifdef DEBUG_CLIP
|
||||
//cout << "ClipSelector::setState() t = " << ID << " clipNum = " << clipNum << " state = " << s << endl;
|
||||
//cout << "ClipSelector::setState() t = " << ID << " clipNum = " << clipNum << " state = " << s << endl;
|
||||
#endif
|
||||
clips[clipNum].setState( s );
|
||||
if ( s == GridLogic::STATE_EMPTY )
|
||||
{
|
||||
clips[clipNum].setName("");
|
||||
}
|
||||
|
||||
redraw();
|
||||
clips[clipNum].setState( s );
|
||||
if ( s == GridLogic::STATE_EMPTY ) {
|
||||
clips[clipNum].setName("");
|
||||
}
|
||||
|
||||
redraw();
|
||||
}
|
||||
|
||||
std::string ClipSelector::clipName(int clip)
|
||||
{
|
||||
return clips[clip].getName();
|
||||
return clips[clip].getName();
|
||||
}
|
||||
|
||||
void ClipSelector::clipName(int clip, std::string name)
|
||||
{
|
||||
clips[clip].setName( name );
|
||||
redraw();
|
||||
clips[clip].setName( name );
|
||||
redraw();
|
||||
}
|
||||
|
||||
void ClipSelector::setSpecial(int scene)
|
||||
{
|
||||
if ( special == -1 && scene == -1 )
|
||||
{
|
||||
// no change
|
||||
return;
|
||||
}
|
||||
|
||||
special = scene;
|
||||
redraw();
|
||||
if ( special == -1 && scene == -1 ) {
|
||||
// no change
|
||||
return;
|
||||
}
|
||||
|
||||
special = scene;
|
||||
redraw();
|
||||
}
|
||||
|
||||
void ClipSelector::draw()
|
||||
{
|
||||
if (damage() & FL_DAMAGE_ALL)
|
||||
{
|
||||
if ( value() )
|
||||
{
|
||||
highlight = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
highlight = false;
|
||||
}
|
||||
|
||||
cairo_t *cr = Fl::cairo_cc();
|
||||
|
||||
cairo_save( cr );
|
||||
|
||||
int clipWidth = w - 2;
|
||||
int clipHeight = (h / numClips);
|
||||
|
||||
// text height adjustment based on clip size
|
||||
// small 22, 13
|
||||
// start 29, 17
|
||||
//printf("clipHeight %i\n", clipHeight);
|
||||
int textHeight = 13 + ((clipHeight - 22) * 0.66 );
|
||||
|
||||
|
||||
|
||||
int xOff = x+clipHeight/2;
|
||||
|
||||
int drawY = y + 1;
|
||||
for( int i = 0; i < numClips; i++) // draw each clip
|
||||
{
|
||||
int yOff = drawY+ clipHeight/2 -1;
|
||||
|
||||
cairo_rectangle( cr, x+2, drawY, clipWidth-1, clipHeight - 4 );
|
||||
cairo_set_source_rgba(cr, 66 / 255.f, 66 / 255.f , 66 / 255.f, 0.4);
|
||||
cairo_fill(cr);
|
||||
|
||||
cairo_rectangle( cr, x+2, drawY, clipHeight-4, clipHeight - 4 );
|
||||
|
||||
if ( clips[i].getState() == GridLogic::STATE_RECORDING )
|
||||
{
|
||||
cairo_set_source_rgba(cr, 1.f, 0 / 255.f , 0 / 255.f, 1.f);
|
||||
cairo_fill(cr);
|
||||
//cairo_arc( cr, x+14, drawY+13, 4.3, 0, 6.29 );
|
||||
cairo_arc( cr, xOff, yOff, 4.3, 0, 6.29 );
|
||||
cairo_set_source_rgba(cr, 0, 0, 0, 1.f);
|
||||
cairo_fill(cr);
|
||||
}
|
||||
else if ( clips[i].getState() == GridLogic::STATE_PLAYING )
|
||||
{
|
||||
cairo_set_source_rgba(cr, 0.0, 1.0, 0, 1.f );
|
||||
cairo_fill(cr);
|
||||
cairo_move_to( cr, xOff-4, yOff-5 );
|
||||
cairo_line_to( cr, xOff+5, yOff );
|
||||
cairo_line_to( cr, xOff-4, yOff+5 );
|
||||
cairo_close_path(cr);
|
||||
cairo_set_source_rgba(cr, 0, 0, 0, 1.f);
|
||||
cairo_fill(cr);
|
||||
}
|
||||
else if ( clips[i].getState() == GridLogic::STATE_PLAY_QUEUED )
|
||||
{
|
||||
cairo_set_source_rgba( cr, 0 / 255.f, 153 / 255.f , 255 / 255.f , 1 );
|
||||
cairo_fill(cr);
|
||||
cairo_move_to( cr, xOff-4, yOff-5 );
|
||||
cairo_line_to( cr, xOff+5, yOff );
|
||||
cairo_line_to( cr, xOff-4, yOff +5 );
|
||||
cairo_close_path(cr);
|
||||
cairo_set_source_rgba(cr, 0, 0, 0, 1.f);
|
||||
cairo_fill(cr);
|
||||
}
|
||||
else if ( clips[i].getState() == GridLogic::STATE_STOP_QUEUED )
|
||||
{
|
||||
cairo_set_source_rgba( cr, 0 / 255.f, 153 / 255.f , 255 / 255.f , 1 );
|
||||
cairo_fill(cr);
|
||||
cairo_arc( cr, xOff, yOff, 4.3, 0, 6.29 );
|
||||
cairo_set_source_rgba(cr, 0, 0, 0, 1.f);
|
||||
cairo_set_line_width(cr, 2.2f);
|
||||
cairo_stroke(cr);
|
||||
}
|
||||
else if ( clips[i].getState() == GridLogic::STATE_RECORD_QUEUED )
|
||||
{
|
||||
cairo_set_source_rgba( cr, 0 / 255.f, 153 / 255.f , 255 / 255.f , 1 );
|
||||
cairo_fill(cr);
|
||||
cairo_arc( cr, xOff, yOff, 4.3, 0, 6.29 );
|
||||
cairo_set_source_rgba(cr, 0, 0, 0, 1.f);
|
||||
cairo_fill(cr);
|
||||
}
|
||||
else if ( clips[i].getState() == GridLogic::STATE_STOPPED )
|
||||
{
|
||||
cairo_set_source_rgba(cr, 1.0, 0.6, 0, 1.f);
|
||||
cairo_fill(cr);
|
||||
cairo_arc( cr, xOff, yOff, 4.3, 0, 6.29 );
|
||||
cairo_set_source_rgba(cr, 0, 0, 0, 1.f);
|
||||
cairo_set_line_width(cr, 2.2f);
|
||||
cairo_stroke(cr);
|
||||
}
|
||||
else
|
||||
{
|
||||
cairo_set_source_rgba(cr, 66 / 255.f, 66 / 255.f , 66 / 255.f, 1.f);
|
||||
cairo_fill(cr);
|
||||
}
|
||||
|
||||
cairo_rectangle( cr, x+2, drawY, clipWidth -1, clipHeight - 3 );
|
||||
|
||||
float alpha = 1;
|
||||
cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, alpha);
|
||||
cairo_set_line_width( cr, 1.3);
|
||||
cairo_move_to( cr, x+clipHeight-1, drawY );
|
||||
cairo_line_to( cr, x+clipHeight-1, drawY + clipHeight - 2);
|
||||
cairo_stroke(cr);
|
||||
|
||||
// clip name
|
||||
cairo_move_to( cr, x + clipHeight + 5, drawY + textHeight );
|
||||
cairo_set_source_rgba( cr, 255 / 255.f, 255 / 255.f , 255 / 255.f , 0.9 );
|
||||
cairo_set_font_size( cr, 11 );
|
||||
|
||||
std::string tmp = clips[i].getName().substr(0,8);
|
||||
|
||||
cairo_show_text( cr, tmp.c_str() );
|
||||
|
||||
// special indicator?
|
||||
if ( i == special )
|
||||
{
|
||||
cairo_rectangle( cr, x+2, drawY, clipWidth -1, clipHeight - 3 );
|
||||
cairo_set_source_rgba(cr, 0.0, 153 / 255.f, 1.0, alpha);
|
||||
cairo_stroke( cr );
|
||||
}
|
||||
|
||||
drawY += clipHeight;
|
||||
|
||||
}
|
||||
|
||||
cairo_restore( cr );
|
||||
|
||||
//draw_label();
|
||||
}
|
||||
if (damage() & FL_DAMAGE_ALL) {
|
||||
if ( value() ) {
|
||||
highlight = true;
|
||||
} else {
|
||||
highlight = false;
|
||||
}
|
||||
|
||||
cairo_t *cr = Fl::cairo_cc();
|
||||
|
||||
cairo_save( cr );
|
||||
|
||||
int clipWidth = w - 2;
|
||||
int clipHeight = (h / numClips);
|
||||
|
||||
// text height adjustment based on clip size
|
||||
// small 22, 13
|
||||
// start 29, 17
|
||||
//printf("clipHeight %i\n", clipHeight);
|
||||
int textHeight = 13 + ((clipHeight - 22) * 0.66 );
|
||||
|
||||
|
||||
|
||||
int xOff = x+clipHeight/2;
|
||||
|
||||
int drawY = y + 1;
|
||||
for( int i = 0; i < numClips; i++) { // draw each clip
|
||||
int yOff = drawY+ clipHeight/2 -1;
|
||||
|
||||
cairo_rectangle( cr, x+2, drawY, clipWidth-1, clipHeight - 4 );
|
||||
cairo_set_source_rgba(cr, 66 / 255.f, 66 / 255.f , 66 / 255.f, 0.4);
|
||||
cairo_fill(cr);
|
||||
|
||||
cairo_rectangle( cr, x+2, drawY, clipHeight-4, clipHeight - 4 );
|
||||
|
||||
if ( clips[i].getState() == GridLogic::STATE_RECORDING ) {
|
||||
cairo_set_source_rgba(cr, 1.f, 0 / 255.f , 0 / 255.f, 1.f);
|
||||
cairo_fill(cr);
|
||||
//cairo_arc( cr, x+14, drawY+13, 4.3, 0, 6.29 );
|
||||
cairo_arc( cr, xOff, yOff, 4.3, 0, 6.29 );
|
||||
cairo_set_source_rgba(cr, 0, 0, 0, 1.f);
|
||||
cairo_fill(cr);
|
||||
} else if ( clips[i].getState() == GridLogic::STATE_PLAYING ) {
|
||||
cairo_set_source_rgba(cr, 0.0, 1.0, 0, 1.f );
|
||||
cairo_fill(cr);
|
||||
cairo_move_to( cr, xOff-4, yOff-5 );
|
||||
cairo_line_to( cr, xOff+5, yOff );
|
||||
cairo_line_to( cr, xOff-4, yOff+5 );
|
||||
cairo_close_path(cr);
|
||||
cairo_set_source_rgba(cr, 0, 0, 0, 1.f);
|
||||
cairo_fill(cr);
|
||||
} else if ( clips[i].getState() == GridLogic::STATE_PLAY_QUEUED ) {
|
||||
cairo_set_source_rgba( cr, 0 / 255.f, 153 / 255.f , 255 / 255.f , 1 );
|
||||
cairo_fill(cr);
|
||||
cairo_move_to( cr, xOff-4, yOff-5 );
|
||||
cairo_line_to( cr, xOff+5, yOff );
|
||||
cairo_line_to( cr, xOff-4, yOff +5 );
|
||||
cairo_close_path(cr);
|
||||
cairo_set_source_rgba(cr, 0, 0, 0, 1.f);
|
||||
cairo_fill(cr);
|
||||
} else if ( clips[i].getState() == GridLogic::STATE_STOP_QUEUED ) {
|
||||
cairo_set_source_rgba( cr, 0 / 255.f, 153 / 255.f , 255 / 255.f , 1 );
|
||||
cairo_fill(cr);
|
||||
cairo_arc( cr, xOff, yOff, 4.3, 0, 6.29 );
|
||||
cairo_set_source_rgba(cr, 0, 0, 0, 1.f);
|
||||
cairo_set_line_width(cr, 2.2f);
|
||||
cairo_stroke(cr);
|
||||
} else if ( clips[i].getState() == GridLogic::STATE_RECORD_QUEUED ) {
|
||||
cairo_set_source_rgba( cr, 0 / 255.f, 153 / 255.f , 255 / 255.f , 1 );
|
||||
cairo_fill(cr);
|
||||
cairo_arc( cr, xOff, yOff, 4.3, 0, 6.29 );
|
||||
cairo_set_source_rgba(cr, 0, 0, 0, 1.f);
|
||||
cairo_fill(cr);
|
||||
} else if ( clips[i].getState() == GridLogic::STATE_STOPPED ) {
|
||||
cairo_set_source_rgba(cr, 1.0, 0.6, 0, 1.f);
|
||||
cairo_fill(cr);
|
||||
cairo_arc( cr, xOff, yOff, 4.3, 0, 6.29 );
|
||||
cairo_set_source_rgba(cr, 0, 0, 0, 1.f);
|
||||
cairo_set_line_width(cr, 2.2f);
|
||||
cairo_stroke(cr);
|
||||
} else {
|
||||
cairo_set_source_rgba(cr, 66 / 255.f, 66 / 255.f , 66 / 255.f, 1.f);
|
||||
cairo_fill(cr);
|
||||
}
|
||||
|
||||
cairo_rectangle( cr, x+2, drawY, clipWidth -1, clipHeight - 3 );
|
||||
|
||||
float alpha = 1;
|
||||
cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, alpha);
|
||||
cairo_set_line_width( cr, 1.3);
|
||||
cairo_move_to( cr, x+clipHeight-1, drawY );
|
||||
cairo_line_to( cr, x+clipHeight-1, drawY + clipHeight - 2);
|
||||
cairo_stroke(cr);
|
||||
|
||||
// clip name
|
||||
cairo_move_to( cr, x + clipHeight + 5, drawY + textHeight );
|
||||
cairo_set_source_rgba( cr, 255 / 255.f, 255 / 255.f , 255 / 255.f , 0.9 );
|
||||
cairo_set_font_size( cr, 11 );
|
||||
|
||||
std::string tmp = clips[i].getName().substr(0,8);
|
||||
|
||||
cairo_show_text( cr, tmp.c_str() );
|
||||
|
||||
// special indicator?
|
||||
if ( i == special ) {
|
||||
cairo_rectangle( cr, x+2, drawY, clipWidth -1, clipHeight - 3 );
|
||||
cairo_set_source_rgba(cr, 0.0, 153 / 255.f, 1.0, alpha);
|
||||
cairo_stroke( cr );
|
||||
}
|
||||
|
||||
drawY += clipHeight;
|
||||
|
||||
}
|
||||
|
||||
cairo_restore( cr );
|
||||
|
||||
//draw_label();
|
||||
}
|
||||
}
|
||||
|
||||
void ClipSelector::resize(int X, int Y, int W, int H)
|
||||
{
|
||||
Fl_Widget::resize(X,Y,W,H);
|
||||
x = X;
|
||||
y = Y;
|
||||
w = W;
|
||||
h = H;
|
||||
redraw();
|
||||
Fl_Widget::resize(X,Y,W,H);
|
||||
x = X;
|
||||
y = Y;
|
||||
w = W;
|
||||
h = H;
|
||||
redraw();
|
||||
}
|
||||
|
||||
|
||||
|
||||
int ClipSelector::handle(int event)
|
||||
{
|
||||
switch(event) {
|
||||
case FL_ACTIVATE:
|
||||
{
|
||||
}
|
||||
case FL_DEACTIVATE:
|
||||
{
|
||||
}
|
||||
return 1;
|
||||
case FL_PUSH:
|
||||
highlight = 1;
|
||||
{
|
||||
// calculate the clicked clip number
|
||||
int clipHeight = (h / numClips);
|
||||
int clipNum = ( (Fl::event_y() ) - y ) / clipHeight;
|
||||
if (clipNum >= numClips)
|
||||
clipNum = numClips -1; // fix for clicking the lowest pixel
|
||||
|
||||
// handle right clicks: popup menu
|
||||
if ( Fl::event_state(FL_BUTTON3) )
|
||||
{
|
||||
if ( _master )
|
||||
{
|
||||
// ask new name for clip, then
|
||||
const char* name = fl_input( "Scene name: ", clips[clipNum].getName().c_str() );
|
||||
if ( name )
|
||||
clips[clipNum].setName( name );
|
||||
|
||||
redraw();
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
Fl_Menu_Item rclick_menu[] =
|
||||
{
|
||||
{ "Load" },
|
||||
{ "Save" },
|
||||
{ "Special"},
|
||||
{ "Beats", 0, 0, 0, FL_SUBMENU | FL_MENU_DIVIDER },
|
||||
{"1 "},
|
||||
{"2"},
|
||||
{"4"},
|
||||
{"8"},
|
||||
{"16"},
|
||||
{"32"},
|
||||
{"64"},
|
||||
{0},
|
||||
//{ "Record" },
|
||||
{ "Use as tempo" },
|
||||
{ "Rename", 0, 0, 0, FL_MENU_DIVIDER},
|
||||
{ "Clear" },
|
||||
{ 0 }
|
||||
};
|
||||
Fl_Menu_Item *m = (Fl_Menu_Item*) rclick_menu->popup(Fl::event_x(), Fl::event_y(), 0, 0, 0);
|
||||
if ( !m )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if ( strcmp(m->label(), "Load") == 0 )
|
||||
{
|
||||
gui->selectLoadSample( ID, clipNum );
|
||||
}
|
||||
else if ( strcmp(m->label(), "Save") == 0 )
|
||||
{
|
||||
//gui->saveBufferPath = "/tmp/test.wav";
|
||||
char* tmp = gui->selectSavePath();
|
||||
if(tmp && strlen(tmp)) {
|
||||
if( access( tmp, F_OK ) != -1 ) {
|
||||
int overwrite = fl_choice("Overwrite file?","Cancel","Overwrite",0);
|
||||
if (!overwrite) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
gui->saveBufferPath = tmp;
|
||||
free(tmp);
|
||||
gui->selectSaveSample( ID, clipNum );
|
||||
}
|
||||
}
|
||||
else if ( strcmp(m->label(), "1 ") == 0 ) {
|
||||
EventLooperLoopLength e = EventLooperLoopLength(ID, clipNum ,1);
|
||||
writeToDspRingbuffer( &e );
|
||||
} else if ( strcmp(m->label(), "2") == 0 ) {
|
||||
EventLooperLoopLength e = EventLooperLoopLength(ID, clipNum ,2);
|
||||
writeToDspRingbuffer( &e );
|
||||
} else if ( strcmp(m->label(), "4") == 0 ) {
|
||||
EventLooperLoopLength e = EventLooperLoopLength(ID, clipNum ,4);
|
||||
writeToDspRingbuffer( &e );
|
||||
} else if ( strcmp(m->label(), "8") == 0 ) {
|
||||
EventLooperLoopLength e = EventLooperLoopLength(ID, clipNum ,8);
|
||||
writeToDspRingbuffer( &e );
|
||||
} else if ( strcmp(m->label(), "16") == 0 ) {
|
||||
EventLooperLoopLength e = EventLooperLoopLength(ID, clipNum ,16);
|
||||
writeToDspRingbuffer( &e );
|
||||
} else if ( strcmp(m->label(), "32") == 0 ) {
|
||||
EventLooperLoopLength e = EventLooperLoopLength(ID, clipNum ,32);
|
||||
writeToDspRingbuffer( &e );
|
||||
} else if ( strcmp(m->label(), "64") == 0 ) {
|
||||
EventLooperLoopLength e = EventLooperLoopLength(ID, clipNum ,64);
|
||||
writeToDspRingbuffer( &e );
|
||||
}
|
||||
else if ( strcmp(m->label(), "Use as tempo") == 0 )
|
||||
{
|
||||
EventLooperUseAsTempo e (ID, clipNum);
|
||||
writeToDspRingbuffer( &e );
|
||||
}
|
||||
else if ( strcmp(m->label(), "Special") == 0 )
|
||||
{
|
||||
//printf("special selected %i, %i\n", ID, clipNum );
|
||||
EventGridSelectNewChosen e( ID, clipNum);
|
||||
writeToDspRingbuffer( &e );
|
||||
}
|
||||
else if ( strcmp(m->label(), "Rename") == 0 )
|
||||
{
|
||||
const char* name = fl_input( "Clip name: ", clips[clipNum].getName().c_str() );
|
||||
if ( name )
|
||||
clips[clipNum].setName( name );
|
||||
}
|
||||
else if ( strcmp(m->label(), "Clear") == 0 )
|
||||
{
|
||||
// for a clip to become 0
|
||||
EventGridState e( ID, clipNum, GridLogic::STATE_EMPTY );
|
||||
writeToDspRingbuffer( &e );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( _master )
|
||||
{
|
||||
EventGridLaunchScene e( clipNum );
|
||||
writeToDspRingbuffer( &e );
|
||||
redraw();
|
||||
return 1;
|
||||
}
|
||||
|
||||
// write "pressed" event for this track,scene
|
||||
EventGridEvent e( ID, clipNum, true );
|
||||
writeToDspRingbuffer( &e );
|
||||
}
|
||||
}
|
||||
redraw();
|
||||
do_callback();
|
||||
return 1;
|
||||
case FL_DRAG:
|
||||
{
|
||||
int t = Fl::event_inside(this);
|
||||
if (t != highlight)
|
||||
{
|
||||
highlight = t;
|
||||
redraw();
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
case FL_ENTER:
|
||||
mouseOver = true;
|
||||
|
||||
redraw();
|
||||
return 1;
|
||||
case FL_LEAVE:
|
||||
mouseOver = false;
|
||||
redraw();
|
||||
return 1;
|
||||
case FL_RELEASE:
|
||||
return 1;
|
||||
case FL_SHORTCUT:
|
||||
if ( test_shortcut() )
|
||||
{
|
||||
do_callback();
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
default:
|
||||
return Fl_Widget::handle(event);
|
||||
}
|
||||
switch(event) {
|
||||
case FL_ACTIVATE: {
|
||||
}
|
||||
case FL_DEACTIVATE: {
|
||||
}
|
||||
return 1;
|
||||
case FL_PUSH:
|
||||
highlight = 1;
|
||||
{
|
||||
// calculate the clicked clip number
|
||||
int clipHeight = (h / numClips);
|
||||
int clipNum = ( (Fl::event_y() ) - y ) / clipHeight;
|
||||
if (clipNum >= numClips)
|
||||
clipNum = numClips -1; // fix for clicking the lowest pixel
|
||||
|
||||
// handle right clicks: popup menu
|
||||
if ( Fl::event_state(FL_BUTTON3) ) {
|
||||
if ( _master ) {
|
||||
// ask new name for clip, then
|
||||
const char* name = fl_input( "Scene name: ", clips[clipNum].getName().c_str() );
|
||||
if ( name )
|
||||
clips[clipNum].setName( name );
|
||||
|
||||
redraw();
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
Fl_Menu_Item rclick_menu[] = {
|
||||
{ "Load" },
|
||||
{ "Save" },
|
||||
{ "Special"},
|
||||
{ "Beats", 0, 0, 0, FL_SUBMENU | FL_MENU_DIVIDER },
|
||||
{"1 "},
|
||||
{"2"},
|
||||
{"4"},
|
||||
{"8"},
|
||||
{"16"},
|
||||
{"32"},
|
||||
{"64"},
|
||||
{0},
|
||||
//{ "Record" },
|
||||
{ "Use as tempo" },
|
||||
{ "Rename", 0, 0, 0, FL_MENU_DIVIDER},
|
||||
{ "Clear" },
|
||||
{ 0 }
|
||||
};
|
||||
Fl_Menu_Item *m = (Fl_Menu_Item*) rclick_menu->popup(Fl::event_x(), Fl::event_y(), 0, 0, 0);
|
||||
if ( !m ) {
|
||||
return 0;
|
||||
} else if ( strcmp(m->label(), "Load") == 0 ) {
|
||||
gui->selectLoadSample( ID, clipNum );
|
||||
} else if ( strcmp(m->label(), "Save") == 0 ) {
|
||||
//gui->saveBufferPath = "/tmp/test.wav";
|
||||
char* tmp = gui->selectSavePath();
|
||||
if(tmp && strlen(tmp)) {
|
||||
if( access( tmp, F_OK ) != -1 ) {
|
||||
int overwrite = fl_choice("Overwrite file?","Cancel","Overwrite",0);
|
||||
if (!overwrite) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
gui->saveBufferPath = tmp;
|
||||
free(tmp);
|
||||
gui->selectSaveSample( ID, clipNum );
|
||||
}
|
||||
} else if ( strcmp(m->label(), "1 ") == 0 ) {
|
||||
EventLooperLoopLength e = EventLooperLoopLength(ID, clipNum ,1);
|
||||
writeToDspRingbuffer( &e );
|
||||
} else if ( strcmp(m->label(), "2") == 0 ) {
|
||||
EventLooperLoopLength e = EventLooperLoopLength(ID, clipNum ,2);
|
||||
writeToDspRingbuffer( &e );
|
||||
} else if ( strcmp(m->label(), "4") == 0 ) {
|
||||
EventLooperLoopLength e = EventLooperLoopLength(ID, clipNum ,4);
|
||||
writeToDspRingbuffer( &e );
|
||||
} else if ( strcmp(m->label(), "8") == 0 ) {
|
||||
EventLooperLoopLength e = EventLooperLoopLength(ID, clipNum ,8);
|
||||
writeToDspRingbuffer( &e );
|
||||
} else if ( strcmp(m->label(), "16") == 0 ) {
|
||||
EventLooperLoopLength e = EventLooperLoopLength(ID, clipNum ,16);
|
||||
writeToDspRingbuffer( &e );
|
||||
} else if ( strcmp(m->label(), "32") == 0 ) {
|
||||
EventLooperLoopLength e = EventLooperLoopLength(ID, clipNum ,32);
|
||||
writeToDspRingbuffer( &e );
|
||||
} else if ( strcmp(m->label(), "64") == 0 ) {
|
||||
EventLooperLoopLength e = EventLooperLoopLength(ID, clipNum ,64);
|
||||
writeToDspRingbuffer( &e );
|
||||
} else if ( strcmp(m->label(), "Use as tempo") == 0 ) {
|
||||
EventLooperUseAsTempo e (ID, clipNum);
|
||||
writeToDspRingbuffer( &e );
|
||||
} else if ( strcmp(m->label(), "Special") == 0 ) {
|
||||
//printf("special selected %i, %i\n", ID, clipNum );
|
||||
EventGridSelectNewChosen e( ID, clipNum);
|
||||
writeToDspRingbuffer( &e );
|
||||
} else if ( strcmp(m->label(), "Rename") == 0 ) {
|
||||
const char* name = fl_input( "Clip name: ", clips[clipNum].getName().c_str() );
|
||||
if ( name )
|
||||
clips[clipNum].setName( name );
|
||||
} else if ( strcmp(m->label(), "Clear") == 0 ) {
|
||||
// for a clip to become 0
|
||||
EventGridState e( ID, clipNum, GridLogic::STATE_EMPTY );
|
||||
writeToDspRingbuffer( &e );
|
||||
}
|
||||
} else {
|
||||
if ( _master ) {
|
||||
EventGridLaunchScene e( clipNum );
|
||||
writeToDspRingbuffer( &e );
|
||||
redraw();
|
||||
return 1;
|
||||
}
|
||||
|
||||
// write "pressed" event for this track,scene
|
||||
EventGridEvent e( ID, clipNum, true );
|
||||
writeToDspRingbuffer( &e );
|
||||
}
|
||||
}
|
||||
redraw();
|
||||
do_callback();
|
||||
return 1;
|
||||
case FL_DRAG: {
|
||||
int t = Fl::event_inside(this);
|
||||
if (t != highlight) {
|
||||
highlight = t;
|
||||
redraw();
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
case FL_ENTER:
|
||||
mouseOver = true;
|
||||
|
||||
redraw();
|
||||
return 1;
|
||||
case FL_LEAVE:
|
||||
mouseOver = false;
|
||||
redraw();
|
||||
return 1;
|
||||
case FL_RELEASE:
|
||||
return 1;
|
||||
case FL_SHORTCUT:
|
||||
if ( test_shortcut() ) {
|
||||
do_callback();
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
default:
|
||||
return Fl_Widget::handle(event);
|
||||
}
|
||||
}
|
||||
|
||||
} // Avtk
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -38,73 +38,73 @@ namespace Avtk
|
|||
|
||||
class ClipState
|
||||
{
|
||||
public:
|
||||
ClipState() :
|
||||
state(GridLogic::STATE_EMPTY),
|
||||
name("")
|
||||
{}
|
||||
|
||||
void setName(std::string n)
|
||||
{
|
||||
name = n;
|
||||
}
|
||||
|
||||
void setState(GridLogic::State s)
|
||||
{
|
||||
state = s;
|
||||
}
|
||||
|
||||
std::string getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
GridLogic::State getState()
|
||||
{
|
||||
return state;
|
||||
}
|
||||
|
||||
private:
|
||||
GridLogic::State state;
|
||||
std::string name;
|
||||
public:
|
||||
ClipState() :
|
||||
state(GridLogic::STATE_EMPTY),
|
||||
name("")
|
||||
{}
|
||||
|
||||
void setName(std::string n)
|
||||
{
|
||||
name = n;
|
||||
}
|
||||
|
||||
void setState(GridLogic::State s)
|
||||
{
|
||||
state = s;
|
||||
}
|
||||
|
||||
std::string getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
GridLogic::State getState()
|
||||
{
|
||||
return state;
|
||||
}
|
||||
|
||||
private:
|
||||
GridLogic::State state;
|
||||
std::string name;
|
||||
};
|
||||
|
||||
class ClipSelector : public Fl_Button
|
||||
{
|
||||
public:
|
||||
ClipSelector( int _x, int _y, int _w, int _h,
|
||||
const char *_label, bool master = false);
|
||||
|
||||
int ID;
|
||||
|
||||
// FIXME: NSCENES?
|
||||
static const int numClips = 10;
|
||||
ClipState clips[numClips];
|
||||
|
||||
/// indicates if a clip is the "special" clip
|
||||
void setSpecial(int scene);
|
||||
int special;
|
||||
|
||||
bool _master;
|
||||
bool mouseOver;
|
||||
bool highlight;
|
||||
int x, y, w, h;
|
||||
const char* label;
|
||||
|
||||
void setID( int id );
|
||||
|
||||
/** converts the Looper::State into the UI represnted ClipSelector state.
|
||||
* It puts some of the data into clips[], and stores unique state into the class.
|
||||
**/
|
||||
void setState( int clipNum, GridLogic::State s );
|
||||
|
||||
void clipName(int clip, std::string name);
|
||||
std::string clipName(int clip);
|
||||
|
||||
void draw();
|
||||
int handle(int event);
|
||||
|
||||
void resize(int X, int Y, int W, int H);
|
||||
public:
|
||||
ClipSelector( int _x, int _y, int _w, int _h,
|
||||
const char *_label, bool master = false);
|
||||
|
||||
int ID;
|
||||
|
||||
// FIXME: NSCENES?
|
||||
static const int numClips = 10;
|
||||
ClipState clips[numClips];
|
||||
|
||||
/// indicates if a clip is the "special" clip
|
||||
void setSpecial(int scene);
|
||||
int special;
|
||||
|
||||
bool _master;
|
||||
bool mouseOver;
|
||||
bool highlight;
|
||||
int x, y, w, h;
|
||||
const char* label;
|
||||
|
||||
void setID( int id );
|
||||
|
||||
/** converts the Looper::State into the UI represnted ClipSelector state.
|
||||
* It puts some of the data into clips[], and stores unique state into the class.
|
||||
**/
|
||||
void setState( int clipNum, GridLogic::State s );
|
||||
|
||||
void clipName(int clip, std::string name);
|
||||
std::string clipName(int clip);
|
||||
|
||||
void draw();
|
||||
int handle(int event);
|
||||
|
||||
void resize(int X, int Y, int W, int H);
|
||||
};
|
||||
|
||||
} // Avtk
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -21,218 +21,206 @@
|
|||
using namespace Avtk;
|
||||
|
||||
Volume::Volume(int _x, int _y, int _w, int _h, const char *_label ):
|
||||
Fl_Slider(_x, _y, _w, _h, _label)
|
||||
Fl_Slider(_x, _y, _w, _h, _label)
|
||||
{
|
||||
x = _x;
|
||||
y = _y;
|
||||
w = _w;
|
||||
h = _h;
|
||||
|
||||
label = _label;
|
||||
|
||||
mouseClickedX = 0;
|
||||
mouseClickedY = 0;
|
||||
mouseClicked = false;
|
||||
|
||||
active = true;
|
||||
highlight = false;
|
||||
|
||||
ampL = 0;
|
||||
ampR = 0;
|
||||
compress = 0;
|
||||
value( 0.78f );
|
||||
x = _x;
|
||||
y = _y;
|
||||
w = _w;
|
||||
h = _h;
|
||||
|
||||
orientationHorizontal = false;
|
||||
label = _label;
|
||||
|
||||
mouseClickedX = 0;
|
||||
mouseClickedY = 0;
|
||||
mouseClicked = false;
|
||||
|
||||
active = true;
|
||||
highlight = false;
|
||||
|
||||
ampL = 0;
|
||||
ampR = 0;
|
||||
compress = 0;
|
||||
value( 0.78f );
|
||||
|
||||
orientationHorizontal = false;
|
||||
}
|
||||
|
||||
|
||||
void Volume::fader( float f )
|
||||
{
|
||||
// redraw on larger value change
|
||||
//if ( fabsf( value() - f ) > 0.025 )
|
||||
value( f );
|
||||
// redraw on larger value change
|
||||
//if ( fabsf( value() - f ) > 0.025 )
|
||||
value( f );
|
||||
}
|
||||
|
||||
|
||||
void Volume::amplitude (float aL, float aR)
|
||||
{
|
||||
if ( aL < 0.1 ) aL = 0.f;
|
||||
if ( aR < 0.1 ) aR = 0.f;
|
||||
|
||||
// only redraw if changed more than X amount
|
||||
if ( fabsf(ampL - aL) > 0.025 ||
|
||||
fabsf(ampR - aR) > 0.025 )
|
||||
{
|
||||
ampL = aL;
|
||||
ampR = aR;
|
||||
redraw();
|
||||
}
|
||||
if ( aL < 0.1 ) aL = 0.f;
|
||||
if ( aR < 0.1 ) aR = 0.f;
|
||||
|
||||
// only redraw if changed more than X amount
|
||||
if ( fabsf(ampL - aL) > 0.025 ||
|
||||
fabsf(ampR - aR) > 0.025 ) {
|
||||
ampL = aL;
|
||||
ampR = aR;
|
||||
redraw();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Volume::compression(float c)
|
||||
{
|
||||
compress = c;
|
||||
redraw();
|
||||
compress = c;
|
||||
redraw();
|
||||
}
|
||||
|
||||
|
||||
void Volume::setOrientationHorizontal()
|
||||
{
|
||||
orientationHorizontal = true;
|
||||
redraw();
|
||||
orientationHorizontal = true;
|
||||
redraw();
|
||||
}
|
||||
|
||||
void Volume::set_active(bool a)
|
||||
{
|
||||
active = a;
|
||||
redraw();
|
||||
active = a;
|
||||
redraw();
|
||||
}
|
||||
|
||||
void Volume::draw()
|
||||
{
|
||||
if (damage() & FL_DAMAGE_ALL)
|
||||
{
|
||||
cairo_t *cr = Fl::cairo_cc();
|
||||
|
||||
cairo_save( cr );
|
||||
|
||||
cairo_set_line_width(cr, 1.5);
|
||||
|
||||
// fill background
|
||||
cairo_rectangle( cr, x, y, w, h);
|
||||
cairo_set_source_rgba(cr, 66 / 255.f, 66 / 255.f , 66 / 255.f, 0.4);
|
||||
//cairo_set_source_rgb( cr, 28 / 255.f, 28 / 255.f , 28 / 255.f );
|
||||
cairo_fill( cr );
|
||||
|
||||
//cairo_set_dash ( cr, dashes, 1, 0.0);
|
||||
cairo_set_line_width( cr, 1.0);
|
||||
|
||||
// loop over each 2nd line, drawing dots
|
||||
cairo_set_line_width(cr, 1.0);
|
||||
cairo_set_source_rgb(cr, 0.4,0.4,0.4);
|
||||
for ( int i = 0; i < 2; i++ )
|
||||
{
|
||||
cairo_move_to( cr, x + ((w / 2.f)*i), y );
|
||||
cairo_line_to( cr, x + ((w / 2.f)*i), y + h );
|
||||
}
|
||||
for ( int i = 0; i < 4; i++ )
|
||||
{
|
||||
cairo_move_to( cr, x , y + ((h / 4.f)*i) );
|
||||
cairo_line_to( cr, x + w, y + ((h / 4.f)*i) );
|
||||
}
|
||||
|
||||
cairo_set_source_rgba( cr, 66 / 255.f, 66 / 255.f , 66 / 255.f , 0.5 );
|
||||
cairo_stroke(cr);
|
||||
//cairo_set_dash ( cr, dashes, 0, 0.0);
|
||||
|
||||
|
||||
// audio level
|
||||
if ( orientationHorizontal )
|
||||
{
|
||||
cairo_rectangle(cr, x, y+h*0.15, w * ampL, 9.9 );
|
||||
cairo_rectangle(cr, x, y+h*0.56, w * ampR, 9.9 );
|
||||
}
|
||||
else
|
||||
{
|
||||
cairo_rectangle(cr, x+w*0.15, y+h*(1-ampL), 9.9, h - h*(1-ampL) );
|
||||
cairo_rectangle(cr, x+w*0.56, y+h*(1-ampR), 9.9, h - h*(1-ampR) );
|
||||
}
|
||||
cairo_set_source_rgba( cr, 0 / 255.f, 153 / 255.f , 255 / 255.f , 0.21 );
|
||||
cairo_fill_preserve( cr );
|
||||
cairo_set_source_rgba( cr, 0 / 255.f, 153 / 255.f , 255 / 255.f , 1 );
|
||||
cairo_stroke(cr);
|
||||
|
||||
// fader
|
||||
if ( orientationHorizontal )
|
||||
cairo_rectangle(cr, x+2+(w-24)*(value()), y+5, 20, h-10);
|
||||
else
|
||||
cairo_rectangle(cr, x+5, y+2+(h-24)*(1-value()), w-10, 20);
|
||||
|
||||
cairo_set_source_rgba( cr, 1.0f, 0.48, 0.f, 1);
|
||||
cairo_set_line_width(cr, 1.9);
|
||||
cairo_stroke( cr );
|
||||
|
||||
// stroke outline
|
||||
cairo_rectangle(cr, x, y, w, h);
|
||||
cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
|
||||
cairo_set_line_width(cr, 1.9);
|
||||
cairo_stroke( cr );
|
||||
|
||||
cairo_restore( cr );
|
||||
}
|
||||
if (damage() & FL_DAMAGE_ALL) {
|
||||
cairo_t *cr = Fl::cairo_cc();
|
||||
|
||||
cairo_save( cr );
|
||||
|
||||
cairo_set_line_width(cr, 1.5);
|
||||
|
||||
// fill background
|
||||
cairo_rectangle( cr, x, y, w, h);
|
||||
cairo_set_source_rgba(cr, 66 / 255.f, 66 / 255.f , 66 / 255.f, 0.4);
|
||||
//cairo_set_source_rgb( cr, 28 / 255.f, 28 / 255.f , 28 / 255.f );
|
||||
cairo_fill( cr );
|
||||
|
||||
//cairo_set_dash ( cr, dashes, 1, 0.0);
|
||||
cairo_set_line_width( cr, 1.0);
|
||||
|
||||
// loop over each 2nd line, drawing dots
|
||||
cairo_set_line_width(cr, 1.0);
|
||||
cairo_set_source_rgb(cr, 0.4,0.4,0.4);
|
||||
for ( int i = 0; i < 2; i++ ) {
|
||||
cairo_move_to( cr, x + ((w / 2.f)*i), y );
|
||||
cairo_line_to( cr, x + ((w / 2.f)*i), y + h );
|
||||
}
|
||||
for ( int i = 0; i < 4; i++ ) {
|
||||
cairo_move_to( cr, x , y + ((h / 4.f)*i) );
|
||||
cairo_line_to( cr, x + w, y + ((h / 4.f)*i) );
|
||||
}
|
||||
|
||||
cairo_set_source_rgba( cr, 66 / 255.f, 66 / 255.f , 66 / 255.f , 0.5 );
|
||||
cairo_stroke(cr);
|
||||
//cairo_set_dash ( cr, dashes, 0, 0.0);
|
||||
|
||||
|
||||
// audio level
|
||||
if ( orientationHorizontal ) {
|
||||
cairo_rectangle(cr, x, y+h*0.15, w * ampL, 9.9 );
|
||||
cairo_rectangle(cr, x, y+h*0.56, w * ampR, 9.9 );
|
||||
} else {
|
||||
cairo_rectangle(cr, x+w*0.15, y+h*(1-ampL), 9.9, h - h*(1-ampL) );
|
||||
cairo_rectangle(cr, x+w*0.56, y+h*(1-ampR), 9.9, h - h*(1-ampR) );
|
||||
}
|
||||
cairo_set_source_rgba( cr, 0 / 255.f, 153 / 255.f , 255 / 255.f , 0.21 );
|
||||
cairo_fill_preserve( cr );
|
||||
cairo_set_source_rgba( cr, 0 / 255.f, 153 / 255.f , 255 / 255.f , 1 );
|
||||
cairo_stroke(cr);
|
||||
|
||||
// fader
|
||||
if ( orientationHorizontal )
|
||||
cairo_rectangle(cr, x+2+(w-24)*(value()), y+5, 20, h-10);
|
||||
else
|
||||
cairo_rectangle(cr, x+5, y+2+(h-24)*(1-value()), w-10, 20);
|
||||
|
||||
cairo_set_source_rgba( cr, 1.0f, 0.48, 0.f, 1);
|
||||
cairo_set_line_width(cr, 1.9);
|
||||
cairo_stroke( cr );
|
||||
|
||||
// stroke outline
|
||||
cairo_rectangle(cr, x, y, w, h);
|
||||
cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
|
||||
cairo_set_line_width(cr, 1.9);
|
||||
cairo_stroke( cr );
|
||||
|
||||
cairo_restore( cr );
|
||||
}
|
||||
}
|
||||
|
||||
void Volume::resize(int X, int Y, int W, int H)
|
||||
{
|
||||
Fl_Widget::resize(X,Y,W,H);
|
||||
x = X;
|
||||
y = Y;
|
||||
w = W;
|
||||
h = H;
|
||||
redraw();
|
||||
Fl_Widget::resize(X,Y,W,H);
|
||||
x = X;
|
||||
y = Y;
|
||||
w = W;
|
||||
h = H;
|
||||
redraw();
|
||||
}
|
||||
|
||||
int Volume::handle(int event)
|
||||
{
|
||||
switch(event)
|
||||
{
|
||||
case FL_PUSH:
|
||||
highlight = 0;
|
||||
redraw();
|
||||
return 1;
|
||||
case FL_DRAG:
|
||||
{
|
||||
if ( Fl::event_state(FL_BUTTON1) )
|
||||
{
|
||||
if ( mouseClicked == false ) // catch the "click" event
|
||||
{
|
||||
mouseClickedX = Fl::event_x();
|
||||
mouseClickedY = Fl::event_y();
|
||||
mouseClicked = true;
|
||||
}
|
||||
|
||||
float delta = (mouseClickedY - Fl::event_y() ) / float(h);
|
||||
// handle the x / y swap, and the inverting of direction (mouseX / Y relative)
|
||||
if ( orientationHorizontal )
|
||||
delta = ( Fl::event_x() - mouseClickedX ) / float(w);
|
||||
|
||||
float valY = value();
|
||||
valY += delta;
|
||||
|
||||
if ( valY > 1.0 ) valY = 1.0;
|
||||
if ( valY < 0.0 ) valY = 0.0;
|
||||
|
||||
set_value( valY );
|
||||
|
||||
mouseClickedX = Fl::event_x();
|
||||
mouseClickedY = Fl::event_y();
|
||||
redraw();
|
||||
do_callback();
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
case FL_ENTER:
|
||||
return 1;
|
||||
case FL_MOUSEWHEEL:
|
||||
//printf("no scroll on faders\n");
|
||||
return 1;
|
||||
case FL_RELEASE:
|
||||
if (highlight) {
|
||||
highlight = 0;
|
||||
redraw();
|
||||
do_callback();
|
||||
}
|
||||
mouseClicked = false;
|
||||
return 1;
|
||||
case FL_SHORTCUT:
|
||||
if ( test_shortcut() )
|
||||
{
|
||||
do_callback();
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
default:
|
||||
return Fl_Widget::handle(event);
|
||||
}
|
||||
switch(event) {
|
||||
case FL_PUSH:
|
||||
highlight = 0;
|
||||
redraw();
|
||||
return 1;
|
||||
case FL_DRAG: {
|
||||
if ( Fl::event_state(FL_BUTTON1) ) {
|
||||
if ( mouseClicked == false ) { // catch the "click" event
|
||||
mouseClickedX = Fl::event_x();
|
||||
mouseClickedY = Fl::event_y();
|
||||
mouseClicked = true;
|
||||
}
|
||||
|
||||
float delta = (mouseClickedY - Fl::event_y() ) / float(h);
|
||||
// handle the x / y swap, and the inverting of direction (mouseX / Y relative)
|
||||
if ( orientationHorizontal )
|
||||
delta = ( Fl::event_x() - mouseClickedX ) / float(w);
|
||||
|
||||
float valY = value();
|
||||
valY += delta;
|
||||
|
||||
if ( valY > 1.0 ) valY = 1.0;
|
||||
if ( valY < 0.0 ) valY = 0.0;
|
||||
|
||||
set_value( valY );
|
||||
|
||||
mouseClickedX = Fl::event_x();
|
||||
mouseClickedY = Fl::event_y();
|
||||
redraw();
|
||||
do_callback();
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
case FL_ENTER:
|
||||
return 1;
|
||||
case FL_MOUSEWHEEL:
|
||||
//printf("no scroll on faders\n");
|
||||
return 1;
|
||||
case FL_RELEASE:
|
||||
if (highlight) {
|
||||
highlight = 0;
|
||||
redraw();
|
||||
do_callback();
|
||||
}
|
||||
mouseClicked = false;
|
||||
return 1;
|
||||
case FL_SHORTCUT:
|
||||
if ( test_shortcut() ) {
|
||||
do_callback();
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
default:
|
||||
return Fl_Widget::handle(event);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -28,39 +28,39 @@
|
|||
|
||||
namespace Avtk
|
||||
{
|
||||
class Volume : public Fl_Slider
|
||||
{
|
||||
public:
|
||||
Volume(int _x, int _y, int _w, int _h, const char *_label = 0);
|
||||
|
||||
void set_active(bool a);
|
||||
void setOrientationHorizontal();
|
||||
|
||||
void fader( float f );
|
||||
void compression(float c);
|
||||
void amplitude (float aL, float aR);
|
||||
|
||||
void draw();
|
||||
int handle(int event);
|
||||
|
||||
void resize(int X, int Y, int W, int H);
|
||||
|
||||
|
||||
private:
|
||||
bool active;
|
||||
bool highlight;
|
||||
bool orientationHorizontal;
|
||||
|
||||
int x, y, w, h;
|
||||
const char* label;
|
||||
|
||||
int mouseClickedX;
|
||||
int mouseClickedY;
|
||||
bool mouseClicked;
|
||||
|
||||
float ampL, ampR;
|
||||
float compress;
|
||||
};
|
||||
class Volume : public Fl_Slider
|
||||
{
|
||||
public:
|
||||
Volume(int _x, int _y, int _w, int _h, const char *_label = 0);
|
||||
|
||||
void set_active(bool a);
|
||||
void setOrientationHorizontal();
|
||||
|
||||
void fader( float f );
|
||||
void compression(float c);
|
||||
void amplitude (float aL, float aR);
|
||||
|
||||
void draw();
|
||||
int handle(int event);
|
||||
|
||||
void resize(int X, int Y, int W, int H);
|
||||
|
||||
|
||||
private:
|
||||
bool active;
|
||||
bool highlight;
|
||||
bool orientationHorizontal;
|
||||
|
||||
int x, y, w, h;
|
||||
const char* label;
|
||||
|
||||
int mouseClickedX;
|
||||
int mouseClickedY;
|
||||
bool mouseClicked;
|
||||
|
||||
float ampL, ampR;
|
||||
float compress;
|
||||
};
|
||||
} // Avtk
|
||||
|
||||
#endif // AVTK_VOLUME_H
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -33,276 +33,259 @@ namespace Avtk
|
|||
|
||||
class Waveform : public Fl_Widget
|
||||
{
|
||||
public:
|
||||
Waveform(int _x, int _y, int _w, int _h, const char *_label=0 ):
|
||||
Fl_Widget(_x, _y, _w, _h, _label)
|
||||
{
|
||||
x = _x;
|
||||
y = _y;
|
||||
w = _w;
|
||||
h = _h;
|
||||
|
||||
label = _label;
|
||||
|
||||
highlight = false;
|
||||
newWaveform = false;
|
||||
|
||||
waveformCr = 0;
|
||||
waveformSurf = 0;
|
||||
|
||||
|
||||
data = (float*)malloc( sizeof(float) * w );
|
||||
|
||||
srand (time(NULL));
|
||||
|
||||
for (int i = 0; i < _w; i++)
|
||||
{
|
||||
data[i] = rand() / RAND_MAX / 0.75;
|
||||
}
|
||||
|
||||
newWaveform = true;
|
||||
|
||||
strokeRim = true;
|
||||
}
|
||||
|
||||
bool strokeRim;
|
||||
bool highlight;
|
||||
int x, y, w, h;
|
||||
const char* label;
|
||||
|
||||
cairo_t* waveformCr;
|
||||
cairo_surface_t* waveformSurf;
|
||||
|
||||
bool newWaveform;
|
||||
|
||||
long dataSize;
|
||||
float* data;
|
||||
|
||||
void setData( float* d, long size )
|
||||
{
|
||||
//cout << "AvtkWaveform: setDataPtr = " << data << endl;
|
||||
dataSize = size;
|
||||
data = d;
|
||||
newWaveform = true;
|
||||
|
||||
|
||||
damage(FL_DAMAGE_ALL);
|
||||
}
|
||||
|
||||
void draw()
|
||||
{
|
||||
if (damage() & FL_DAMAGE_ALL)
|
||||
{
|
||||
cairo_t *cr = Fl::cairo_cc();
|
||||
cairo_save(cr);
|
||||
|
||||
// clear the surface
|
||||
cairo_rectangle(cr, x, y, w, h);
|
||||
cairo_set_source_rgb (cr, 0.1,0.1,0.1);
|
||||
cairo_fill( cr );
|
||||
|
||||
if ( newWaveform )
|
||||
{
|
||||
if ( !waveformCr )
|
||||
{
|
||||
// create the waveform surface and context
|
||||
//cout << "waveform draw() creating new objects" << endl;
|
||||
waveformSurf= cairo_image_surface_create ( CAIRO_FORMAT_ARGB32, w, h);
|
||||
waveformCr = cairo_create ( waveformSurf );
|
||||
//cout << "waveform draw() creating objects done" << endl;
|
||||
}
|
||||
|
||||
// clear the surface
|
||||
cairo_rectangle(waveformCr, 0, 0, w, h);
|
||||
cairo_set_source_rgb (waveformCr, 0.1,0.1,0.1);
|
||||
cairo_fill( waveformCr );
|
||||
|
||||
// set up dashed lines, 1 px off, 1 px on
|
||||
double dashes[1];
|
||||
dashes[0] = 2.0;
|
||||
|
||||
cairo_set_dash ( waveformCr, dashes, 1, 0.0);
|
||||
cairo_set_line_width( waveformCr, 1.0);
|
||||
|
||||
// loop over each 2nd line, drawing dots
|
||||
cairo_set_line_width(waveformCr, 1.0);
|
||||
cairo_set_source_rgb(waveformCr, 0.4,0.4,0.4);
|
||||
for ( int i = 1; i < 4; i++ )
|
||||
{
|
||||
cairo_move_to( waveformCr, ((w / 4.f)*i), 0);
|
||||
cairo_line_to( waveformCr, ((w / 4.f)*i), h );
|
||||
}
|
||||
for ( int i = 1; i < 4; i++ )
|
||||
{
|
||||
cairo_move_to( waveformCr, 0, ((h / 4.f)*i) );
|
||||
cairo_line_to( waveformCr, w, ((h / 4.f)*i) );
|
||||
}
|
||||
|
||||
cairo_set_source_rgba( waveformCr, 66 / 255.f, 66 / 255.f , 66 / 255.f , 0.5 );
|
||||
cairo_stroke(waveformCr);
|
||||
cairo_set_dash ( waveformCr, dashes, 0, 0.0);
|
||||
|
||||
|
||||
if ( !data )
|
||||
{
|
||||
// draw X
|
||||
cairo_move_to( cr, 0 , 0 );
|
||||
cairo_line_to( cr, 0 + w, 0 + h );
|
||||
cairo_move_to( cr, 0 , 0 + h );
|
||||
cairo_line_to( cr, 0 + w, 0 );
|
||||
cairo_set_source_rgb ( cr, 0.2,0.2,0.2);
|
||||
cairo_stroke(cr);
|
||||
|
||||
// draw text
|
||||
cairo_move_to( cr, 0 + (w/2.f) - 65, 0 + (h/2.f) + 10 );
|
||||
cairo_set_source_rgb ( cr, 0.6,0.6,0.6);
|
||||
cairo_set_font_size( cr, 20 );
|
||||
cairo_show_text( cr, "No data loaded" );
|
||||
}
|
||||
else
|
||||
{
|
||||
// don't draw every sample
|
||||
int sampleCountForDrawing = -1;
|
||||
|
||||
float currentTop = 0.f;
|
||||
float previousTop = 0.f;
|
||||
float currentSample = 0.f;
|
||||
|
||||
// find how many samples per pixel
|
||||
int samplesPerPix = int(dataSize / float(w));
|
||||
//cout << "width = " << w << " sampsPerPx " << samplesPerPix << endl;
|
||||
|
||||
// loop over each pixel value we need
|
||||
for( int p = 0; p < w; p++ )
|
||||
{
|
||||
float averageMax = 0.f;
|
||||
float averageMin = 0.f;
|
||||
|
||||
// calc value for this pixel
|
||||
for( int i = 0; i < samplesPerPix; i++ )
|
||||
{
|
||||
float tmp = data[i + (p * samplesPerPix)];
|
||||
if ( tmp < 0 )
|
||||
{
|
||||
averageMin -= tmp;
|
||||
}
|
||||
else
|
||||
{
|
||||
averageMax += tmp;
|
||||
}
|
||||
}
|
||||
|
||||
// - 0.1 to keep in bounds of square
|
||||
averageMin = (averageMin / samplesPerPix);
|
||||
averageMax = (averageMax / samplesPerPix);
|
||||
|
||||
// don't use to the *very* top of the widget, only 0.8 (top & bottom)
|
||||
float dH = h * 0.4;
|
||||
|
||||
// emulate log shape
|
||||
float tmpMin = log( 0.1 + (averageMin*4.9) );
|
||||
float tmpMax = log( 0.1 + (averageMax*4.9) );
|
||||
|
||||
// logMin range == -2.3 -> 1.6: add 2.3, then / 3.9
|
||||
float logMin = -((tmpMin + 2.3) / 3.9);
|
||||
float logMax = ((tmpMax + 2.3) / 3.9);
|
||||
|
||||
//printf("input %f, output %f\n", averageMin, logMin );
|
||||
|
||||
// draw lines
|
||||
cairo_move_to( waveformCr, p, h * 0.5 + (logMin * dH ) );
|
||||
cairo_line_to( waveformCr, p, h * 0.5 + (logMax * dH ) );
|
||||
}
|
||||
|
||||
// stroke the waveform
|
||||
cairo_set_source_rgb( waveformCr, 1.0,1.0,1.0);
|
||||
cairo_stroke( waveformCr );
|
||||
|
||||
newWaveform = false;
|
||||
}
|
||||
}
|
||||
|
||||
cairo_set_source_surface(cr, waveformSurf, x, y);
|
||||
cairo_rectangle( cr, x, y, w, h);
|
||||
cairo_paint(cr);
|
||||
|
||||
if ( strokeRim )
|
||||
{
|
||||
// stroke rim
|
||||
cairo_set_line_width(cr, 1);
|
||||
cairo_rectangle(cr, x, y, w, h);
|
||||
cairo_set_source_rgba( cr, 100 / 255.f, 100 / 255.f , 100 / 255.f , 1 );
|
||||
cairo_stroke( cr );
|
||||
}
|
||||
|
||||
//cout << "waveform draw() done" << endl;
|
||||
|
||||
cairo_restore(cr);
|
||||
}
|
||||
}
|
||||
|
||||
void resize(int X, int Y, int W, int H)
|
||||
{
|
||||
Fl_Widget::resize(X,Y,W,H);
|
||||
|
||||
// take the smaller value
|
||||
long newSize = W > w ? W : w;
|
||||
printf("Waveform new size %li, from %i\n", newSize, w );
|
||||
|
||||
x = X;
|
||||
y = Y;
|
||||
w = W;
|
||||
h = H;
|
||||
|
||||
// FIXME: needs to be resampled, not clipped at end
|
||||
// delete old data, and resize it
|
||||
float* newData = (float*)malloc( sizeof(float) * w );
|
||||
|
||||
memcpy( newData, data, newSize );
|
||||
free ( data );
|
||||
data = newData;
|
||||
|
||||
newWaveform = true;
|
||||
|
||||
|
||||
redraw();
|
||||
}
|
||||
|
||||
int handle(int event)
|
||||
{
|
||||
return 0;
|
||||
|
||||
switch(event)
|
||||
{
|
||||
case FL_PUSH:
|
||||
highlight = 0;
|
||||
redraw();
|
||||
return 1;
|
||||
case FL_DRAG: {
|
||||
int t = Fl::event_inside(this);
|
||||
if (t != highlight) {
|
||||
redraw();
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
case FL_RELEASE:
|
||||
if (highlight) {
|
||||
highlight = 0;
|
||||
redraw();
|
||||
do_callback();
|
||||
}
|
||||
return 1;
|
||||
case FL_SHORTCUT:
|
||||
if ( test_shortcut() )
|
||||
{
|
||||
do_callback();
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
default:
|
||||
return Fl_Widget::handle(event);
|
||||
}
|
||||
}
|
||||
public:
|
||||
Waveform(int _x, int _y, int _w, int _h, const char *_label=0 ):
|
||||
Fl_Widget(_x, _y, _w, _h, _label)
|
||||
{
|
||||
x = _x;
|
||||
y = _y;
|
||||
w = _w;
|
||||
h = _h;
|
||||
|
||||
label = _label;
|
||||
|
||||
highlight = false;
|
||||
newWaveform = false;
|
||||
|
||||
waveformCr = 0;
|
||||
waveformSurf = 0;
|
||||
|
||||
|
||||
data = (float*)malloc( sizeof(float) * w );
|
||||
|
||||
srand (time(NULL));
|
||||
|
||||
for (int i = 0; i < _w; i++) {
|
||||
data[i] = rand() / RAND_MAX / 0.75;
|
||||
}
|
||||
|
||||
newWaveform = true;
|
||||
|
||||
strokeRim = true;
|
||||
}
|
||||
|
||||
bool strokeRim;
|
||||
bool highlight;
|
||||
int x, y, w, h;
|
||||
const char* label;
|
||||
|
||||
cairo_t* waveformCr;
|
||||
cairo_surface_t* waveformSurf;
|
||||
|
||||
bool newWaveform;
|
||||
|
||||
long dataSize;
|
||||
float* data;
|
||||
|
||||
void setData( float* d, long size )
|
||||
{
|
||||
//cout << "AvtkWaveform: setDataPtr = " << data << endl;
|
||||
dataSize = size;
|
||||
data = d;
|
||||
newWaveform = true;
|
||||
|
||||
|
||||
damage(FL_DAMAGE_ALL);
|
||||
}
|
||||
|
||||
void draw()
|
||||
{
|
||||
if (damage() & FL_DAMAGE_ALL) {
|
||||
cairo_t *cr = Fl::cairo_cc();
|
||||
cairo_save(cr);
|
||||
|
||||
// clear the surface
|
||||
cairo_rectangle(cr, x, y, w, h);
|
||||
cairo_set_source_rgb (cr, 0.1,0.1,0.1);
|
||||
cairo_fill( cr );
|
||||
|
||||
if ( newWaveform ) {
|
||||
if ( !waveformCr ) {
|
||||
// create the waveform surface and context
|
||||
//cout << "waveform draw() creating new objects" << endl;
|
||||
waveformSurf= cairo_image_surface_create ( CAIRO_FORMAT_ARGB32, w, h);
|
||||
waveformCr = cairo_create ( waveformSurf );
|
||||
//cout << "waveform draw() creating objects done" << endl;
|
||||
}
|
||||
|
||||
// clear the surface
|
||||
cairo_rectangle(waveformCr, 0, 0, w, h);
|
||||
cairo_set_source_rgb (waveformCr, 0.1,0.1,0.1);
|
||||
cairo_fill( waveformCr );
|
||||
|
||||
// set up dashed lines, 1 px off, 1 px on
|
||||
double dashes[1];
|
||||
dashes[0] = 2.0;
|
||||
|
||||
cairo_set_dash ( waveformCr, dashes, 1, 0.0);
|
||||
cairo_set_line_width( waveformCr, 1.0);
|
||||
|
||||
// loop over each 2nd line, drawing dots
|
||||
cairo_set_line_width(waveformCr, 1.0);
|
||||
cairo_set_source_rgb(waveformCr, 0.4,0.4,0.4);
|
||||
for ( int i = 1; i < 4; i++ ) {
|
||||
cairo_move_to( waveformCr, ((w / 4.f)*i), 0);
|
||||
cairo_line_to( waveformCr, ((w / 4.f)*i), h );
|
||||
}
|
||||
for ( int i = 1; i < 4; i++ ) {
|
||||
cairo_move_to( waveformCr, 0, ((h / 4.f)*i) );
|
||||
cairo_line_to( waveformCr, w, ((h / 4.f)*i) );
|
||||
}
|
||||
|
||||
cairo_set_source_rgba( waveformCr, 66 / 255.f, 66 / 255.f , 66 / 255.f , 0.5 );
|
||||
cairo_stroke(waveformCr);
|
||||
cairo_set_dash ( waveformCr, dashes, 0, 0.0);
|
||||
|
||||
|
||||
if ( !data ) {
|
||||
// draw X
|
||||
cairo_move_to( cr, 0 , 0 );
|
||||
cairo_line_to( cr, 0 + w, 0 + h );
|
||||
cairo_move_to( cr, 0 , 0 + h );
|
||||
cairo_line_to( cr, 0 + w, 0 );
|
||||
cairo_set_source_rgb ( cr, 0.2,0.2,0.2);
|
||||
cairo_stroke(cr);
|
||||
|
||||
// draw text
|
||||
cairo_move_to( cr, 0 + (w/2.f) - 65, 0 + (h/2.f) + 10 );
|
||||
cairo_set_source_rgb ( cr, 0.6,0.6,0.6);
|
||||
cairo_set_font_size( cr, 20 );
|
||||
cairo_show_text( cr, "No data loaded" );
|
||||
} else {
|
||||
// don't draw every sample
|
||||
int sampleCountForDrawing = -1;
|
||||
|
||||
float currentTop = 0.f;
|
||||
float previousTop = 0.f;
|
||||
float currentSample = 0.f;
|
||||
|
||||
// find how many samples per pixel
|
||||
int samplesPerPix = int(dataSize / float(w));
|
||||
//cout << "width = " << w << " sampsPerPx " << samplesPerPix << endl;
|
||||
|
||||
// loop over each pixel value we need
|
||||
for( int p = 0; p < w; p++ ) {
|
||||
float averageMax = 0.f;
|
||||
float averageMin = 0.f;
|
||||
|
||||
// calc value for this pixel
|
||||
for( int i = 0; i < samplesPerPix; i++ ) {
|
||||
float tmp = data[i + (p * samplesPerPix)];
|
||||
if ( tmp < 0 ) {
|
||||
averageMin -= tmp;
|
||||
} else {
|
||||
averageMax += tmp;
|
||||
}
|
||||
}
|
||||
|
||||
// - 0.1 to keep in bounds of square
|
||||
averageMin = (averageMin / samplesPerPix);
|
||||
averageMax = (averageMax / samplesPerPix);
|
||||
|
||||
// don't use to the *very* top of the widget, only 0.8 (top & bottom)
|
||||
float dH = h * 0.4;
|
||||
|
||||
// emulate log shape
|
||||
float tmpMin = log( 0.1 + (averageMin*4.9) );
|
||||
float tmpMax = log( 0.1 + (averageMax*4.9) );
|
||||
|
||||
// logMin range == -2.3 -> 1.6: add 2.3, then / 3.9
|
||||
float logMin = -((tmpMin + 2.3) / 3.9);
|
||||
float logMax = ((tmpMax + 2.3) / 3.9);
|
||||
|
||||
//printf("input %f, output %f\n", averageMin, logMin );
|
||||
|
||||
// draw lines
|
||||
cairo_move_to( waveformCr, p, h * 0.5 + (logMin * dH ) );
|
||||
cairo_line_to( waveformCr, p, h * 0.5 + (logMax * dH ) );
|
||||
}
|
||||
|
||||
// stroke the waveform
|
||||
cairo_set_source_rgb( waveformCr, 1.0,1.0,1.0);
|
||||
cairo_stroke( waveformCr );
|
||||
|
||||
newWaveform = false;
|
||||
}
|
||||
}
|
||||
|
||||
cairo_set_source_surface(cr, waveformSurf, x, y);
|
||||
cairo_rectangle( cr, x, y, w, h);
|
||||
cairo_paint(cr);
|
||||
|
||||
if ( strokeRim ) {
|
||||
// stroke rim
|
||||
cairo_set_line_width(cr, 1);
|
||||
cairo_rectangle(cr, x, y, w, h);
|
||||
cairo_set_source_rgba( cr, 100 / 255.f, 100 / 255.f , 100 / 255.f , 1 );
|
||||
cairo_stroke( cr );
|
||||
}
|
||||
|
||||
//cout << "waveform draw() done" << endl;
|
||||
|
||||
cairo_restore(cr);
|
||||
}
|
||||
}
|
||||
|
||||
void resize(int X, int Y, int W, int H)
|
||||
{
|
||||
Fl_Widget::resize(X,Y,W,H);
|
||||
|
||||
// take the smaller value
|
||||
long newSize = W > w ? W : w;
|
||||
printf("Waveform new size %li, from %i\n", newSize, w );
|
||||
|
||||
x = X;
|
||||
y = Y;
|
||||
w = W;
|
||||
h = H;
|
||||
|
||||
// FIXME: needs to be resampled, not clipped at end
|
||||
// delete old data, and resize it
|
||||
float* newData = (float*)malloc( sizeof(float) * w );
|
||||
|
||||
memcpy( newData, data, newSize );
|
||||
free ( data );
|
||||
data = newData;
|
||||
|
||||
newWaveform = true;
|
||||
|
||||
|
||||
redraw();
|
||||
}
|
||||
|
||||
int handle(int event)
|
||||
{
|
||||
return 0;
|
||||
|
||||
switch(event) {
|
||||
case FL_PUSH:
|
||||
highlight = 0;
|
||||
redraw();
|
||||
return 1;
|
||||
case FL_DRAG: {
|
||||
int t = Fl::event_inside(this);
|
||||
if (t != highlight) {
|
||||
redraw();
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
case FL_RELEASE:
|
||||
if (highlight) {
|
||||
highlight = 0;
|
||||
redraw();
|
||||
do_callback();
|
||||
}
|
||||
return 1;
|
||||
case FL_SHORTCUT:
|
||||
if ( test_shortcut() ) {
|
||||
do_callback();
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
default:
|
||||
return Fl_Widget::handle(event);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // Avtk
|
||||
|
|
172
src/buffers.hxx
172
src/buffers.hxx
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -24,91 +24,91 @@
|
|||
|
||||
class Buffers
|
||||
{
|
||||
public:
|
||||
|
||||
enum BUFFER {
|
||||
// AUDIO
|
||||
MASTER_INPUT = 0,
|
||||
|
||||
MASTER_OUT_L,
|
||||
MASTER_OUT_R,
|
||||
|
||||
JACK_SEND_OUT,
|
||||
JACK_MASTER_OUT_L,
|
||||
JACK_MASTER_OUT_R,
|
||||
JACK_SIDECHAIN_KEY,
|
||||
JACK_SIDECHAIN_SIGNAL,
|
||||
|
||||
SEND,
|
||||
SIDECHAIN_KEY,
|
||||
SIDECHAIN_SIGNAL,
|
||||
|
||||
MASTER_RETURN_L,
|
||||
MASTER_RETURN_R,
|
||||
|
||||
HEADPHONES_OUT,
|
||||
|
||||
// MIDI
|
||||
MASTER_MIDI_INPUT,
|
||||
|
||||
// track buffers: they are the "working" buffers per track:
|
||||
// the end result is mixed into the master output, while each
|
||||
// stage along the way the amplitude etc can be analysed
|
||||
TRACK_0,
|
||||
TRACK_1,
|
||||
TRACK_2,
|
||||
TRACK_3,
|
||||
TRACK_4,
|
||||
TRACK_5,
|
||||
TRACK_6,
|
||||
TRACK_7,
|
||||
//Per track sends/returns
|
||||
SEND_TRACK_0,
|
||||
SEND_TRACK_1,
|
||||
SEND_TRACK_2,
|
||||
SEND_TRACK_3,
|
||||
SEND_TRACK_4,
|
||||
SEND_TRACK_5,
|
||||
SEND_TRACK_6,
|
||||
SEND_TRACK_7,
|
||||
RETURN_TRACK_0,
|
||||
RETURN_TRACK_1,
|
||||
RETURN_TRACK_2,
|
||||
RETURN_TRACK_3,
|
||||
RETURN_TRACK_4,
|
||||
RETURN_TRACK_5,
|
||||
RETURN_TRACK_6,
|
||||
RETURN_TRACK_7,
|
||||
public:
|
||||
|
||||
JACK_TRACK_0,
|
||||
JACK_TRACK_1,
|
||||
JACK_TRACK_2,
|
||||
JACK_TRACK_3,
|
||||
JACK_TRACK_4,
|
||||
JACK_TRACK_5,
|
||||
JACK_TRACK_6,
|
||||
JACK_TRACK_7,
|
||||
enum BUFFER {
|
||||
// AUDIO
|
||||
MASTER_INPUT = 0,
|
||||
|
||||
MASTER_OUT_L,
|
||||
MASTER_OUT_R,
|
||||
|
||||
JACK_SEND_OUT,
|
||||
JACK_MASTER_OUT_L,
|
||||
JACK_MASTER_OUT_R,
|
||||
JACK_SIDECHAIN_KEY,
|
||||
JACK_SIDECHAIN_SIGNAL,
|
||||
|
||||
SEND,
|
||||
SIDECHAIN_KEY,
|
||||
SIDECHAIN_SIGNAL,
|
||||
|
||||
MASTER_RETURN_L,
|
||||
MASTER_RETURN_R,
|
||||
|
||||
HEADPHONES_OUT,
|
||||
|
||||
// MIDI
|
||||
MASTER_MIDI_INPUT,
|
||||
|
||||
// track buffers: they are the "working" buffers per track:
|
||||
// the end result is mixed into the master output, while each
|
||||
// stage along the way the amplitude etc can be analysed
|
||||
TRACK_0,
|
||||
TRACK_1,
|
||||
TRACK_2,
|
||||
TRACK_3,
|
||||
TRACK_4,
|
||||
TRACK_5,
|
||||
TRACK_6,
|
||||
TRACK_7,
|
||||
//Per track sends/returns
|
||||
SEND_TRACK_0,
|
||||
SEND_TRACK_1,
|
||||
SEND_TRACK_2,
|
||||
SEND_TRACK_3,
|
||||
SEND_TRACK_4,
|
||||
SEND_TRACK_5,
|
||||
SEND_TRACK_6,
|
||||
SEND_TRACK_7,
|
||||
RETURN_TRACK_0,
|
||||
RETURN_TRACK_1,
|
||||
RETURN_TRACK_2,
|
||||
RETURN_TRACK_3,
|
||||
RETURN_TRACK_4,
|
||||
RETURN_TRACK_5,
|
||||
RETURN_TRACK_6,
|
||||
RETURN_TRACK_7,
|
||||
|
||||
JACK_TRACK_0,
|
||||
JACK_TRACK_1,
|
||||
JACK_TRACK_2,
|
||||
JACK_TRACK_3,
|
||||
JACK_TRACK_4,
|
||||
JACK_TRACK_5,
|
||||
JACK_TRACK_6,
|
||||
JACK_TRACK_7,
|
||||
|
||||
|
||||
BUFFER_COUNT,
|
||||
};
|
||||
|
||||
Buffers()
|
||||
{
|
||||
memset( audio, 0, sizeof(float*)*BUFFER_COUNT);
|
||||
memset( midi , 0, sizeof(void *)*BUFFER_COUNT);
|
||||
}
|
||||
float* audio[BUFFER_COUNT];
|
||||
void* midi [BUFFER_COUNT];
|
||||
|
||||
// Jack details
|
||||
jack_nframes_t nframes;
|
||||
jack_nframes_t samplerate;
|
||||
|
||||
jack_nframes_t transportFrame;
|
||||
jack_position_t* transportPosition;
|
||||
jack_transport_state_t* transportState;
|
||||
|
||||
|
||||
BUFFER_COUNT,
|
||||
};
|
||||
|
||||
Buffers()
|
||||
{
|
||||
memset( audio, 0, sizeof(float*)*BUFFER_COUNT);
|
||||
memset( midi , 0, sizeof(void *)*BUFFER_COUNT);
|
||||
}
|
||||
float* audio[BUFFER_COUNT];
|
||||
void* midi [BUFFER_COUNT];
|
||||
|
||||
// Jack details
|
||||
jack_nframes_t nframes;
|
||||
jack_nframes_t samplerate;
|
||||
|
||||
jack_nframes_t transportFrame;
|
||||
jack_position_t* transportPosition;
|
||||
jack_transport_state_t* transportState;
|
||||
|
||||
};
|
||||
|
||||
#endif // LUPPP_BUFFERS_H
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -27,32 +27,35 @@ typedef int LupppAction;
|
|||
|
||||
class Binding
|
||||
{
|
||||
public:
|
||||
Binding() : status(0), data(0), action(0), active(-1),
|
||||
track(-2),scene(-1),send(-1) { ID = privateID++; }
|
||||
|
||||
int ID;
|
||||
|
||||
unsigned char status;
|
||||
unsigned char data;
|
||||
|
||||
/// the action this binding relates to: this is an integer based on the
|
||||
/// event.hxx enumeration of event types
|
||||
LupppAction action;
|
||||
|
||||
/// arguments to the event: track number, scene number etc
|
||||
int active;
|
||||
int track;
|
||||
int scene;
|
||||
int send;
|
||||
|
||||
/// maps from Gridlogic::State to MIDI output value from binding
|
||||
std::map<int,int> clipStateMap;
|
||||
|
||||
private:
|
||||
/// static int counter to allow deleting this specific instance
|
||||
static int privateID;
|
||||
|
||||
public:
|
||||
Binding() : status(0), data(0), action(0), active(-1),
|
||||
track(-2),scene(-1),send(-1)
|
||||
{
|
||||
ID = privateID++;
|
||||
}
|
||||
|
||||
int ID;
|
||||
|
||||
unsigned char status;
|
||||
unsigned char data;
|
||||
|
||||
/// the action this binding relates to: this is an integer based on the
|
||||
/// event.hxx enumeration of event types
|
||||
LupppAction action;
|
||||
|
||||
/// arguments to the event: track number, scene number etc
|
||||
int active;
|
||||
int track;
|
||||
int scene;
|
||||
int send;
|
||||
|
||||
/// maps from Gridlogic::State to MIDI output value from binding
|
||||
std::map<int,int> clipStateMap;
|
||||
|
||||
private:
|
||||
/// static int counter to allow deleting this specific instance
|
||||
static int privateID;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -29,7 +29,7 @@ int Controller::privateID = 0;
|
|||
|
||||
Controller::Controller()
|
||||
{
|
||||
ID = privateID++;
|
||||
ID = privateID++;
|
||||
}
|
||||
|
||||
void Controller::reset()
|
||||
|
@ -38,5 +38,5 @@ void Controller::reset()
|
|||
|
||||
int Controller::getID()
|
||||
{
|
||||
return ID;
|
||||
return ID;
|
||||
}
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -31,66 +31,72 @@
|
|||
**/
|
||||
class Controller
|
||||
{
|
||||
public:
|
||||
/// used to report the controller status
|
||||
enum STATUS {
|
||||
CONTROLLER_ERROR = 0,
|
||||
CONTROLLER_OK,
|
||||
};
|
||||
|
||||
/// creates the controller instance: this is called in the non-RT thread
|
||||
Controller();
|
||||
|
||||
/// controllers have a unique ID
|
||||
int getID();
|
||||
|
||||
/// allows instance to register MIDI observer type functionality
|
||||
virtual int registerComponents(){return 0;}
|
||||
|
||||
virtual ~Controller(){};
|
||||
|
||||
/// get the status of the controller
|
||||
virtual STATUS status(){return CONTROLLER_OK;}
|
||||
|
||||
/// name string to show in UI
|
||||
virtual std::string getName() = 0;
|
||||
|
||||
/// master
|
||||
virtual void masterInputVol(float f){}
|
||||
virtual void masterInputTo(int to,float f){}
|
||||
virtual void masterInputToActive(int to,float f){}
|
||||
virtual void masterVolume(float f){}
|
||||
virtual void masterReturnVolume(float f){}
|
||||
virtual void metronomeEnable(bool b){}
|
||||
|
||||
/// FX
|
||||
virtual void trackSend(int t, int send, float v){}
|
||||
virtual void trackSendActive(int t, int send, bool a){}
|
||||
public:
|
||||
/// used to report the controller status
|
||||
enum STATUS {
|
||||
CONTROLLER_ERROR = 0,
|
||||
CONTROLLER_OK,
|
||||
};
|
||||
|
||||
virtual void trackJackSend(int t, float v){}
|
||||
virtual void trackJackSendActivate(int t, bool a){}
|
||||
|
||||
/// Time
|
||||
virtual void bpm(int bpm){}
|
||||
virtual void tapTempo(bool b){}
|
||||
|
||||
/// Special
|
||||
virtual void specialScene(int t, int scene){}
|
||||
|
||||
/// track functionality
|
||||
virtual void mute(int t, bool b){}
|
||||
virtual void volume(int t, float f){}
|
||||
virtual void progress(int t, int s, float f){}
|
||||
virtual void recordArm(int t, bool r){}
|
||||
virtual void setSceneState(int track, int scene, GridLogic::State s){}
|
||||
virtual void launchScene( int scene ){}
|
||||
|
||||
/// reset controller
|
||||
virtual void reset();
|
||||
|
||||
private:
|
||||
static int privateID;
|
||||
int ID;
|
||||
/// creates the controller instance: this is called in the non-RT thread
|
||||
Controller();
|
||||
|
||||
/// controllers have a unique ID
|
||||
int getID();
|
||||
|
||||
/// allows instance to register MIDI observer type functionality
|
||||
virtual int registerComponents()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual ~Controller() {};
|
||||
|
||||
/// get the status of the controller
|
||||
virtual STATUS status()
|
||||
{
|
||||
return CONTROLLER_OK;
|
||||
}
|
||||
|
||||
/// name string to show in UI
|
||||
virtual std::string getName() = 0;
|
||||
|
||||
/// master
|
||||
virtual void masterInputVol(float f) {}
|
||||
virtual void masterInputTo(int to,float f) {}
|
||||
virtual void masterInputToActive(int to,float f) {}
|
||||
virtual void masterVolume(float f) {}
|
||||
virtual void masterReturnVolume(float f) {}
|
||||
virtual void metronomeEnable(bool b) {}
|
||||
|
||||
/// FX
|
||||
virtual void trackSend(int t, int send, float v) {}
|
||||
virtual void trackSendActive(int t, int send, bool a) {}
|
||||
|
||||
virtual void trackJackSend(int t, float v) {}
|
||||
virtual void trackJackSendActivate(int t, bool a) {}
|
||||
|
||||
/// Time
|
||||
virtual void bpm(int bpm) {}
|
||||
virtual void tapTempo(bool b) {}
|
||||
|
||||
/// Special
|
||||
virtual void specialScene(int t, int scene) {}
|
||||
|
||||
/// track functionality
|
||||
virtual void mute(int t, bool b) {}
|
||||
virtual void volume(int t, float f) {}
|
||||
virtual void progress(int t, int s, float f) {}
|
||||
virtual void recordArm(int t, bool r) {}
|
||||
virtual void setSceneState(int track, int scene, GridLogic::State s) {}
|
||||
virtual void launchScene( int scene ) {}
|
||||
|
||||
/// reset controller
|
||||
virtual void reset();
|
||||
|
||||
private:
|
||||
static int privateID;
|
||||
int ID;
|
||||
};
|
||||
|
||||
#endif // LUPPP_CONTROLLER_H
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -36,96 +36,96 @@
|
|||
**/
|
||||
class GenericMIDI : public Controller, public MidiIO
|
||||
{
|
||||
public:
|
||||
/// Creates a blank GenericMIDI instance, which can be bound dynamically
|
||||
GenericMIDI(int waste = 0, std::string name = "generic");
|
||||
|
||||
/// Attempts to load a .ctlr file, pointed to by the string
|
||||
GenericMIDI(std::string file);
|
||||
|
||||
int registerComponents();
|
||||
|
||||
Controller::STATUS status();
|
||||
|
||||
void setName(std::string );
|
||||
std::string getName();
|
||||
std::string getAuthor();
|
||||
std::string getEmail();
|
||||
|
||||
/// track actions
|
||||
//void mute(int t, bool b);
|
||||
|
||||
void metronomeEnable(bool b);
|
||||
|
||||
void launchScene( int scene );
|
||||
|
||||
void volume(int t, float f);
|
||||
|
||||
|
||||
void recordArm(int t, bool b);
|
||||
void setSceneState(int track, int clip, GridLogic::State s);
|
||||
|
||||
/*
|
||||
void progress(int t, int s, float f);
|
||||
void launchScene( int scene );
|
||||
|
||||
/// track FX
|
||||
void trackSend(int t, int send, float v);
|
||||
*/
|
||||
|
||||
void trackSend(int t, int send, float v);
|
||||
void trackSendActive(int t, int send, bool a);
|
||||
public:
|
||||
/// Creates a blank GenericMIDI instance, which can be bound dynamically
|
||||
GenericMIDI(int waste = 0, std::string name = "generic");
|
||||
|
||||
virtual void trackJackSend(int t, float v);
|
||||
virtual void trackJackSendActivate(int t, bool a);
|
||||
|
||||
/// footswitch -> scene launch controls
|
||||
void setFootswitchToNextScene(int v);
|
||||
bool footswitchNextScene;
|
||||
bool footswitchPrevScene;
|
||||
|
||||
|
||||
void reset();
|
||||
|
||||
void midi(unsigned char* data);
|
||||
|
||||
void process(int nframes);
|
||||
|
||||
const std::vector<Binding*>& getMidiToAction();
|
||||
|
||||
// for adding bindings from MIDI / GUI event pair
|
||||
void setupBinding( LupppAction eventType, int midiStatus, int midiData, int track, int scene, int send, int active );
|
||||
void removeBinding( int bindingID );
|
||||
|
||||
private:
|
||||
STATUS stat;
|
||||
|
||||
std::string name;
|
||||
std::string author;
|
||||
std::string email;
|
||||
|
||||
/// contains midi binding instances
|
||||
std::vector<Binding*> midiToAction;
|
||||
std::vector<Binding*> actionToMidi;
|
||||
|
||||
int loadController(std::string controllerFile);
|
||||
|
||||
/// creates a binding from a cJSON inputBindings / outputBindings object
|
||||
Binding* setupBinding( cJSON* bindings );
|
||||
|
||||
|
||||
/// for "sampling" a clip in the grid, and applying events to it:
|
||||
/// footpedal for example
|
||||
bool shiftPressed;
|
||||
int footpedalTrack;
|
||||
int footpedalScene;
|
||||
|
||||
/*
|
||||
/// for handling events
|
||||
void ccChange( int track, int cc, float value );
|
||||
void noteOff( int track, int note, int vel );
|
||||
void noteOn( int track, int note, int vel );
|
||||
*/
|
||||
/// Attempts to load a .ctlr file, pointed to by the string
|
||||
GenericMIDI(std::string file);
|
||||
|
||||
int registerComponents();
|
||||
|
||||
Controller::STATUS status();
|
||||
|
||||
void setName(std::string );
|
||||
std::string getName();
|
||||
std::string getAuthor();
|
||||
std::string getEmail();
|
||||
|
||||
/// track actions
|
||||
//void mute(int t, bool b);
|
||||
|
||||
void metronomeEnable(bool b);
|
||||
|
||||
void launchScene( int scene );
|
||||
|
||||
void volume(int t, float f);
|
||||
|
||||
|
||||
void recordArm(int t, bool b);
|
||||
void setSceneState(int track, int clip, GridLogic::State s);
|
||||
|
||||
/*
|
||||
void progress(int t, int s, float f);
|
||||
void launchScene( int scene );
|
||||
|
||||
/// track FX
|
||||
void trackSend(int t, int send, float v);
|
||||
*/
|
||||
|
||||
void trackSend(int t, int send, float v);
|
||||
void trackSendActive(int t, int send, bool a);
|
||||
|
||||
virtual void trackJackSend(int t, float v);
|
||||
virtual void trackJackSendActivate(int t, bool a);
|
||||
|
||||
/// footswitch -> scene launch controls
|
||||
void setFootswitchToNextScene(int v);
|
||||
bool footswitchNextScene;
|
||||
bool footswitchPrevScene;
|
||||
|
||||
|
||||
void reset();
|
||||
|
||||
void midi(unsigned char* data);
|
||||
|
||||
void process(int nframes);
|
||||
|
||||
const std::vector<Binding*>& getMidiToAction();
|
||||
|
||||
// for adding bindings from MIDI / GUI event pair
|
||||
void setupBinding( LupppAction eventType, int midiStatus, int midiData, int track, int scene, int send, int active );
|
||||
void removeBinding( int bindingID );
|
||||
|
||||
private:
|
||||
STATUS stat;
|
||||
|
||||
std::string name;
|
||||
std::string author;
|
||||
std::string email;
|
||||
|
||||
/// contains midi binding instances
|
||||
std::vector<Binding*> midiToAction;
|
||||
std::vector<Binding*> actionToMidi;
|
||||
|
||||
int loadController(std::string controllerFile);
|
||||
|
||||
/// creates a binding from a cJSON inputBindings / outputBindings object
|
||||
Binding* setupBinding( cJSON* bindings );
|
||||
|
||||
|
||||
/// for "sampling" a clip in the grid, and applying events to it:
|
||||
/// footpedal for example
|
||||
bool shiftPressed;
|
||||
int footpedalTrack;
|
||||
int footpedalScene;
|
||||
|
||||
/*
|
||||
/// for handling events
|
||||
void ccChange( int track, int cc, float value );
|
||||
void noteOff( int track, int note, int vel );
|
||||
void noteOn( int track, int note, int vel );
|
||||
*/
|
||||
};
|
||||
|
||||
#endif // LUPPP_GENERIC_MIDI_H
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -30,120 +30,120 @@
|
|||
extern Jack* jack;
|
||||
|
||||
LupppGUI::LupppGUI() :
|
||||
Controller()
|
||||
Controller()
|
||||
{
|
||||
}
|
||||
|
||||
void LupppGUI::masterInputVol(float f)
|
||||
{
|
||||
EventMasterInputVol e( f );
|
||||
writeToGuiRingbuffer( &e );
|
||||
EventMasterInputVol e( f );
|
||||
writeToGuiRingbuffer( &e );
|
||||
}
|
||||
|
||||
void LupppGUI::masterInputTo(int to,float f)
|
||||
{
|
||||
EventMasterInputTo e( (Event::INPUT_TO)to, f );
|
||||
writeToGuiRingbuffer( &e );
|
||||
EventMasterInputTo e( (Event::INPUT_TO)to, f );
|
||||
writeToGuiRingbuffer( &e );
|
||||
}
|
||||
|
||||
void LupppGUI::masterInputToActive(int to,float f)
|
||||
{
|
||||
EventMasterInputToActive e( (Event::INPUT_TO)to, f );
|
||||
writeToGuiRingbuffer( &e );
|
||||
EventMasterInputToActive e( (Event::INPUT_TO)to, f );
|
||||
writeToGuiRingbuffer( &e );
|
||||
}
|
||||
|
||||
void LupppGUI::masterVolume(float f)
|
||||
{
|
||||
EventMasterVol e( f );
|
||||
writeToGuiRingbuffer( &e );
|
||||
EventMasterVol e( f );
|
||||
writeToGuiRingbuffer( &e );
|
||||
}
|
||||
|
||||
void LupppGUI::masterReturnVolume(float f)
|
||||
{
|
||||
printf(" return %f ", f );
|
||||
EventMasterReturn e( RETURN_MAIN, f );
|
||||
writeToGuiRingbuffer( &e );
|
||||
printf(" return %f ", f );
|
||||
EventMasterReturn e( RETURN_MAIN, f );
|
||||
writeToGuiRingbuffer( &e );
|
||||
}
|
||||
|
||||
void LupppGUI::metronomeEnable(bool r)
|
||||
{
|
||||
EventMetronomeActive e( r );
|
||||
writeToGuiRingbuffer( &e );
|
||||
EventMetronomeActive e( r );
|
||||
writeToGuiRingbuffer( &e );
|
||||
}
|
||||
|
||||
void LupppGUI::recordArm(int t, bool r)
|
||||
{
|
||||
EventTrackRecordArm e( t, r );
|
||||
writeToGuiRingbuffer( &e );
|
||||
EventTrackRecordArm e( t, r );
|
||||
writeToGuiRingbuffer( &e );
|
||||
}
|
||||
|
||||
void LupppGUI::trackSend(int t, int send, float r)
|
||||
{
|
||||
EventTrackSend e( t, static_cast<Event::SEND_TYPE>(send), r );
|
||||
writeToGuiRingbuffer( &e );
|
||||
EventTrackSend e( t, static_cast<Event::SEND_TYPE>(send), r );
|
||||
writeToGuiRingbuffer( &e );
|
||||
}
|
||||
|
||||
void LupppGUI::specialScene(int t, int s)
|
||||
{
|
||||
EventGridSelectNewChosen e( t, s );
|
||||
writeToGuiRingbuffer( &e );
|
||||
EventGridSelectNewChosen e( t, s );
|
||||
writeToGuiRingbuffer( &e );
|
||||
}
|
||||
|
||||
void LupppGUI::trackSendActive(int t, int send, bool a)
|
||||
{
|
||||
EventTrackSendActive e( t, static_cast<Event::SEND_TYPE>(send), a );
|
||||
writeToGuiRingbuffer( &e );
|
||||
EventTrackSendActive e( t, static_cast<Event::SEND_TYPE>(send), a );
|
||||
writeToGuiRingbuffer( &e );
|
||||
}
|
||||
|
||||
void LupppGUI::trackJackSend(int t, float v)
|
||||
{
|
||||
EventTrackJackSend e(t,v);
|
||||
writeToGuiRingbuffer(&e);
|
||||
EventTrackJackSend e(t,v);
|
||||
writeToGuiRingbuffer(&e);
|
||||
}
|
||||
|
||||
void LupppGUI::trackJackSendActivate(int t, bool a)
|
||||
{
|
||||
EventTrackJackSendActivate e(t,a);
|
||||
writeToGuiRingbuffer(&e);
|
||||
EventTrackJackSendActivate e(t,a);
|
||||
writeToGuiRingbuffer(&e);
|
||||
}
|
||||
|
||||
void LupppGUI::setSceneState(int t, int clip, GridLogic::State s)
|
||||
{
|
||||
EventGridState e( t, clip, s );
|
||||
writeToGuiRingbuffer( &e );
|
||||
EventGridState e( t, clip, s );
|
||||
writeToGuiRingbuffer( &e );
|
||||
}
|
||||
|
||||
void LupppGUI::launchScene( int scene )
|
||||
{
|
||||
EventGridLaunchScene e( scene );
|
||||
writeToGuiRingbuffer( &e );
|
||||
EventGridLaunchScene e( scene );
|
||||
writeToGuiRingbuffer( &e );
|
||||
}
|
||||
|
||||
void LupppGUI::mute(int t, bool b)
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
void LupppGUI::tapTempo( bool b )
|
||||
{
|
||||
EventTimeTempoTap e(b);
|
||||
writeToGuiRingbuffer( &e );
|
||||
EventTimeTempoTap e(b);
|
||||
writeToGuiRingbuffer( &e );
|
||||
}
|
||||
|
||||
void LupppGUI::bpm(int bpm)
|
||||
{
|
||||
EventTimeBPM e(bpm);
|
||||
writeToGuiRingbuffer( &e );
|
||||
EventTimeBPM e(bpm);
|
||||
writeToGuiRingbuffer( &e );
|
||||
}
|
||||
|
||||
void LupppGUI::volume(int t, float f)
|
||||
{
|
||||
EventTrackVol e( t, f );
|
||||
writeToGuiRingbuffer( &e );
|
||||
EventTrackVol e( t, f );
|
||||
writeToGuiRingbuffer( &e );
|
||||
}
|
||||
|
||||
void LupppGUI::progress(int t, int s, float f)
|
||||
{
|
||||
EventLooperProgress e( t, f );
|
||||
writeToGuiRingbuffer( &e );
|
||||
EventLooperProgress e( t, f );
|
||||
writeToGuiRingbuffer( &e );
|
||||
}
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -26,37 +26,40 @@
|
|||
|
||||
class LupppGUI : public Controller
|
||||
{
|
||||
public:
|
||||
LupppGUI();
|
||||
|
||||
std::string getName(){return "Luppp GUI";}
|
||||
|
||||
void masterVolume(float f);
|
||||
void masterReturnVolume(float f);
|
||||
void masterInputVol(float v);
|
||||
void masterInputTo(int to,float f);
|
||||
void masterInputToActive(int to,float f);
|
||||
|
||||
void metronomeEnable(bool b);
|
||||
|
||||
void trackSend(int t, int send, float r);
|
||||
void trackSendActive(int t, int send, bool a);
|
||||
public:
|
||||
LupppGUI();
|
||||
|
||||
std::string getName()
|
||||
{
|
||||
return "Luppp GUI";
|
||||
}
|
||||
|
||||
void masterVolume(float f);
|
||||
void masterReturnVolume(float f);
|
||||
void masterInputVol(float v);
|
||||
void masterInputTo(int to,float f);
|
||||
void masterInputToActive(int to,float f);
|
||||
|
||||
void metronomeEnable(bool b);
|
||||
|
||||
void trackSend(int t, int send, float r);
|
||||
void trackSendActive(int t, int send, bool a);
|
||||
|
||||
virtual void trackJackSend(int t, float v);
|
||||
virtual void trackJackSendActivate(int t, bool a);
|
||||
|
||||
void bpm(int bpm);
|
||||
void tapTempo( bool b );
|
||||
|
||||
void specialScene(int t, int scene);
|
||||
|
||||
void mute(int t, bool b);
|
||||
void volume(int t, float f);
|
||||
void progress(int t, int s, float p);
|
||||
void recordArm(int t, bool b);
|
||||
void launchScene( int scene );
|
||||
void setSceneState(int track, int clip, GridLogic::State s);
|
||||
|
||||
virtual void trackJackSend(int t, float v);
|
||||
virtual void trackJackSendActivate(int t, bool a);
|
||||
|
||||
void bpm(int bpm);
|
||||
void tapTempo( bool b );
|
||||
|
||||
void specialScene(int t, int scene);
|
||||
|
||||
void mute(int t, bool b);
|
||||
void volume(int t, float f);
|
||||
void progress(int t, int s, float p);
|
||||
void recordArm(int t, bool b);
|
||||
void launchScene( int scene );
|
||||
void setSceneState(int track, int clip, GridLogic::State s);
|
||||
|
||||
};
|
||||
|
||||
#endif // LUPPP_CONTROLLER_GUI_H
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -26,56 +26,56 @@
|
|||
#include "../looperclip.hxx"
|
||||
|
||||
NonSeq::NonSeq() :
|
||||
Controller(),
|
||||
MidiIO()
|
||||
Controller(),
|
||||
MidiIO()
|
||||
{
|
||||
std::string name = "non-seq";
|
||||
registerMidiPorts( name );
|
||||
std::string name = "non-seq";
|
||||
registerMidiPorts( name );
|
||||
}
|
||||
|
||||
void NonSeq::launchScene( int scene )
|
||||
{
|
||||
unsigned char data[3];
|
||||
data[0] = 176;
|
||||
data[1] = 20;
|
||||
data[2] = scene;
|
||||
|
||||
//LUPPP_NOTE("NonSeq::launchScene() %i, %i, %i\n", data[0],data[1],data[2] );
|
||||
writeMidi( data );
|
||||
unsigned char data[3];
|
||||
data[0] = 176;
|
||||
data[1] = 20;
|
||||
data[2] = scene;
|
||||
|
||||
//LUPPP_NOTE("NonSeq::launchScene() %i, %i, %i\n", data[0],data[1],data[2] );
|
||||
writeMidi( data );
|
||||
}
|
||||
|
||||
std::string NonSeq::getName()
|
||||
{
|
||||
return "non-seq";
|
||||
return "non-seq";
|
||||
}
|
||||
|
||||
|
||||
void NonSeq::setSceneState(int track, int scene, GridLogic::State s)
|
||||
{
|
||||
unsigned char data[3];
|
||||
data[0] = 176;
|
||||
data[1] = 22; // off
|
||||
|
||||
// check *actual* value of playing: *NOT* GridState::s, because it could be queued
|
||||
// for something else, but we want the *actual* here, not "queued". This is a unique
|
||||
// use case because were trying to control non-seq as if it were part of Luppp.
|
||||
if( jack->getLooper( track )->getClip( scene )->playing() )
|
||||
data[1] = 21;
|
||||
|
||||
data[2] = track;
|
||||
|
||||
//LUPPP_NOTE("NonSeq::setSceneState() %i, %i, %i\n", data[0],data[1],data[2] );
|
||||
writeMidi( data );
|
||||
unsigned char data[3];
|
||||
data[0] = 176;
|
||||
data[1] = 22; // off
|
||||
|
||||
// check *actual* value of playing: *NOT* GridState::s, because it could be queued
|
||||
// for something else, but we want the *actual* here, not "queued". This is a unique
|
||||
// use case because were trying to control non-seq as if it were part of Luppp.
|
||||
if( jack->getLooper( track )->getClip( scene )->playing() )
|
||||
data[1] = 21;
|
||||
|
||||
data[2] = track;
|
||||
|
||||
//LUPPP_NOTE("NonSeq::setSceneState() %i, %i, %i\n", data[0],data[1],data[2] );
|
||||
writeMidi( data );
|
||||
}
|
||||
|
||||
|
||||
int NonSeq::registerComponents()
|
||||
{
|
||||
// makes JACK add this controller to the midiObservers list:
|
||||
// note the static_cast<>() is *needed* here for multiple-inheritance
|
||||
MidiIO* m = static_cast<MidiIO*>(this);
|
||||
|
||||
jack->registerMidiIO( m );
|
||||
|
||||
return LUPPP_RETURN_OK;
|
||||
// makes JACK add this controller to the midiObservers list:
|
||||
// note the static_cast<>() is *needed* here for multiple-inheritance
|
||||
MidiIO* m = static_cast<MidiIO*>(this);
|
||||
|
||||
jack->registerMidiIO( m );
|
||||
|
||||
return LUPPP_RETURN_OK;
|
||||
}
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -29,17 +29,17 @@
|
|||
**/
|
||||
class NonSeq : public Controller, public MidiIO
|
||||
{
|
||||
public:
|
||||
NonSeq();
|
||||
~NonSeq(){};
|
||||
|
||||
std::string getName();
|
||||
|
||||
int registerComponents();
|
||||
|
||||
void launchScene( int scene );
|
||||
|
||||
void setSceneState(int track, int scene, GridLogic::State s);
|
||||
public:
|
||||
NonSeq();
|
||||
~NonSeq() {};
|
||||
|
||||
std::string getName();
|
||||
|
||||
int registerComponents();
|
||||
|
||||
void launchScene( int scene );
|
||||
|
||||
void setSceneState(int track, int scene, GridLogic::State s);
|
||||
};
|
||||
|
||||
#endif // LUPPP_NON_SEQ_H
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -22,167 +22,162 @@
|
|||
|
||||
ControllerUpdater::ControllerUpdater()
|
||||
{
|
||||
// CAREFUL size of controllers: otherwise malloc() called
|
||||
c.reserve( CONTROLLERS_PREALLOC );
|
||||
// CAREFUL size of controllers: otherwise malloc() called
|
||||
c.reserve( CONTROLLERS_PREALLOC );
|
||||
}
|
||||
|
||||
void ControllerUpdater::registerController( Controller* controller )
|
||||
{
|
||||
if (!controller)
|
||||
{
|
||||
LUPPP_ERROR("Register Controller passed NULL controller!");
|
||||
return;
|
||||
}
|
||||
|
||||
//LUPPP_NOTE("Registering controller %s", controller->getName().c_str() );
|
||||
|
||||
// store the controller instance
|
||||
c.push_back( controller );
|
||||
|
||||
// and tell it to register itself (MidiObserver / AudioObserver etc)
|
||||
controller->registerComponents();
|
||||
if (!controller) {
|
||||
LUPPP_ERROR("Register Controller passed NULL controller!");
|
||||
return;
|
||||
}
|
||||
|
||||
//LUPPP_NOTE("Registering controller %s", controller->getName().c_str() );
|
||||
|
||||
// store the controller instance
|
||||
c.push_back( controller );
|
||||
|
||||
// and tell it to register itself (MidiObserver / AudioObserver etc)
|
||||
controller->registerComponents();
|
||||
}
|
||||
|
||||
void ControllerUpdater::removeController( int id )
|
||||
{
|
||||
for( unsigned int i = 0; i < c.size(); i++)
|
||||
{
|
||||
if ( c.at(i)->getID() == id )
|
||||
{
|
||||
// keep pointer: otherwise we mem-leak
|
||||
Controller* removed = c.at( i );
|
||||
|
||||
cout << "Removing item " << i << " with name " << removed->getName() << endl;
|
||||
|
||||
// remove the instance at
|
||||
c.erase( c.begin() + i );
|
||||
|
||||
// send it for de-allocation
|
||||
EventControllerInstance e( removed );
|
||||
writeToGuiRingbuffer( &e );
|
||||
}
|
||||
}
|
||||
|
||||
for( unsigned int i = 0; i < c.size(); i++) {
|
||||
if ( c.at(i)->getID() == id ) {
|
||||
// keep pointer: otherwise we mem-leak
|
||||
Controller* removed = c.at( i );
|
||||
|
||||
cout << "Removing item " << i << " with name " << removed->getName() << endl;
|
||||
|
||||
// remove the instance at
|
||||
c.erase( c.begin() + i );
|
||||
|
||||
// send it for de-allocation
|
||||
EventControllerInstance e( removed );
|
||||
writeToGuiRingbuffer( &e );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Controller* ControllerUpdater::getController(int id)
|
||||
{
|
||||
// search controllers for ID, if found return a pointer to it
|
||||
for( unsigned int i = 0; i < c.size(); i++)
|
||||
{
|
||||
if ( c.at(i)->getID() == id )
|
||||
{
|
||||
LUPPP_NOTE("getController target ID: %i, found ID: %i, returning %s", id, i, c.at(i)->getName().c_str() );
|
||||
return c.at(i);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
// search controllers for ID, if found return a pointer to it
|
||||
for( unsigned int i = 0; i < c.size(); i++) {
|
||||
if ( c.at(i)->getID() == id ) {
|
||||
LUPPP_NOTE("getController target ID: %i, found ID: %i, returning %s", id, i, c.at(i)->getName().c_str() );
|
||||
return c.at(i);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ControllerUpdater::reset()
|
||||
{
|
||||
for(unsigned int i = 0; i < c.size(); i++)
|
||||
c.at(i)->reset();
|
||||
for(unsigned int i = 0; i < c.size(); i++)
|
||||
c.at(i)->reset();
|
||||
}
|
||||
|
||||
void ControllerUpdater::mute(int t, bool b)
|
||||
{
|
||||
for(unsigned int i = 0; i < c.size(); i++)
|
||||
c.at(i)->mute(t,b);
|
||||
for(unsigned int i = 0; i < c.size(); i++)
|
||||
c.at(i)->mute(t,b);
|
||||
}
|
||||
|
||||
void ControllerUpdater::masterVolume(float v)
|
||||
{
|
||||
for(unsigned int i = 0; i < c.size(); i++)
|
||||
c.at(i)->masterVolume(v);
|
||||
for(unsigned int i = 0; i < c.size(); i++)
|
||||
c.at(i)->masterVolume(v);
|
||||
}
|
||||
|
||||
void ControllerUpdater::masterReturnVolume(float v)
|
||||
{
|
||||
for(unsigned int i = 0; i < c.size(); i++)
|
||||
c.at(i)->masterReturnVolume( v );
|
||||
for(unsigned int i = 0; i < c.size(); i++)
|
||||
c.at(i)->masterReturnVolume( v );
|
||||
}
|
||||
|
||||
void ControllerUpdater::setTrackSceneProgress(int t, int s, float p)
|
||||
{
|
||||
for(unsigned int i = 0; i < c.size(); i++)
|
||||
c.at(i)->progress(t,s,p);
|
||||
for(unsigned int i = 0; i < c.size(); i++)
|
||||
c.at(i)->progress(t,s,p);
|
||||
}
|
||||
|
||||
void ControllerUpdater::setTrackSendActive(int t, int send, bool v)
|
||||
{
|
||||
for(unsigned int i = 0; i < c.size(); i++)
|
||||
c.at(i)->trackSendActive(t, send, v);
|
||||
for(unsigned int i = 0; i < c.size(); i++)
|
||||
c.at(i)->trackSendActive(t, send, v);
|
||||
}
|
||||
void ControllerUpdater::setTrackSend(int t, int send, float v)
|
||||
{
|
||||
for(unsigned int i = 0; i < c.size(); i++)
|
||||
c.at(i)->trackSend(t, send, v);
|
||||
for(unsigned int i = 0; i < c.size(); i++)
|
||||
c.at(i)->trackSend(t, send, v);
|
||||
}
|
||||
|
||||
void ControllerUpdater::setTrackJackSendActive(int t, bool v)
|
||||
{
|
||||
for(unsigned int i = 0; i < c.size(); i++)
|
||||
c.at(i)->trackJackSendActivate(t, v);
|
||||
for(unsigned int i = 0; i < c.size(); i++)
|
||||
c.at(i)->trackJackSendActivate(t, v);
|
||||
}
|
||||
|
||||
void ControllerUpdater::setTrackJackSend(int t, float v)
|
||||
{
|
||||
for(unsigned int i = 0; i < c.size(); i++)
|
||||
c.at(i)->trackJackSend(t, v);
|
||||
for(unsigned int i = 0; i < c.size(); i++)
|
||||
c.at(i)->trackJackSend(t, v);
|
||||
}
|
||||
|
||||
void ControllerUpdater::specialScene(int t, int scene)
|
||||
{
|
||||
for(unsigned int i = 0; i < c.size(); i++)
|
||||
c.at(i)->specialScene(t, scene);
|
||||
for(unsigned int i = 0; i < c.size(); i++)
|
||||
c.at(i)->specialScene(t, scene);
|
||||
}
|
||||
|
||||
void ControllerUpdater::masterInputToActive(int to, bool v)
|
||||
{
|
||||
for(unsigned int i = 0; i < c.size(); i++)
|
||||
c.at(i)->masterInputToActive( to, v);
|
||||
for(unsigned int i = 0; i < c.size(); i++)
|
||||
c.at(i)->masterInputToActive( to, v);
|
||||
}
|
||||
void ControllerUpdater::masterInputTo( int to, float v )
|
||||
{
|
||||
for(unsigned int i = 0; i < c.size(); i++)
|
||||
c.at(i)->masterInputTo( to, v);
|
||||
for(unsigned int i = 0; i < c.size(); i++)
|
||||
c.at(i)->masterInputTo( to, v);
|
||||
}
|
||||
void ControllerUpdater::masterInputVol( float v )
|
||||
{
|
||||
for(unsigned int i = 0; i < c.size(); i++)
|
||||
c.at(i)->masterInputVol( v );
|
||||
for(unsigned int i = 0; i < c.size(); i++)
|
||||
c.at(i)->masterInputVol( v );
|
||||
}
|
||||
|
||||
void ControllerUpdater::launchScene( int scene )
|
||||
{
|
||||
for(unsigned int i = 0; i < c.size(); i++)
|
||||
c.at(i)->launchScene(scene);
|
||||
for(unsigned int i = 0; i < c.size(); i++)
|
||||
c.at(i)->launchScene(scene);
|
||||
}
|
||||
|
||||
void ControllerUpdater::setSceneState(int t, int clip, GridLogic::State s)
|
||||
{
|
||||
for(unsigned int i = 0; i < c.size(); i++)
|
||||
c.at(i)->setSceneState(t,clip,s);
|
||||
for(unsigned int i = 0; i < c.size(); i++)
|
||||
c.at(i)->setSceneState(t,clip,s);
|
||||
}
|
||||
|
||||
void ControllerUpdater::recordArm(int t, bool r)
|
||||
{
|
||||
for(unsigned int i = 0; i < c.size(); i++)
|
||||
c.at(i)->recordArm(t,r);
|
||||
for(unsigned int i = 0; i < c.size(); i++)
|
||||
c.at(i)->recordArm(t,r);
|
||||
}
|
||||
|
||||
void ControllerUpdater::volume(int t, float v)
|
||||
{
|
||||
for(unsigned int i = 0; i < c.size(); i++) c.at(i)->volume(t,v);
|
||||
for(unsigned int i = 0; i < c.size(); i++) c.at(i)->volume(t,v);
|
||||
}
|
||||
|
||||
void ControllerUpdater::tapTempo(bool b)
|
||||
{
|
||||
for(unsigned int i = 0; i < c.size(); i++) c.at(i)->tapTempo(b);
|
||||
for(unsigned int i = 0; i < c.size(); i++) c.at(i)->tapTempo(b);
|
||||
}
|
||||
|
||||
void ControllerUpdater::metronomeEnable(bool b)
|
||||
{
|
||||
for(unsigned int i = 0; i < c.size(); i++) c.at(i)->metronomeEnable(b);
|
||||
for(unsigned int i = 0; i < c.size(); i++) c.at(i)->metronomeEnable(b);
|
||||
}
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -33,60 +33,60 @@ using namespace std;
|
|||
* Updates each registered controller when a certain event occurs. All output
|
||||
* devices (MIDI controllers, GUI, OSC-UI's etc) are registered in order to
|
||||
* stay up-to-date.
|
||||
*
|
||||
*
|
||||
* This class does no scheduling, it passes the events to the Controllers
|
||||
* immidiatly.
|
||||
*
|
||||
*
|
||||
* The Logic class is the opposite of this: it takes input and Luppp processes
|
||||
* it, pushing the relevant updates in state through ControllerUpdater to each
|
||||
* registered device.
|
||||
**/
|
||||
class ControllerUpdater
|
||||
{
|
||||
public:
|
||||
ControllerUpdater();
|
||||
|
||||
/// add a Controller* to Controllers that recieve updates
|
||||
void registerController( Controller* controller );
|
||||
|
||||
/// removes a controller by ID
|
||||
void removeController( int controllerID );
|
||||
|
||||
/// returns a Controller* from ID
|
||||
Controller* getController(int id);
|
||||
|
||||
void reset();
|
||||
void mute(int t, bool b);
|
||||
|
||||
void masterVolume(float v);
|
||||
void masterReturnVolume(float v);
|
||||
void masterInputToActive(int to, bool v);
|
||||
void masterInputTo( int inputTo, float vol );
|
||||
void masterInputVol( float vol );
|
||||
|
||||
void setTrackSceneProgress(int t, int s, float p);
|
||||
void setTrackSendActive(int t, int send, bool v);
|
||||
void setTrackSend(int t, int send, float v);
|
||||
public:
|
||||
ControllerUpdater();
|
||||
|
||||
void setTrackJackSendActive(int t, bool v);
|
||||
void setTrackJackSend(int t, float v);
|
||||
|
||||
void specialScene(int t, int scene);
|
||||
|
||||
void launchScene( int scene );
|
||||
|
||||
void setSceneState(int t, int clip, GridLogic::State s);
|
||||
|
||||
void recordArm(int t, bool r);
|
||||
|
||||
void volume(int t, float v);
|
||||
|
||||
void tapTempo(bool b);
|
||||
|
||||
void metronomeEnable(bool b);
|
||||
|
||||
private:
|
||||
std::vector<Controller*> c;
|
||||
/// add a Controller* to Controllers that recieve updates
|
||||
void registerController( Controller* controller );
|
||||
|
||||
/// removes a controller by ID
|
||||
void removeController( int controllerID );
|
||||
|
||||
/// returns a Controller* from ID
|
||||
Controller* getController(int id);
|
||||
|
||||
void reset();
|
||||
void mute(int t, bool b);
|
||||
|
||||
void masterVolume(float v);
|
||||
void masterReturnVolume(float v);
|
||||
void masterInputToActive(int to, bool v);
|
||||
void masterInputTo( int inputTo, float vol );
|
||||
void masterInputVol( float vol );
|
||||
|
||||
void setTrackSceneProgress(int t, int s, float p);
|
||||
void setTrackSendActive(int t, int send, bool v);
|
||||
void setTrackSend(int t, int send, float v);
|
||||
|
||||
void setTrackJackSendActive(int t, bool v);
|
||||
void setTrackJackSend(int t, float v);
|
||||
|
||||
void specialScene(int t, int scene);
|
||||
|
||||
void launchScene( int scene );
|
||||
|
||||
void setSceneState(int t, int clip, GridLogic::State s);
|
||||
|
||||
void recordArm(int t, bool r);
|
||||
|
||||
void volume(int t, float v);
|
||||
|
||||
void tapTempo(bool b);
|
||||
|
||||
void metronomeEnable(bool b);
|
||||
|
||||
private:
|
||||
std::vector<Controller*> c;
|
||||
};
|
||||
|
||||
#endif // LUPPP_CONTROLLER_UPDATER_H
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -24,34 +24,26 @@
|
|||
void luppp_debug( int warnLevel, const char* name, const char* file, const char* func, int line,
|
||||
const char* format, ... )
|
||||
{
|
||||
if ( warnLevel == DEBUG_LEVEL_ERROR )
|
||||
{
|
||||
printf( "[\033[1;31m%s\033[0m] %s:%i: ", name, func, line );
|
||||
}
|
||||
else if ( warnLevel == DEBUG_LEVEL_WARN )
|
||||
{
|
||||
printf( "[\033[1;33m%s\033[0m] %s:%i: ", name, func, line );
|
||||
}
|
||||
else if ( warnLevel == DEBUG_LEVEL_TEST )
|
||||
{
|
||||
if ( warnLevel == DEBUG_LEVEL_ERROR ) {
|
||||
printf( "[\033[1;31m%s\033[0m] %s:%i: ", name, func, line );
|
||||
} else if ( warnLevel == DEBUG_LEVEL_WARN ) {
|
||||
printf( "[\033[1;33m%s\033[0m] %s:%i: ", name, func, line );
|
||||
} else if ( warnLevel == DEBUG_LEVEL_TEST ) {
|
||||
#ifdef BUILD_TESTS
|
||||
printf( "[\033[1;33m%s\033[0m] %s:%i: ", name, func, line );
|
||||
printf( "[\033[1;33m%s\033[0m] %s:%i: ", name, func, line );
|
||||
#endif
|
||||
}
|
||||
else // NOTE
|
||||
{
|
||||
printf( "[\033[1;32m%s\033[0m] %s:%i: ", name, func, line );
|
||||
}
|
||||
printf( "\033[0m" );
|
||||
|
||||
if ( format )
|
||||
{
|
||||
va_list args;
|
||||
va_start( args, format );
|
||||
vfprintf( stdout, format, args );
|
||||
va_end( args );
|
||||
}
|
||||
printf( "\n" );
|
||||
|
||||
} else { // NOTE
|
||||
printf( "[\033[1;32m%s\033[0m] %s:%i: ", name, func, line );
|
||||
}
|
||||
printf( "\033[0m" );
|
||||
|
||||
if ( format ) {
|
||||
va_list args;
|
||||
va_start( args, format );
|
||||
vfprintf( stdout, format, args );
|
||||
va_end( args );
|
||||
}
|
||||
printf( "\n" );
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -29,10 +29,10 @@ LUPPP_KILL( "%s", "MessageHere" );
|
|||
*/
|
||||
|
||||
enum DEBUG_LEVEL {
|
||||
DEBUG_LEVEL_NOTE = 0,
|
||||
DEBUG_LEVEL_WARN,
|
||||
DEBUG_LEVEL_ERROR,
|
||||
DEBUG_LEVEL_TEST
|
||||
DEBUG_LEVEL_NOTE = 0,
|
||||
DEBUG_LEVEL_WARN,
|
||||
DEBUG_LEVEL_ERROR,
|
||||
DEBUG_LEVEL_TEST
|
||||
};
|
||||
|
||||
void luppp_debug( int warnLevel, const char* name, const char* file, const char* func, int line,
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -29,23 +29,23 @@
|
|||
#include <pmmintrin.h>
|
||||
inline void AVOIDDENORMALS()
|
||||
{
|
||||
//LUPPP_NOTE("Denormals: FZ DAZ using SSE3");
|
||||
_MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);
|
||||
_MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON);
|
||||
//LUPPP_NOTE("Denormals: FZ DAZ using SSE3");
|
||||
_MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);
|
||||
_MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON);
|
||||
}
|
||||
#else
|
||||
#include <xmmintrin.h>
|
||||
inline void AVOIDDENORMALS()
|
||||
{
|
||||
//LUPPP_NOTE("Denormals: FZ");
|
||||
_MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);
|
||||
//LUPPP_NOTE("Denormals: FZ");
|
||||
_MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);
|
||||
}
|
||||
#endif //__SSE3__
|
||||
|
||||
#else
|
||||
inline void AVOIDDENORMALS()
|
||||
{
|
||||
LUPPP_NOTE( "Denormals: Warning! No protection" );
|
||||
LUPPP_NOTE( "Denormals: Warning! No protection" );
|
||||
}
|
||||
#endif //__SSE__
|
||||
|
||||
|
|
1149
src/diskreader.cxx
1149
src/diskreader.cxx
File diff suppressed because it is too large
Load diff
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -28,51 +28,51 @@ class AudioBuffer;
|
|||
/** DiskReader
|
||||
* This class reads a previously saved session from disk, restoring Luppp's
|
||||
* internal state to that of when the save took place.
|
||||
*
|
||||
* The directory <sessionDir> is the main point of loading. The user selects
|
||||
*
|
||||
* The directory <sessionDir> is the main point of loading. The user selects
|
||||
* that directory to load the session from. <sessionDir>.luppp is the name of
|
||||
* the session file: it contains all info about the session: Volumes, loaded
|
||||
* samples etc.
|
||||
*
|
||||
*
|
||||
* Samples are read from the directory <sessionDir>/samples, in which there is a
|
||||
* sample.cfg file, which can be parsed to get sample metadata.
|
||||
**/
|
||||
class DiskReader
|
||||
{
|
||||
public:
|
||||
DiskReader();
|
||||
|
||||
/// loads default settings for Luppp: controller instances etc
|
||||
int loadPreferences();
|
||||
|
||||
/// loads a sample into a new AudioBuffer, returning the buffer
|
||||
int loadSample( int track, int scene, std::string path );
|
||||
std::string getLastLoadedSamplePath();
|
||||
|
||||
/// reads a session from disk, parsing and restoring state
|
||||
int readSession( std::string path );
|
||||
|
||||
public:
|
||||
DiskReader();
|
||||
|
||||
/// loads default settings for Luppp: controller instances etc
|
||||
int loadPreferences();
|
||||
|
||||
/// loads a sample into a new AudioBuffer, returning the buffer
|
||||
int loadSample( int track, int scene, std::string path );
|
||||
std::string getLastLoadedSamplePath();
|
||||
|
||||
/// reads a session from disk, parsing and restoring state
|
||||
int readSession( std::string path );
|
||||
|
||||
#ifdef BUILD_TESTS
|
||||
int runTests();
|
||||
int runTests();
|
||||
#endif
|
||||
|
||||
private:
|
||||
cJSON* sessionJson;
|
||||
|
||||
std::string sessionName;
|
||||
std::string sessionPath;
|
||||
|
||||
// convinience functions
|
||||
int readTracks();
|
||||
int readMaster();
|
||||
int readScenes(int t, cJSON* track);
|
||||
|
||||
// ui show editor
|
||||
int showAudioEditor(AudioBuffer* );
|
||||
|
||||
// sample load dialog
|
||||
int resampleQuality;
|
||||
std::string lastLoadedSamplePath;
|
||||
|
||||
private:
|
||||
cJSON* sessionJson;
|
||||
|
||||
std::string sessionName;
|
||||
std::string sessionPath;
|
||||
|
||||
// convinience functions
|
||||
int readTracks();
|
||||
int readMaster();
|
||||
int readScenes(int t, cJSON* track);
|
||||
|
||||
// ui show editor
|
||||
int showAudioEditor(AudioBuffer* );
|
||||
|
||||
// sample load dialog
|
||||
int resampleQuality;
|
||||
std::string lastLoadedSamplePath;
|
||||
};
|
||||
|
||||
#endif // LUPPP_DISK_READER_H
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -43,498 +43,451 @@ using namespace std;
|
|||
|
||||
DiskWriter::DiskWriter()
|
||||
{
|
||||
sessionJson = cJSON_CreateObject();
|
||||
audioJson = cJSON_CreateObject();
|
||||
|
||||
// setup default controller name / author etc
|
||||
controllerInfo[CONTROLLER_NAME] = "no name";
|
||||
controllerInfo[CONTROLLER_AUTHOR] = "no author";
|
||||
controllerInfo[CONTROLLER_LINK] = "no link";
|
||||
|
||||
sessionDir = getenv("HOME");
|
||||
sessionName = "session";
|
||||
foldersCreated = false;
|
||||
|
||||
// create .config/openAV/luppp/ directory
|
||||
stringstream dotConfig;
|
||||
dotConfig << getenv("HOME") << "/.config/openAV/";
|
||||
int dotConfigDir = mkdir( dotConfig.str().c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH );
|
||||
if ( errno == EEXIST )
|
||||
{
|
||||
//LUPPP_NOTE("dotConfigDir exists");
|
||||
}
|
||||
else if ( dotConfigDir )
|
||||
{
|
||||
LUPPP_WARN("Error creating dotConfigDir: %s", strerror(errno));
|
||||
}
|
||||
else
|
||||
{
|
||||
LUPPP_NOTE("Creating .config/openAV/ directory");
|
||||
}
|
||||
|
||||
stringstream dotConfigLuppp;
|
||||
dotConfigLuppp << getenv("HOME") << "/.config/openAV/luppp";
|
||||
int dotConfigLupppDir = mkdir( dotConfigLuppp.str().c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH );
|
||||
if ( errno == EEXIST )
|
||||
{
|
||||
//LUPPP_NOTE("dotConfigLupppDir exists");
|
||||
}
|
||||
else if ( dotConfigLupppDir )
|
||||
{
|
||||
LUPPP_WARN("Error creating dotConfigLupppDir: %s", strerror(errno));
|
||||
}
|
||||
else
|
||||
{
|
||||
LUPPP_NOTE("Creating .config/openAV/luppp directory");
|
||||
}
|
||||
|
||||
stringstream dotConfigCtlr;
|
||||
dotConfigCtlr << getenv("HOME") << "/.config/openAV/luppp/controllers/";
|
||||
int dotConfigCtlrDir = mkdir( dotConfigCtlr.str().c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH );
|
||||
if ( errno == EEXIST )
|
||||
{
|
||||
//LUPPP_NOTE("dotConfigCtlrDir exists");
|
||||
}
|
||||
else if ( dotConfigCtlrDir )
|
||||
{
|
||||
LUPPP_WARN("Error creating dotConfigCtlrDir: %s", strerror(errno));
|
||||
}
|
||||
else
|
||||
{
|
||||
LUPPP_NOTE("Creating .config/openAV/luppp directory");
|
||||
}
|
||||
sessionJson = cJSON_CreateObject();
|
||||
audioJson = cJSON_CreateObject();
|
||||
|
||||
// setup default controller name / author etc
|
||||
controllerInfo[CONTROLLER_NAME] = "no name";
|
||||
controllerInfo[CONTROLLER_AUTHOR] = "no author";
|
||||
controllerInfo[CONTROLLER_LINK] = "no link";
|
||||
|
||||
sessionDir = getenv("HOME");
|
||||
sessionName = "session";
|
||||
foldersCreated = false;
|
||||
|
||||
// create .config/openAV/luppp/ directory
|
||||
stringstream dotConfig;
|
||||
dotConfig << getenv("HOME") << "/.config/openAV/";
|
||||
int dotConfigDir = mkdir( dotConfig.str().c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH );
|
||||
if ( errno == EEXIST ) {
|
||||
//LUPPP_NOTE("dotConfigDir exists");
|
||||
} else if ( dotConfigDir ) {
|
||||
LUPPP_WARN("Error creating dotConfigDir: %s", strerror(errno));
|
||||
} else {
|
||||
LUPPP_NOTE("Creating .config/openAV/ directory");
|
||||
}
|
||||
|
||||
stringstream dotConfigLuppp;
|
||||
dotConfigLuppp << getenv("HOME") << "/.config/openAV/luppp";
|
||||
int dotConfigLupppDir = mkdir( dotConfigLuppp.str().c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH );
|
||||
if ( errno == EEXIST ) {
|
||||
//LUPPP_NOTE("dotConfigLupppDir exists");
|
||||
} else if ( dotConfigLupppDir ) {
|
||||
LUPPP_WARN("Error creating dotConfigLupppDir: %s", strerror(errno));
|
||||
} else {
|
||||
LUPPP_NOTE("Creating .config/openAV/luppp directory");
|
||||
}
|
||||
|
||||
stringstream dotConfigCtlr;
|
||||
dotConfigCtlr << getenv("HOME") << "/.config/openAV/luppp/controllers/";
|
||||
int dotConfigCtlrDir = mkdir( dotConfigCtlr.str().c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH );
|
||||
if ( errno == EEXIST ) {
|
||||
//LUPPP_NOTE("dotConfigCtlrDir exists");
|
||||
} else if ( dotConfigCtlrDir ) {
|
||||
LUPPP_WARN("Error creating dotConfigCtlrDir: %s", strerror(errno));
|
||||
} else {
|
||||
LUPPP_NOTE("Creating .config/openAV/luppp directory");
|
||||
}
|
||||
};
|
||||
|
||||
void DiskWriter::initialize(std::string path, std::string name )
|
||||
{
|
||||
sessionName = name;
|
||||
sessionPath = path;
|
||||
|
||||
// write session.luppp JSON node to <path>/<sessionName>.luppp
|
||||
stringstream sessionDirStream;
|
||||
|
||||
sessionDirStream << path;
|
||||
|
||||
if ( !gui->getNsm() )
|
||||
sessionDirStream << "/" << sessionName << ".luppp";
|
||||
|
||||
sessionDir = sessionDirStream.str();
|
||||
|
||||
LUPPP_NOTE( "Creating session dir %s", sessionDir.c_str() );
|
||||
|
||||
int sessionDirError = mkdir( sessionDir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH );
|
||||
if ( sessionDirError )
|
||||
{
|
||||
// handle by using different filename?
|
||||
LUPPP_WARN("Error creating session directory. Does the path: %s exist?",path.c_str());
|
||||
}
|
||||
|
||||
stringstream audioDirStream;
|
||||
audioDirStream << sessionDir << "/audio";
|
||||
audioDir = audioDirStream.str();
|
||||
LUPPP_NOTE("Creating audio dir %s", audioDir.c_str() );
|
||||
|
||||
int audioDirError = mkdir( audioDir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH );
|
||||
if ( audioDirError )
|
||||
{
|
||||
LUPPP_WARN("Error creating sample directory");
|
||||
}
|
||||
|
||||
foldersCreated = true;
|
||||
sessionName = name;
|
||||
sessionPath = path;
|
||||
|
||||
// write session.luppp JSON node to <path>/<sessionName>.luppp
|
||||
stringstream sessionDirStream;
|
||||
|
||||
sessionDirStream << path;
|
||||
|
||||
if ( !gui->getNsm() )
|
||||
sessionDirStream << "/" << sessionName << ".luppp";
|
||||
|
||||
sessionDir = sessionDirStream.str();
|
||||
|
||||
LUPPP_NOTE( "Creating session dir %s", sessionDir.c_str() );
|
||||
|
||||
int sessionDirError = mkdir( sessionDir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH );
|
||||
if ( sessionDirError ) {
|
||||
// handle by using different filename?
|
||||
LUPPP_WARN("Error creating session directory. Does the path: %s exist?",path.c_str());
|
||||
}
|
||||
|
||||
stringstream audioDirStream;
|
||||
audioDirStream << sessionDir << "/audio";
|
||||
audioDir = audioDirStream.str();
|
||||
LUPPP_NOTE("Creating audio dir %s", audioDir.c_str() );
|
||||
|
||||
int audioDirError = mkdir( audioDir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH );
|
||||
if ( audioDirError ) {
|
||||
LUPPP_WARN("Error creating sample directory");
|
||||
}
|
||||
|
||||
foldersCreated = true;
|
||||
}
|
||||
|
||||
std::string DiskWriter::getLastSaveName()
|
||||
{
|
||||
return sessionName;
|
||||
return sessionName;
|
||||
}
|
||||
|
||||
std::string DiskWriter::getLastSavePath()
|
||||
{
|
||||
return sessionPath;
|
||||
return sessionPath;
|
||||
}
|
||||
|
||||
void DiskWriter::writeControllerInfo( CONTROLLER_INFO c, std::string s )
|
||||
{
|
||||
controllerInfo[c] = s;
|
||||
controllerInfo[c] = s;
|
||||
}
|
||||
|
||||
int DiskWriter::writeControllerFile( Controller* c )
|
||||
{
|
||||
if ( c )
|
||||
{
|
||||
LUPPP_NOTE("DiskWriter Controller* id: %i", c->getID() );
|
||||
}
|
||||
else
|
||||
{
|
||||
LUPPP_ERROR("DiskWriter Controller* passed NULL" );
|
||||
return LUPPP_RETURN_ERROR;
|
||||
}
|
||||
|
||||
// check if controller of ID is actually a GenericMIDI controller
|
||||
GenericMIDI* g = dynamic_cast<GenericMIDI*>( c );
|
||||
|
||||
if ( g )
|
||||
{
|
||||
LUPPP_NOTE("Creating JSON for .ctlr file...");
|
||||
|
||||
cJSON* controllerJson = cJSON_CreateObject();
|
||||
|
||||
cJSON_AddItemToObject( controllerJson, "name",
|
||||
cJSON_CreateString( controllerInfo[CONTROLLER_NAME].c_str() ) );
|
||||
cJSON_AddItemToObject( controllerJson, "author",
|
||||
cJSON_CreateString( controllerInfo[CONTROLLER_AUTHOR].c_str() ) );
|
||||
cJSON_AddItemToObject( controllerJson, "link",
|
||||
cJSON_CreateString( controllerInfo[CONTROLLER_LINK].c_str() ) );
|
||||
|
||||
// input bindings
|
||||
std::vector<Binding*> b = g->getMidiToAction();
|
||||
|
||||
cJSON* inputBindings = cJSON_CreateArray();
|
||||
cJSON_AddItemToObject(controllerJson, "inputBindings", inputBindings );
|
||||
for(unsigned int i = 0; i < b.size(); i++ )
|
||||
{
|
||||
// create binding
|
||||
cJSON* binding = cJSON_CreateObject();
|
||||
cJSON_AddItemToArray( inputBindings, binding );
|
||||
|
||||
// add metadata to binding
|
||||
const char* actionName = Event::getPrettyName( b.at(i)->action );
|
||||
|
||||
if ( actionName )
|
||||
{
|
||||
cJSON_AddItemToObject( binding, "action", cJSON_CreateString( actionName ) );
|
||||
|
||||
cJSON_AddNumberToObject( binding, "status", b.at(i)->status );
|
||||
cJSON_AddNumberToObject( binding, "data" , b.at(i)->data );
|
||||
|
||||
// only add JSON elements if they're not the "invalid" defaults
|
||||
if ( b.at(i)->track != -2 )
|
||||
cJSON_AddNumberToObject( binding, "track" , b.at(i)->track );
|
||||
if ( b.at(i)->scene != -1 )
|
||||
cJSON_AddNumberToObject( binding, "scene" , b.at(i)->scene );
|
||||
if ( b.at(i)->send != -1 )
|
||||
cJSON_AddNumberToObject( binding, "send" , b.at(i)->send );
|
||||
if ( b.at(i)->active!= -1 )
|
||||
cJSON_AddNumberToObject( binding, "active", b.at(i)->active );
|
||||
|
||||
LUPPP_NOTE("Creating Binding: action %i == %s!", b.at(i)->action, actionName );
|
||||
}
|
||||
else
|
||||
{
|
||||
LUPPP_WARN("Binding action %i has no prettyName!", b.at(i)->action );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//std::vector<Binding*> b = g->getMidiToAction();
|
||||
/*
|
||||
cJSON* outputBindings = cJSON_CreateArray();
|
||||
cJSON_AddItemToObject(controllerJson, "outputBindings", outputBindings );
|
||||
|
||||
for(unsigned int i = 0; i < b.size(); i++ )
|
||||
{
|
||||
// create binding
|
||||
cJSON* binding = cJSON_CreateObject();
|
||||
cJSON_AddItemToArray( outputBindings, binding );
|
||||
|
||||
// add metadata to binding
|
||||
// FIXME: get action string from Event class: need to move function from GenericMIDI to there
|
||||
cJSON_AddItemToObject( binding, "action", cJSON_CreateString( "gridlogic:launchscene" ) );
|
||||
|
||||
cJSON_AddNumberToObject( binding, "status", b.at(i)->status );
|
||||
cJSON_AddNumberToObject( binding, "data" , b.at(i)->data );
|
||||
|
||||
cJSON_AddNumberToObject( binding, "track" , b.at(i)->track );
|
||||
cJSON_AddNumberToObject( binding, "scene" , b.at(i)->scene );
|
||||
cJSON_AddNumberToObject( binding, "send" , b.at(i)->send );
|
||||
cJSON_AddNumberToObject( binding, "active", b.at(i)->active );
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
// write the sample JSON node to <samplePath>/sample.cfg
|
||||
stringstream controllerCfgPath;
|
||||
controllerCfgPath << getenv("HOME") << "/.config/openAV/luppp/controllers/" << g->getName() << ".ctlr";
|
||||
|
||||
ifstream infile( controllerCfgPath.str().c_str() );
|
||||
if ( infile.good() )
|
||||
{
|
||||
// file exists: ask user overwrite or rename?
|
||||
//LUPPP_WARN("Controller filename exists: prompting user to overwrite y/n?");
|
||||
int action = fl_choice("Controller exists, action?", "Cancel", "Rename", "Overwrite");
|
||||
if ( action == 0 )
|
||||
{
|
||||
// return OK, as user has chosen to cancel writing the file
|
||||
return LUPPP_RETURN_OK;
|
||||
}
|
||||
else if ( action == 1 )
|
||||
{
|
||||
// rename here
|
||||
const char* name = fl_input("New name for .ctlr file:");
|
||||
if ( name )
|
||||
{
|
||||
// clear the filename
|
||||
controllerCfgPath.str( "" );
|
||||
controllerCfgPath << getenv("HOME") << "/.config/openAV/luppp/controllers/" << name << ".ctlr";
|
||||
LUPPP_NOTE( "New .ctlr filename %s", controllerCfgPath.str().c_str() );
|
||||
}
|
||||
else
|
||||
{
|
||||
LUPPP_NOTE("No name entered for .ctlr file, canceling!");
|
||||
return LUPPP_RETURN_ERROR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// just overwrite the file, no action
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
LUPPP_NOTE("Writing %s.ctlr file to disk", g->getName().c_str() );
|
||||
|
||||
ofstream controllerCfgFile;
|
||||
controllerCfgFile.open ( controllerCfgPath.str().c_str() );
|
||||
controllerCfgFile << cJSON_Print( controllerJson );
|
||||
controllerCfgFile.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
LUPPP_WARN("Invalid Controller pointer: cannot write %s as is not a GenericMIDI controller!", c->getName().c_str() );
|
||||
return LUPPP_RETURN_ERROR;
|
||||
}
|
||||
|
||||
return LUPPP_RETURN_OK;
|
||||
if ( c ) {
|
||||
LUPPP_NOTE("DiskWriter Controller* id: %i", c->getID() );
|
||||
} else {
|
||||
LUPPP_ERROR("DiskWriter Controller* passed NULL" );
|
||||
return LUPPP_RETURN_ERROR;
|
||||
}
|
||||
|
||||
// check if controller of ID is actually a GenericMIDI controller
|
||||
GenericMIDI* g = dynamic_cast<GenericMIDI*>( c );
|
||||
|
||||
if ( g ) {
|
||||
LUPPP_NOTE("Creating JSON for .ctlr file...");
|
||||
|
||||
cJSON* controllerJson = cJSON_CreateObject();
|
||||
|
||||
cJSON_AddItemToObject( controllerJson, "name",
|
||||
cJSON_CreateString( controllerInfo[CONTROLLER_NAME].c_str() ) );
|
||||
cJSON_AddItemToObject( controllerJson, "author",
|
||||
cJSON_CreateString( controllerInfo[CONTROLLER_AUTHOR].c_str() ) );
|
||||
cJSON_AddItemToObject( controllerJson, "link",
|
||||
cJSON_CreateString( controllerInfo[CONTROLLER_LINK].c_str() ) );
|
||||
|
||||
// input bindings
|
||||
std::vector<Binding*> b = g->getMidiToAction();
|
||||
|
||||
cJSON* inputBindings = cJSON_CreateArray();
|
||||
cJSON_AddItemToObject(controllerJson, "inputBindings", inputBindings );
|
||||
for(unsigned int i = 0; i < b.size(); i++ ) {
|
||||
// create binding
|
||||
cJSON* binding = cJSON_CreateObject();
|
||||
cJSON_AddItemToArray( inputBindings, binding );
|
||||
|
||||
// add metadata to binding
|
||||
const char* actionName = Event::getPrettyName( b.at(i)->action );
|
||||
|
||||
if ( actionName ) {
|
||||
cJSON_AddItemToObject( binding, "action", cJSON_CreateString( actionName ) );
|
||||
|
||||
cJSON_AddNumberToObject( binding, "status", b.at(i)->status );
|
||||
cJSON_AddNumberToObject( binding, "data" , b.at(i)->data );
|
||||
|
||||
// only add JSON elements if they're not the "invalid" defaults
|
||||
if ( b.at(i)->track != -2 )
|
||||
cJSON_AddNumberToObject( binding, "track" , b.at(i)->track );
|
||||
if ( b.at(i)->scene != -1 )
|
||||
cJSON_AddNumberToObject( binding, "scene" , b.at(i)->scene );
|
||||
if ( b.at(i)->send != -1 )
|
||||
cJSON_AddNumberToObject( binding, "send" , b.at(i)->send );
|
||||
if ( b.at(i)->active!= -1 )
|
||||
cJSON_AddNumberToObject( binding, "active", b.at(i)->active );
|
||||
|
||||
LUPPP_NOTE("Creating Binding: action %i == %s!", b.at(i)->action, actionName );
|
||||
} else {
|
||||
LUPPP_WARN("Binding action %i has no prettyName!", b.at(i)->action );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//std::vector<Binding*> b = g->getMidiToAction();
|
||||
/*
|
||||
cJSON* outputBindings = cJSON_CreateArray();
|
||||
cJSON_AddItemToObject(controllerJson, "outputBindings", outputBindings );
|
||||
|
||||
for(unsigned int i = 0; i < b.size(); i++ )
|
||||
{
|
||||
// create binding
|
||||
cJSON* binding = cJSON_CreateObject();
|
||||
cJSON_AddItemToArray( outputBindings, binding );
|
||||
|
||||
// add metadata to binding
|
||||
// FIXME: get action string from Event class: need to move function from GenericMIDI to there
|
||||
cJSON_AddItemToObject( binding, "action", cJSON_CreateString( "gridlogic:launchscene" ) );
|
||||
|
||||
cJSON_AddNumberToObject( binding, "status", b.at(i)->status );
|
||||
cJSON_AddNumberToObject( binding, "data" , b.at(i)->data );
|
||||
|
||||
cJSON_AddNumberToObject( binding, "track" , b.at(i)->track );
|
||||
cJSON_AddNumberToObject( binding, "scene" , b.at(i)->scene );
|
||||
cJSON_AddNumberToObject( binding, "send" , b.at(i)->send );
|
||||
cJSON_AddNumberToObject( binding, "active", b.at(i)->active );
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
// write the sample JSON node to <samplePath>/sample.cfg
|
||||
stringstream controllerCfgPath;
|
||||
controllerCfgPath << getenv("HOME") << "/.config/openAV/luppp/controllers/" << g->getName() << ".ctlr";
|
||||
|
||||
ifstream infile( controllerCfgPath.str().c_str() );
|
||||
if ( infile.good() ) {
|
||||
// file exists: ask user overwrite or rename?
|
||||
//LUPPP_WARN("Controller filename exists: prompting user to overwrite y/n?");
|
||||
int action = fl_choice("Controller exists, action?", "Cancel", "Rename", "Overwrite");
|
||||
if ( action == 0 ) {
|
||||
// return OK, as user has chosen to cancel writing the file
|
||||
return LUPPP_RETURN_OK;
|
||||
} else if ( action == 1 ) {
|
||||
// rename here
|
||||
const char* name = fl_input("New name for .ctlr file:");
|
||||
if ( name ) {
|
||||
// clear the filename
|
||||
controllerCfgPath.str( "" );
|
||||
controllerCfgPath << getenv("HOME") << "/.config/openAV/luppp/controllers/" << name << ".ctlr";
|
||||
LUPPP_NOTE( "New .ctlr filename %s", controllerCfgPath.str().c_str() );
|
||||
} else {
|
||||
LUPPP_NOTE("No name entered for .ctlr file, canceling!");
|
||||
return LUPPP_RETURN_ERROR;
|
||||
}
|
||||
} else {
|
||||
// just overwrite the file, no action
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
LUPPP_NOTE("Writing %s.ctlr file to disk", g->getName().c_str() );
|
||||
|
||||
ofstream controllerCfgFile;
|
||||
controllerCfgFile.open ( controllerCfgPath.str().c_str() );
|
||||
controllerCfgFile << cJSON_Print( controllerJson );
|
||||
controllerCfgFile.close();
|
||||
} else {
|
||||
LUPPP_WARN("Invalid Controller pointer: cannot write %s as is not a GenericMIDI controller!", c->getName().c_str() );
|
||||
return LUPPP_RETURN_ERROR;
|
||||
}
|
||||
|
||||
return LUPPP_RETURN_OK;
|
||||
}
|
||||
|
||||
int DiskWriter::writeAudioBuffer(int track, int scene, AudioBuffer* ab,
|
||||
const char *gui_path)
|
||||
const char *gui_path)
|
||||
{
|
||||
stringstream path;
|
||||
if ( gui_path && strlen(gui_path) ) {
|
||||
printf("saving single buffer to %s\n", gui_path);
|
||||
path << gui_path;
|
||||
}
|
||||
else if ( foldersCreated )
|
||||
{
|
||||
stringstream filename;
|
||||
filename << "t_" << track << "_s_" << scene << ".wav";
|
||||
|
||||
// store the clip in clipData, we will write the session JSON for it in writeSession
|
||||
clipData.push_back( ClipData( track, scene, filename.str() ) );
|
||||
|
||||
// add the AudioBuffer metadata to the sample JSON node
|
||||
cJSON* sampleClip = cJSON_CreateObject();
|
||||
cJSON_AddItemToObject(audioJson, filename.str().c_str(), sampleClip );
|
||||
cJSON_AddNumberToObject(sampleClip,"beats", ab->getBeats() );
|
||||
|
||||
// get pretty name from GUI
|
||||
std::string clipName = gui->getTrack(track)->getClipSelector()->clipName( scene );
|
||||
cJSON_AddItemToObject ( sampleClip, "name", cJSON_CreateString( clipName.c_str() ));
|
||||
|
||||
// write the AudioBuffer contents to <path>/audio/ as <name>.wav
|
||||
// or alternatively t_<track>_s_<scene>.wav
|
||||
|
||||
path << audioDir << "/" << filename.str();
|
||||
}
|
||||
else
|
||||
{
|
||||
LUPPP_WARN("%s", "Session folders not created yet, while trying to write audioBuffers.");
|
||||
return LUPPP_RETURN_ERROR;
|
||||
}
|
||||
|
||||
|
||||
SndfileHandle outfile( path.str(), SFM_WRITE, SF_FORMAT_WAV | SF_FORMAT_FLOAT, 1, gui->samplerate );
|
||||
|
||||
// FIXME: the size of the buffer is bigger than the audio contained in it:
|
||||
// calculate the length that needs saving using getBeats() * framesPerBeat
|
||||
if ( ab->getAudioFrames() > 0 )
|
||||
outfile.write( &ab->getData()[0], ab->getAudioFrames() );
|
||||
else
|
||||
{
|
||||
LUPPP_WARN("%s","Sample has zero samples");
|
||||
}
|
||||
|
||||
return LUPPP_RETURN_OK;
|
||||
stringstream path;
|
||||
if ( gui_path && strlen(gui_path) ) {
|
||||
printf("saving single buffer to %s\n", gui_path);
|
||||
path << gui_path;
|
||||
} else if ( foldersCreated ) {
|
||||
stringstream filename;
|
||||
filename << "t_" << track << "_s_" << scene << ".wav";
|
||||
|
||||
// store the clip in clipData, we will write the session JSON for it in writeSession
|
||||
clipData.push_back( ClipData( track, scene, filename.str() ) );
|
||||
|
||||
// add the AudioBuffer metadata to the sample JSON node
|
||||
cJSON* sampleClip = cJSON_CreateObject();
|
||||
cJSON_AddItemToObject(audioJson, filename.str().c_str(), sampleClip );
|
||||
cJSON_AddNumberToObject(sampleClip,"beats", ab->getBeats() );
|
||||
|
||||
// get pretty name from GUI
|
||||
std::string clipName = gui->getTrack(track)->getClipSelector()->clipName( scene );
|
||||
cJSON_AddItemToObject ( sampleClip, "name", cJSON_CreateString( clipName.c_str() ));
|
||||
|
||||
// write the AudioBuffer contents to <path>/audio/ as <name>.wav
|
||||
// or alternatively t_<track>_s_<scene>.wav
|
||||
|
||||
path << audioDir << "/" << filename.str();
|
||||
} else {
|
||||
LUPPP_WARN("%s", "Session folders not created yet, while trying to write audioBuffers.");
|
||||
return LUPPP_RETURN_ERROR;
|
||||
}
|
||||
|
||||
|
||||
SndfileHandle outfile( path.str(), SFM_WRITE, SF_FORMAT_WAV | SF_FORMAT_FLOAT, 1, gui->samplerate );
|
||||
|
||||
// FIXME: the size of the buffer is bigger than the audio contained in it:
|
||||
// calculate the length that needs saving using getBeats() * framesPerBeat
|
||||
if ( ab->getAudioFrames() > 0 )
|
||||
outfile.write( &ab->getData()[0], ab->getAudioFrames() );
|
||||
else {
|
||||
LUPPP_WARN("%s","Sample has zero samples");
|
||||
}
|
||||
|
||||
return LUPPP_RETURN_OK;
|
||||
}
|
||||
|
||||
void DiskWriter::writeMaster()
|
||||
{
|
||||
// Master track stuff
|
||||
cJSON* masterTrack = cJSON_CreateObject();
|
||||
cJSON_AddItemToObject(sessionJson, "master", masterTrack );
|
||||
GMasterTrack* master = gui->getMasterTrack();
|
||||
|
||||
cJSON_AddNumberToObject( masterTrack, "fader", master->getVolume()->value() );
|
||||
cJSON_AddNumberToObject( masterTrack, "bpm", gui->getMasterTrack()->getBpm() );
|
||||
// TODO add samplerate to session JSON
|
||||
//cJSON_AddNumberToObject( masterTrack, "samplerate", gui->getMasterTrack()->getBpm() );
|
||||
|
||||
cJSON_AddNumberToObject( masterTrack, "inputVolume", gui->getMasterTrack()->getInputVolume()->value() );
|
||||
|
||||
cJSON_AddNumberToObject( masterTrack, "inputToSndActive", gui->getMasterTrack()->getInputToSend()->value() );
|
||||
cJSON_AddNumberToObject( masterTrack, "inputToKeyActive", gui->getMasterTrack()->getInputToSidechainKey()->value() );
|
||||
cJSON_AddNumberToObject( masterTrack, "inputToMixActive", gui->getMasterTrack()->getInputToMix()->value() );
|
||||
|
||||
cJSON_AddNumberToObject( masterTrack, "inputToSndVol", gui->getMasterTrack()->getInputToSendVol()->value() );
|
||||
cJSON_AddNumberToObject( masterTrack, "inputToXSide", gui->getMasterTrack()->getInputToXSide()->value() );
|
||||
cJSON_AddNumberToObject( masterTrack, "inputToMixVol", gui->getMasterTrack()->getInputToMixVol()->value() );
|
||||
|
||||
// scene names
|
||||
Avtk::ClipSelector* clipSelector = master->getClipSelector();
|
||||
cJSON* sceneNames = cJSON_CreateArray();
|
||||
cJSON_AddItemToObject( masterTrack, "sceneNames", sceneNames );
|
||||
for(int i = 0; i < NSCENES; i++)
|
||||
{
|
||||
cJSON* sceneName = cJSON_CreateString( clipSelector->clipName(i).c_str() );
|
||||
cJSON_AddItemToArray( sceneNames, sceneName );
|
||||
}
|
||||
|
||||
// Master track stuff
|
||||
cJSON* masterTrack = cJSON_CreateObject();
|
||||
cJSON_AddItemToObject(sessionJson, "master", masterTrack );
|
||||
GMasterTrack* master = gui->getMasterTrack();
|
||||
|
||||
cJSON_AddNumberToObject( masterTrack, "fader", master->getVolume()->value() );
|
||||
cJSON_AddNumberToObject( masterTrack, "bpm", gui->getMasterTrack()->getBpm() );
|
||||
// TODO add samplerate to session JSON
|
||||
//cJSON_AddNumberToObject( masterTrack, "samplerate", gui->getMasterTrack()->getBpm() );
|
||||
|
||||
cJSON_AddNumberToObject( masterTrack, "inputVolume", gui->getMasterTrack()->getInputVolume()->value() );
|
||||
|
||||
cJSON_AddNumberToObject( masterTrack, "inputToSndActive", gui->getMasterTrack()->getInputToSend()->value() );
|
||||
cJSON_AddNumberToObject( masterTrack, "inputToKeyActive", gui->getMasterTrack()->getInputToSidechainKey()->value() );
|
||||
cJSON_AddNumberToObject( masterTrack, "inputToMixActive", gui->getMasterTrack()->getInputToMix()->value() );
|
||||
|
||||
cJSON_AddNumberToObject( masterTrack, "inputToSndVol", gui->getMasterTrack()->getInputToSendVol()->value() );
|
||||
cJSON_AddNumberToObject( masterTrack, "inputToXSide", gui->getMasterTrack()->getInputToXSide()->value() );
|
||||
cJSON_AddNumberToObject( masterTrack, "inputToMixVol", gui->getMasterTrack()->getInputToMixVol()->value() );
|
||||
|
||||
// scene names
|
||||
Avtk::ClipSelector* clipSelector = master->getClipSelector();
|
||||
cJSON* sceneNames = cJSON_CreateArray();
|
||||
cJSON_AddItemToObject( masterTrack, "sceneNames", sceneNames );
|
||||
for(int i = 0; i < NSCENES; i++) {
|
||||
cJSON* sceneName = cJSON_CreateString( clipSelector->clipName(i).c_str() );
|
||||
cJSON_AddItemToArray( sceneNames, sceneName );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int DiskWriter::writeSession()
|
||||
{
|
||||
if ( !foldersCreated )
|
||||
{
|
||||
LUPPP_WARN("%s", "Session folders not created yet, while trying to write session.");
|
||||
return LUPPP_RETURN_ERROR;
|
||||
}
|
||||
|
||||
// add session metadata
|
||||
cJSON_AddItemToObject ( sessionJson, "session", cJSON_CreateString( sessionName.c_str() ));
|
||||
|
||||
cJSON_AddNumberToObject( sessionJson, "version_major", 1 );
|
||||
cJSON_AddNumberToObject( sessionJson, "version_minor", 0 );
|
||||
cJSON_AddNumberToObject( sessionJson, "version_patch", 0 );
|
||||
|
||||
|
||||
writeMaster();
|
||||
|
||||
|
||||
// add JSON "tracks" array
|
||||
cJSON* trackArray = cJSON_CreateArray();
|
||||
cJSON_AddItemToObject(sessionJson, "tracks", trackArray );
|
||||
|
||||
// write tracks into JSON tracks array
|
||||
for(int t = 0; t < NTRACKS; t++)
|
||||
{
|
||||
cJSON* track = cJSON_CreateObject();
|
||||
cJSON_AddItemToArray( trackArray, track );
|
||||
|
||||
// add track metadata: volumes, sends etc
|
||||
cJSON_AddNumberToObject( track, "ID", t );
|
||||
cJSON_AddStringToObject( track, "name", gui->getTrack(t)->bg.getLabel() );
|
||||
|
||||
cJSON_AddNumberToObject( track, "fader", gui->getTrack(t)->getVolume()->value() );
|
||||
|
||||
|
||||
cJSON_AddNumberToObject( track, "sendAmount" , gui->getTrack(t)->getSend() );
|
||||
cJSON_AddNumberToObject( track, "sendActive" , gui->getTrack(t)->getSendActive() );
|
||||
if ( !foldersCreated ) {
|
||||
LUPPP_WARN("%s", "Session folders not created yet, while trying to write session.");
|
||||
return LUPPP_RETURN_ERROR;
|
||||
}
|
||||
|
||||
cJSON_AddNumberToObject( track, "jacksendAmount" , gui->getTrack(t)->getJackSend() );
|
||||
cJSON_AddNumberToObject( track, "jacksendActive" , gui->getTrack(t)->getJackSendActivate() );
|
||||
|
||||
cJSON_AddNumberToObject( track, "xsideAmount", gui->getTrack(t)->getXSide() );
|
||||
cJSON_AddNumberToObject( track, "keyActive" , gui->getTrack(t)->getKeyActive() );
|
||||
|
||||
// write clipData vector into clip placeholder
|
||||
cJSON* clips = cJSON_CreateArray();
|
||||
cJSON_AddItemToObject( track, "clips", clips );
|
||||
|
||||
|
||||
|
||||
for(int s = 0; s < NSCENES; s++)
|
||||
{
|
||||
// add empty string to array
|
||||
cJSON* clip = cJSON_CreateString( "" );
|
||||
cJSON_AddItemToArray( clips, clip );
|
||||
|
||||
// replace blank string if clip exists
|
||||
for(unsigned int i = 0; i < clipData.size(); i++)
|
||||
{
|
||||
if ( clipData.at(i).track == t &&
|
||||
clipData.at(i).scene == s )
|
||||
{
|
||||
cJSON* newClip = cJSON_CreateString( clipData.at(i).name.c_str() );
|
||||
cJSON_ReplaceItemInArray( clips, s, newClip );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
stringstream sessionLuppp;
|
||||
sessionLuppp << sessionDir << "/session.luppp";
|
||||
//c out << "Session dir: " << sessionDir.str() << "\n" << "Sample dir : " << audioDir.str() << endl;
|
||||
ofstream sessionFile;
|
||||
sessionFile.open ( sessionLuppp.str().c_str() );
|
||||
sessionFile << cJSON_Print( sessionJson );
|
||||
sessionFile.close();
|
||||
|
||||
// write the sample JSON node to <samplePath>/sample.cfg
|
||||
stringstream audioCfg;
|
||||
audioCfg << audioDir << "/audio.cfg";
|
||||
|
||||
ofstream audioCfgFile;
|
||||
audioCfgFile.open ( audioCfg.str().c_str() );
|
||||
audioCfgFile << cJSON_Print( audioJson );
|
||||
audioCfgFile.close();
|
||||
|
||||
// clear the clipData, clean page for next save
|
||||
clipData.clear();
|
||||
|
||||
|
||||
// reset the cJSON objects
|
||||
cJSON_Delete( sessionJson );
|
||||
cJSON_Delete( audioJson );
|
||||
|
||||
sessionJson = cJSON_CreateObject();
|
||||
audioJson = cJSON_CreateObject();
|
||||
|
||||
|
||||
return LUPPP_RETURN_OK;
|
||||
// add session metadata
|
||||
cJSON_AddItemToObject ( sessionJson, "session", cJSON_CreateString( sessionName.c_str() ));
|
||||
|
||||
cJSON_AddNumberToObject( sessionJson, "version_major", 1 );
|
||||
cJSON_AddNumberToObject( sessionJson, "version_minor", 0 );
|
||||
cJSON_AddNumberToObject( sessionJson, "version_patch", 0 );
|
||||
|
||||
|
||||
writeMaster();
|
||||
|
||||
|
||||
// add JSON "tracks" array
|
||||
cJSON* trackArray = cJSON_CreateArray();
|
||||
cJSON_AddItemToObject(sessionJson, "tracks", trackArray );
|
||||
|
||||
// write tracks into JSON tracks array
|
||||
for(int t = 0; t < NTRACKS; t++) {
|
||||
cJSON* track = cJSON_CreateObject();
|
||||
cJSON_AddItemToArray( trackArray, track );
|
||||
|
||||
// add track metadata: volumes, sends etc
|
||||
cJSON_AddNumberToObject( track, "ID", t );
|
||||
cJSON_AddStringToObject( track, "name", gui->getTrack(t)->bg.getLabel() );
|
||||
|
||||
cJSON_AddNumberToObject( track, "fader", gui->getTrack(t)->getVolume()->value() );
|
||||
|
||||
|
||||
cJSON_AddNumberToObject( track, "sendAmount" , gui->getTrack(t)->getSend() );
|
||||
cJSON_AddNumberToObject( track, "sendActive" , gui->getTrack(t)->getSendActive() );
|
||||
|
||||
cJSON_AddNumberToObject( track, "jacksendAmount" , gui->getTrack(t)->getJackSend() );
|
||||
cJSON_AddNumberToObject( track, "jacksendActive" , gui->getTrack(t)->getJackSendActivate() );
|
||||
|
||||
cJSON_AddNumberToObject( track, "xsideAmount", gui->getTrack(t)->getXSide() );
|
||||
cJSON_AddNumberToObject( track, "keyActive" , gui->getTrack(t)->getKeyActive() );
|
||||
|
||||
// write clipData vector into clip placeholder
|
||||
cJSON* clips = cJSON_CreateArray();
|
||||
cJSON_AddItemToObject( track, "clips", clips );
|
||||
|
||||
|
||||
|
||||
for(int s = 0; s < NSCENES; s++) {
|
||||
// add empty string to array
|
||||
cJSON* clip = cJSON_CreateString( "" );
|
||||
cJSON_AddItemToArray( clips, clip );
|
||||
|
||||
// replace blank string if clip exists
|
||||
for(unsigned int i = 0; i < clipData.size(); i++) {
|
||||
if ( clipData.at(i).track == t &&
|
||||
clipData.at(i).scene == s ) {
|
||||
cJSON* newClip = cJSON_CreateString( clipData.at(i).name.c_str() );
|
||||
cJSON_ReplaceItemInArray( clips, s, newClip );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
stringstream sessionLuppp;
|
||||
sessionLuppp << sessionDir << "/session.luppp";
|
||||
//c out << "Session dir: " << sessionDir.str() << "\n" << "Sample dir : " << audioDir.str() << endl;
|
||||
ofstream sessionFile;
|
||||
sessionFile.open ( sessionLuppp.str().c_str() );
|
||||
sessionFile << cJSON_Print( sessionJson );
|
||||
sessionFile.close();
|
||||
|
||||
// write the sample JSON node to <samplePath>/sample.cfg
|
||||
stringstream audioCfg;
|
||||
audioCfg << audioDir << "/audio.cfg";
|
||||
|
||||
ofstream audioCfgFile;
|
||||
audioCfgFile.open ( audioCfg.str().c_str() );
|
||||
audioCfgFile << cJSON_Print( audioJson );
|
||||
audioCfgFile.close();
|
||||
|
||||
// clear the clipData, clean page for next save
|
||||
clipData.clear();
|
||||
|
||||
|
||||
// reset the cJSON objects
|
||||
cJSON_Delete( sessionJson );
|
||||
cJSON_Delete( audioJson );
|
||||
|
||||
sessionJson = cJSON_CreateObject();
|
||||
audioJson = cJSON_CreateObject();
|
||||
|
||||
|
||||
return LUPPP_RETURN_OK;
|
||||
}
|
||||
|
||||
|
||||
void DiskWriter::writeDefaultConfigToUserHome()
|
||||
{
|
||||
LUPPP_NOTE("Writing default preferences file.");
|
||||
|
||||
cJSON* prfs = cJSON_CreateObject();
|
||||
|
||||
// "__COMMENT__" : "users home + <whatever it says here>"
|
||||
// "saveDirectory" : "luppp"
|
||||
cJSON_AddItemToObject ( prfs, "__COMMENT__",
|
||||
cJSON_CreateString("users home + <whatever it says here>") );
|
||||
cJSON_AddItemToObject ( prfs, "saveDirectory", cJSON_CreateString( "luppp" ));
|
||||
|
||||
|
||||
// "__COMMENT__" : "0 = LINEAR, 1 = SINC_FASTEST, 2 = SINC_BEST",
|
||||
// "resampleQuality" : 2
|
||||
cJSON_AddItemToObject ( prfs, "__COMMENT__",
|
||||
cJSON_CreateString("0 = LINEAR, 1 = SINC_FASTEST, 2 = SINC_BEST") );
|
||||
cJSON_AddNumberToObject( prfs, "resampleQuality", 1 );
|
||||
|
||||
// "defaultControllers" : [],
|
||||
cJSON* defCtrls = cJSON_CreateArray();
|
||||
cJSON_AddItemToObject( prfs, "defaultControllers", defCtrls );
|
||||
|
||||
// per track send and return option
|
||||
cJSON_AddNumberToObject( prfs, "enablePerTrackSendReturns", 0 );
|
||||
// test output on console
|
||||
// cout << endl << cJSON_Print( prfs ) << endl << endl;
|
||||
|
||||
|
||||
// write JSON to .config/openAV/luppp/luppp.prfs
|
||||
stringstream f;
|
||||
f << getenv("HOME") << "/.config/openAV/luppp/luppp.prfs";
|
||||
|
||||
ofstream outFile;
|
||||
outFile.open ( f.str().c_str() );
|
||||
outFile << cJSON_Print( prfs );
|
||||
outFile.close();
|
||||
LUPPP_NOTE("Writing default preferences file.");
|
||||
|
||||
cJSON* prfs = cJSON_CreateObject();
|
||||
|
||||
// "__COMMENT__" : "users home + <whatever it says here>"
|
||||
// "saveDirectory" : "luppp"
|
||||
cJSON_AddItemToObject ( prfs, "__COMMENT__",
|
||||
cJSON_CreateString("users home + <whatever it says here>") );
|
||||
cJSON_AddItemToObject ( prfs, "saveDirectory", cJSON_CreateString( "luppp" ));
|
||||
|
||||
|
||||
// "__COMMENT__" : "0 = LINEAR, 1 = SINC_FASTEST, 2 = SINC_BEST",
|
||||
// "resampleQuality" : 2
|
||||
cJSON_AddItemToObject ( prfs, "__COMMENT__",
|
||||
cJSON_CreateString("0 = LINEAR, 1 = SINC_FASTEST, 2 = SINC_BEST") );
|
||||
cJSON_AddNumberToObject( prfs, "resampleQuality", 1 );
|
||||
|
||||
// "defaultControllers" : [],
|
||||
cJSON* defCtrls = cJSON_CreateArray();
|
||||
cJSON_AddItemToObject( prfs, "defaultControllers", defCtrls );
|
||||
|
||||
// per track send and return option
|
||||
cJSON_AddNumberToObject( prfs, "enablePerTrackSendReturns", 0 );
|
||||
// test output on console
|
||||
// cout << endl << cJSON_Print( prfs ) << endl << endl;
|
||||
|
||||
|
||||
// write JSON to .config/openAV/luppp/luppp.prfs
|
||||
stringstream f;
|
||||
f << getenv("HOME") << "/.config/openAV/luppp/luppp.prfs";
|
||||
|
||||
ofstream outFile;
|
||||
outFile.open ( f.str().c_str() );
|
||||
outFile << cJSON_Print( prfs );
|
||||
outFile.close();
|
||||
}
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -27,23 +27,22 @@
|
|||
class AudioBuffer;
|
||||
class Controller;
|
||||
|
||||
enum CONTROLLER_INFO
|
||||
{
|
||||
CONTROLLER_NAME,
|
||||
CONTROLLER_AUTHOR,
|
||||
CONTROLLER_LINK,
|
||||
CONTROLLER_INFO_SIZE,
|
||||
enum CONTROLLER_INFO {
|
||||
CONTROLLER_NAME,
|
||||
CONTROLLER_AUTHOR,
|
||||
CONTROLLER_LINK,
|
||||
CONTROLLER_INFO_SIZE,
|
||||
};
|
||||
|
||||
/// To hold data about loaded clips until we write the JSON out
|
||||
class ClipData
|
||||
{
|
||||
public:
|
||||
ClipData(int tr, int sc, std::string na) :
|
||||
track(tr), scene(sc), name(na) {}
|
||||
int track;
|
||||
int scene;
|
||||
std::string name;
|
||||
public:
|
||||
ClipData(int tr, int sc, std::string na) :
|
||||
track(tr), scene(sc), name(na) {}
|
||||
int track;
|
||||
int scene;
|
||||
std::string name;
|
||||
};
|
||||
|
||||
/** DiskWriter
|
||||
|
@ -53,51 +52,51 @@ class ClipData
|
|||
**/
|
||||
class DiskWriter
|
||||
{
|
||||
public:
|
||||
DiskWriter();
|
||||
|
||||
/// sets up session write path etc
|
||||
void initialize( std::string path, std::string sessionName );
|
||||
|
||||
/// writes a single audio buffer to disk for saving whole state.
|
||||
// When gui_path is set, it only saves a single AB* to that path
|
||||
int writeAudioBuffer(int track, int scene, AudioBuffer* ab,
|
||||
const char* gui_path = 0);
|
||||
|
||||
/// flush the JSON to disk, finalizing the save
|
||||
int writeSession();
|
||||
|
||||
std::string getLastSaveName();
|
||||
std::string getLastSavePath();
|
||||
|
||||
/// sets a piece of info to be written to the controller
|
||||
void writeControllerInfo( CONTROLLER_INFO c, std::string s );
|
||||
/// writes a controller definition .ctlr JSON file from a GenericMIDI instance
|
||||
int writeControllerFile( Controller* c );
|
||||
|
||||
/// writes default config file to users home if it doesn't exist
|
||||
void writeDefaultConfigToUserHome();
|
||||
|
||||
public:
|
||||
DiskWriter();
|
||||
|
||||
/// sets up session write path etc
|
||||
void initialize( std::string path, std::string sessionName );
|
||||
|
||||
/// writes a single audio buffer to disk for saving whole state.
|
||||
// When gui_path is set, it only saves a single AB* to that path
|
||||
int writeAudioBuffer(int track, int scene, AudioBuffer* ab,
|
||||
const char* gui_path = 0);
|
||||
|
||||
/// flush the JSON to disk, finalizing the save
|
||||
int writeSession();
|
||||
|
||||
std::string getLastSaveName();
|
||||
std::string getLastSavePath();
|
||||
|
||||
/// sets a piece of info to be written to the controller
|
||||
void writeControllerInfo( CONTROLLER_INFO c, std::string s );
|
||||
/// writes a controller definition .ctlr JSON file from a GenericMIDI instance
|
||||
int writeControllerFile( Controller* c );
|
||||
|
||||
/// writes default config file to users home if it doesn't exist
|
||||
void writeDefaultConfigToUserHome();
|
||||
|
||||
#ifdef BUILD_TESTS
|
||||
int runTests();
|
||||
int runTests();
|
||||
#endif
|
||||
|
||||
private:
|
||||
cJSON* sessionJson;
|
||||
cJSON* audioJson;
|
||||
|
||||
bool foldersCreated;
|
||||
std::string sessionName;
|
||||
std::string sessionPath;
|
||||
std::string audioDir;
|
||||
std::string sessionDir;
|
||||
|
||||
std::vector<ClipData> clipData;
|
||||
|
||||
// convienice functions for code separation
|
||||
void writeMaster();
|
||||
|
||||
std::string controllerInfo[CONTROLLER_INFO_SIZE];
|
||||
|
||||
private:
|
||||
cJSON* sessionJson;
|
||||
cJSON* audioJson;
|
||||
|
||||
bool foldersCreated;
|
||||
std::string sessionName;
|
||||
std::string sessionPath;
|
||||
std::string audioDir;
|
||||
std::string sessionDir;
|
||||
|
||||
std::vector<ClipData> clipData;
|
||||
|
||||
// convienice functions for code separation
|
||||
void writeMaster();
|
||||
|
||||
std::string controllerInfo[CONTROLLER_INFO_SIZE];
|
||||
};
|
||||
|
||||
#endif // LUPPP_DISK_WRITER_H
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -26,63 +26,68 @@
|
|||
|
||||
class DBMeter
|
||||
{
|
||||
public:
|
||||
DBMeter(int rate)
|
||||
{
|
||||
fSamplingFreq = rate;
|
||||
fConst0 = (96.f / float(min(192000, max(1, fSamplingFreq))));
|
||||
|
||||
fRec0[0] = -96.f;
|
||||
fRec0[1] = -96.f;
|
||||
fRec1[0] = -96.f;
|
||||
fRec1[1] = -96.f;
|
||||
|
||||
fvbargraph0 = -96.f;
|
||||
fvbargraph1 = -96.f;
|
||||
}
|
||||
|
||||
int getNumInputs() { return 2;}
|
||||
int getNumOutputs(){ return 2;}
|
||||
|
||||
// call these to get the current dB values
|
||||
float getLeftDB()
|
||||
{
|
||||
// range scale from range = -96 -> +10, to 0 -> 1
|
||||
float zeroOneL = (1-(fvbargraph0 / -96.f));
|
||||
fvbargraph0 = -96;
|
||||
return pow(zeroOneL, 4);
|
||||
}
|
||||
float getRightDB()
|
||||
{
|
||||
float zeroOneR = (1-(fvbargraph1 / -96.f));
|
||||
fvbargraph1 = -96;
|
||||
return pow(zeroOneR, 4);
|
||||
}
|
||||
|
||||
void process(int count, float* inputL, float* inputR )
|
||||
{
|
||||
for (int i = 0; (i < count); i = (i + 1))
|
||||
{
|
||||
fRec0[0] = max((fRec0[1] - fConst0), min(10.f, (20.f * log10f(max(1.58489e-05f, fabsf(*inputL))))));
|
||||
if ( fvbargraph0 < fRec0[0] )
|
||||
fvbargraph0 = fRec0[0];
|
||||
|
||||
fRec1[0] = max((fRec1[1] - fConst0), min(10.f, (20.f * log10f(max(1.58489e-05f, fabsf(*inputR))))));
|
||||
if ( fvbargraph1 < fRec1[0] )
|
||||
fvbargraph1 = fRec1[0];
|
||||
|
||||
fRec0[1] = fRec0[0];
|
||||
fRec1[1] = fRec1[0];
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
float fRec0[2];
|
||||
float fRec1[2];
|
||||
int fSamplingFreq;
|
||||
float fConst0;
|
||||
float fvbargraph0;
|
||||
float fvbargraph1;
|
||||
public:
|
||||
DBMeter(int rate)
|
||||
{
|
||||
fSamplingFreq = rate;
|
||||
fConst0 = (96.f / float(min(192000, max(1, fSamplingFreq))));
|
||||
|
||||
fRec0[0] = -96.f;
|
||||
fRec0[1] = -96.f;
|
||||
fRec1[0] = -96.f;
|
||||
fRec1[1] = -96.f;
|
||||
|
||||
fvbargraph0 = -96.f;
|
||||
fvbargraph1 = -96.f;
|
||||
}
|
||||
|
||||
int getNumInputs()
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
int getNumOutputs()
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
// call these to get the current dB values
|
||||
float getLeftDB()
|
||||
{
|
||||
// range scale from range = -96 -> +10, to 0 -> 1
|
||||
float zeroOneL = (1-(fvbargraph0 / -96.f));
|
||||
fvbargraph0 = -96;
|
||||
return pow(zeroOneL, 4);
|
||||
}
|
||||
float getRightDB()
|
||||
{
|
||||
float zeroOneR = (1-(fvbargraph1 / -96.f));
|
||||
fvbargraph1 = -96;
|
||||
return pow(zeroOneR, 4);
|
||||
}
|
||||
|
||||
void process(int count, float* inputL, float* inputR )
|
||||
{
|
||||
for (int i = 0; (i < count); i = (i + 1)) {
|
||||
fRec0[0] = max((fRec0[1] - fConst0), min(10.f, (20.f * log10f(max(1.58489e-05f, fabsf(*inputL))))));
|
||||
if ( fvbargraph0 < fRec0[0] )
|
||||
fvbargraph0 = fRec0[0];
|
||||
|
||||
fRec1[0] = max((fRec1[1] - fConst0), min(10.f, (20.f * log10f(max(1.58489e-05f, fabsf(*inputR))))));
|
||||
if ( fvbargraph1 < fRec1[0] )
|
||||
fvbargraph1 = fRec1[0];
|
||||
|
||||
fRec0[1] = fRec0[0];
|
||||
fRec1[1] = fRec1[0];
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
float fRec0[2];
|
||||
float fRec1[2];
|
||||
int fSamplingFreq;
|
||||
float fConst0;
|
||||
float fvbargraph0;
|
||||
float fvbargraph1;
|
||||
};
|
||||
|
||||
#endif // OPENAV_DSP_DBMETER_H
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -24,450 +24,479 @@
|
|||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
|
||||
template <int N> inline float faustpower(float x) { return powf(x,N); }
|
||||
template <int N> inline double faustpower(double x) { return pow(x,N); }
|
||||
template <int N> inline int faustpower(int x) { return faustpower<N/2>(x) * faustpower<N-N/2>(x); }
|
||||
template <> inline int faustpower<0>(int x) { return 1; }
|
||||
template <> inline int faustpower<1>(int x) { return x; }
|
||||
template <int N> inline float faustpower(float x)
|
||||
{
|
||||
return powf(x,N);
|
||||
}
|
||||
template <int N> inline double faustpower(double x)
|
||||
{
|
||||
return pow(x,N);
|
||||
}
|
||||
template <int N> inline int faustpower(int x)
|
||||
{
|
||||
return faustpower<N/2>(x) * faustpower<N-N/2>(x);
|
||||
}
|
||||
template <> inline int faustpower<0>(int x)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
template <> inline int faustpower<1>(int x)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
|
||||
class Reverb // : Effect
|
||||
{
|
||||
public:
|
||||
Reverb(int sr)
|
||||
{
|
||||
init( sr );
|
||||
}
|
||||
|
||||
int getNumInputs() { return 2; }
|
||||
int getNumOutputs(){ return 2; }
|
||||
|
||||
void damping(float d)
|
||||
{
|
||||
if( d > 1.0 ) d = 1.0f;
|
||||
if( d < 0.0 ) d = 0.0f;
|
||||
|
||||
_damping = (1-d) * 18500 + 1500.f;
|
||||
}
|
||||
|
||||
void rt60(float rt)
|
||||
{
|
||||
if( rt > 1.0 ) rt = 1.0f;
|
||||
if( rt < 0.0 ) rt = 0.0f;
|
||||
|
||||
_rt60 = 1 + rt * 5;
|
||||
}
|
||||
|
||||
void dryWet(float dw)
|
||||
{
|
||||
if( dw > 1.0 ) dw = 1.0f;
|
||||
if( dw < 0.0 ) dw = 0.0f;
|
||||
_dryWet = dw;
|
||||
}
|
||||
|
||||
void process (int count, float** input, float** output)
|
||||
{
|
||||
float fSlow0 = _rt60;
|
||||
float fSlow1 = expf((fConst2 / fSlow0));
|
||||
float fSlow2 = faustpower<2>(fSlow1);
|
||||
float fSlow3 = (1.0f - fSlow2);
|
||||
float fSlow4 = cosf((fConst3 * _damping));
|
||||
float fSlow5 = (1.0f - (fSlow4 * fSlow2));
|
||||
float fSlow6 = sqrtf(max(0.f, ((faustpower<2>(fSlow5) / faustpower<2>(fSlow3)) - 1.0f)));
|
||||
float fSlow7 = (fSlow5 / fSlow3);
|
||||
float fSlow8 = (fSlow7 - fSlow6);
|
||||
float fSlow9 = (fSlow0 - 0.5f);
|
||||
float fSlow10 = ((expf((fConst2 / fSlow9)) / fSlow1) - 1);
|
||||
float fSlow11 = (fSlow1 * ((1.0f + fSlow6) - fSlow7));
|
||||
float fSlow12 = expf((fConst12 / fSlow0));
|
||||
float fSlow13 = faustpower<2>(fSlow12);
|
||||
float fSlow14 = (1.0f - fSlow13);
|
||||
float fSlow15 = (1.0f - (fSlow4 * fSlow13));
|
||||
float fSlow16 = sqrtf(max(0.f, ((faustpower<2>(fSlow15) / faustpower<2>(fSlow14)) - 1.0f)));
|
||||
float fSlow17 = (fSlow15 / fSlow14);
|
||||
float fSlow18 = (fSlow17 - fSlow16);
|
||||
float fSlow19 = ((expf((fConst12 / fSlow9)) / fSlow12) - 1);
|
||||
float fSlow20 = (fSlow12 * ((1.0f + fSlow16) - fSlow17));
|
||||
float fSlow21 = expf((fConst17 / fSlow0));
|
||||
float fSlow22 = faustpower<2>(fSlow21);
|
||||
float fSlow23 = (1.0f - fSlow22);
|
||||
float fSlow24 = (1.0f - (fSlow4 * fSlow22));
|
||||
float fSlow25 = sqrtf(max(0.f, ((faustpower<2>(fSlow24) / faustpower<2>(fSlow23)) - 1.0f)));
|
||||
float fSlow26 = (fSlow24 / fSlow23);
|
||||
float fSlow27 = (fSlow26 - fSlow25);
|
||||
float fSlow28 = ((expf((fConst17 / fSlow9)) / fSlow21) - 1);
|
||||
float fSlow29 = (fSlow21 * ((1.0f + fSlow25) - fSlow26));
|
||||
float fSlow30 = expf((fConst22 / fSlow0));
|
||||
float fSlow31 = faustpower<2>(fSlow30);
|
||||
float fSlow32 = (1.0f - fSlow31);
|
||||
float fSlow33 = (1.0f - (fSlow4 * fSlow31));
|
||||
float fSlow34 = sqrtf(max(0.f, ((faustpower<2>(fSlow33) / faustpower<2>(fSlow32)) - 1.0f)));
|
||||
float fSlow35 = (fSlow33 / fSlow32);
|
||||
float fSlow36 = (fSlow35 - fSlow34);
|
||||
float fSlow37 = ((expf((fConst22 / fSlow9)) / fSlow30) - 1);
|
||||
float fSlow38 = (fSlow30 * ((1.0f + fSlow34) - fSlow35));
|
||||
float fSlow39 = expf((fConst27 / fSlow0));
|
||||
float fSlow40 = faustpower<2>(fSlow39);
|
||||
float fSlow41 = (1.0f - fSlow40);
|
||||
float fSlow42 = (1.0f - (fSlow4 * fSlow40));
|
||||
float fSlow43 = sqrtf(max(0.f, ((faustpower<2>(fSlow42) / faustpower<2>(fSlow41)) - 1.0f)));
|
||||
float fSlow44 = (fSlow42 / fSlow41);
|
||||
float fSlow45 = (fSlow44 - fSlow43);
|
||||
float fSlow46 = ((expf((fConst27 / fSlow9)) / fSlow39) - 1);
|
||||
float fSlow47 = (fSlow39 * ((1.0f + fSlow43) - fSlow44));
|
||||
float fSlow48 = expf((fConst32 / fSlow0));
|
||||
float fSlow49 = faustpower<2>(fSlow48);
|
||||
float fSlow50 = (1.0f - fSlow49);
|
||||
float fSlow51 = (1.0f - (fSlow4 * fSlow49));
|
||||
float fSlow52 = sqrtf(max(0.f, ((faustpower<2>(fSlow51) / faustpower<2>(fSlow50)) - 1.0f)));
|
||||
float fSlow53 = (fSlow51 / fSlow50);
|
||||
float fSlow54 = (fSlow53 - fSlow52);
|
||||
float fSlow55 = ((expf((fConst32 / fSlow9)) / fSlow48) - 1);
|
||||
float fSlow56 = (fSlow48 * ((1.0f + fSlow52) - fSlow53));
|
||||
float fSlow57 = expf((fConst37 / fSlow0));
|
||||
float fSlow58 = faustpower<2>(fSlow57);
|
||||
float fSlow59 = (1.0f - fSlow58);
|
||||
float fSlow60 = (1.0f - (fSlow4 * fSlow58));
|
||||
float fSlow61 = sqrtf(max(0.f, ((faustpower<2>(fSlow60) / faustpower<2>(fSlow59)) - 1.0f)));
|
||||
float fSlow62 = (fSlow60 / fSlow59);
|
||||
float fSlow63 = (fSlow62 - fSlow61);
|
||||
float fSlow64 = ((expf((fConst37 / fSlow9)) / fSlow57) - 1);
|
||||
float fSlow65 = (fSlow57 * ((1.0f + fSlow61) - fSlow62));
|
||||
float fSlow66 = expf((fConst42 / fSlow0));
|
||||
float fSlow67 = faustpower<2>(fSlow66);
|
||||
float fSlow68 = (1.0f - fSlow67);
|
||||
float fSlow69 = (1.0f - (fSlow67 * fSlow4));
|
||||
float fSlow70 = sqrtf(max(0.f, ((faustpower<2>(fSlow69) / faustpower<2>(fSlow68)) - 1.0f)));
|
||||
float fSlow71 = (fSlow69 / fSlow68);
|
||||
float fSlow72 = (fSlow71 - fSlow70);
|
||||
float fSlow73 = ((expf((fConst42 / fSlow9)) / fSlow66) - 1);
|
||||
float fSlow74 = (fSlow66 * ((1.0f + fSlow70) - fSlow71));
|
||||
float* input0 = input[0];
|
||||
float* input1 = input[1];
|
||||
float* output0 = output[0];
|
||||
float* output1 = output[1];
|
||||
for (int i=0; i<count; i++) {
|
||||
fRec11[0] = ((fConst7 * (fRec4[1] + fRec4[2])) + (fConst6 * fRec11[1]));
|
||||
fRec10[0] = ((fSlow11 * (fRec4[1] + (fSlow10 * fRec11[0]))) + (fSlow8 * fRec10[1]));
|
||||
fVec0[IOTA&8191] = (1e-20f + (0.35355339059327373f * fRec10[0]));
|
||||
float fTemp0 = (0.3f * (float)input0[i]);
|
||||
float fTemp1 = ((fTemp0 + fVec0[(IOTA-iConst9)&8191]) - (0.6f * fRec8[1]));
|
||||
fVec1[IOTA&2047] = fTemp1;
|
||||
fRec8[0] = fVec1[(IOTA-iConst10)&2047];
|
||||
float fRec9 = (0.6f * fVec1[IOTA&2047]);
|
||||
fRec15[0] = ((fConst7 * (fRec0[1] + fRec0[2])) + (fConst6 * fRec15[1]));
|
||||
fRec14[0] = ((fSlow20 * (fRec0[1] + (fSlow19 * fRec15[0]))) + (fSlow18 * fRec14[1]));
|
||||
fVec2[IOTA&8191] = (1e-20f + (0.35355339059327373f * fRec14[0]));
|
||||
float fTemp2 = ((fTemp0 + fVec2[(IOTA-iConst14)&8191]) - (0.6f * fRec12[1]));
|
||||
fVec3[IOTA&1023] = fTemp2;
|
||||
fRec12[0] = fVec3[(IOTA-iConst15)&1023];
|
||||
float fRec13 = (0.6f * fVec3[IOTA&1023]);
|
||||
float fTemp3 = (fRec13 + fRec9);
|
||||
fRec19[0] = ((fConst7 * (fRec2[1] + fRec2[2])) + (fConst6 * fRec19[1]));
|
||||
fRec18[0] = ((fSlow29 * (fRec2[1] + (fSlow28 * fRec19[0]))) + (fSlow27 * fRec18[1]));
|
||||
fVec4[IOTA&8191] = (1e-20f + (0.35355339059327373f * fRec18[0]));
|
||||
float fTemp4 = (fVec4[(IOTA-iConst19)&8191] - (fTemp0 + (0.6f * fRec16[1])));
|
||||
fVec5[IOTA&2047] = fTemp4;
|
||||
fRec16[0] = fVec5[(IOTA-iConst20)&2047];
|
||||
float fRec17 = (0.6f * fVec5[IOTA&2047]);
|
||||
fRec23[0] = ((fConst7 * (fRec6[1] + fRec6[2])) + (fConst6 * fRec23[1]));
|
||||
fRec22[0] = ((fSlow38 * (fRec6[1] + (fSlow37 * fRec23[0]))) + (fSlow36 * fRec22[1]));
|
||||
fVec6[IOTA&8191] = (1e-20f + (0.35355339059327373f * fRec22[0]));
|
||||
float fTemp5 = (fVec6[(IOTA-iConst24)&8191] - (fTemp0 + (0.6f * fRec20[1])));
|
||||
fVec7[IOTA&1023] = fTemp5;
|
||||
fRec20[0] = fVec7[(IOTA-iConst25)&1023];
|
||||
float fRec21 = (0.6f * fVec7[IOTA&1023]);
|
||||
float fTemp6 = (fRec21 + (fRec17 + fTemp3));
|
||||
fRec27[0] = ((fConst7 * (fRec1[1] + fRec1[2])) + (fConst6 * fRec27[1]));
|
||||
fRec26[0] = ((fSlow47 * (fRec1[1] + (fSlow46 * fRec27[0]))) + (fSlow45 * fRec26[1]));
|
||||
fVec8[IOTA&16383] = (1e-20f + (0.35355339059327373f * fRec26[0]));
|
||||
float fTemp7 = (0.3f * (float)input1[i]);
|
||||
float fTemp8 = ((fTemp7 + fVec8[(IOTA-iConst29)&16383]) + (0.6f * fRec24[1]));
|
||||
fVec9[IOTA&2047] = fTemp8;
|
||||
fRec24[0] = fVec9[(IOTA-iConst30)&2047];
|
||||
float fRec25 = (0 - (0.6f * fVec9[IOTA&2047]));
|
||||
fRec31[0] = ((fConst7 * (fRec5[1] + fRec5[2])) + (fConst6 * fRec31[1]));
|
||||
fRec30[0] = ((fSlow56 * (fRec5[1] + (fSlow55 * fRec31[0]))) + (fSlow54 * fRec30[1]));
|
||||
fVec10[IOTA&8191] = (1e-20f + (0.35355339059327373f * fRec30[0]));
|
||||
float fTemp9 = ((fTemp7 + fVec10[(IOTA-iConst34)&8191]) + (0.6f * fRec28[1]));
|
||||
fVec11[IOTA&2047] = fTemp9;
|
||||
fRec28[0] = fVec11[(IOTA-iConst35)&2047];
|
||||
float fRec29 = (0 - (0.6f * fVec11[IOTA&2047]));
|
||||
fRec35[0] = ((fConst7 * (fRec3[1] + fRec3[2])) + (fConst6 * fRec35[1]));
|
||||
fRec34[0] = ((fSlow65 * (fRec3[1] + (fSlow64 * fRec35[0]))) + (fSlow63 * fRec34[1]));
|
||||
fVec12[IOTA&16383] = (1e-20f + (0.35355339059327373f * fRec34[0]));
|
||||
float fTemp10 = ((fVec12[(IOTA-iConst39)&16383] + (0.6f * fRec32[1])) - fTemp7);
|
||||
fVec13[IOTA&2047] = fTemp10;
|
||||
fRec32[0] = fVec13[(IOTA-iConst40)&2047];
|
||||
float fRec33 = (0 - (0.6f * fVec13[IOTA&2047]));
|
||||
fRec39[0] = ((fConst7 * (fRec7[1] + fRec7[2])) + (fConst6 * fRec39[1]));
|
||||
fRec38[0] = ((fSlow74 * (fRec7[1] + (fSlow73 * fRec39[0]))) + (fSlow72 * fRec38[1]));
|
||||
fVec14[IOTA&16383] = (1e-20f + (0.35355339059327373f * fRec38[0]));
|
||||
float fTemp11 = ((fVec14[(IOTA-iConst44)&16383] + (0.6f * fRec36[1])) - fTemp7);
|
||||
fVec15[IOTA&1023] = fTemp11;
|
||||
fRec36[0] = fVec15[(IOTA-iConst45)&1023];
|
||||
float fRec37 = (0 - (0.6f * fVec15[IOTA&1023]));
|
||||
fRec0[0] = (fRec12[1] + (fRec8[1] + (fRec16[1] + (fRec20[1] + (fRec24[1] + (fRec28[1] + (fRec32[1] + (fRec36[1] + (fRec37 + (fRec33 + (fRec29 + (fRec25 + fTemp6))))))))))));
|
||||
fRec1[0] = (0 - ((fRec24[1] + (fRec28[1] + (fRec32[1] + (fRec36[1] + (fRec37 + (fRec33 + (fRec25 + fRec29))))))) - (fRec12[1] + (fRec8[1] + (fRec16[1] + (fRec20[1] + fTemp6))))));
|
||||
float fTemp12 = (fRec17 + fRec21);
|
||||
fRec2[0] = (0 - ((fRec16[1] + (fRec20[1] + (fRec32[1] + (fRec36[1] + (fRec37 + (fRec33 + fTemp12)))))) - (fRec12[1] + (fRec8[1] + (fRec24[1] + (fRec28[1] + (fRec29 + (fRec25 + fTemp3))))))));
|
||||
fRec3[0] = (0 - ((fRec16[1] + (fRec20[1] + (fRec24[1] + (fRec28[1] + (fRec29 + (fRec25 + fTemp12)))))) - (fRec12[1] + (fRec8[1] + (fRec32[1] + (fRec36[1] + (fRec37 + (fRec33 + fTemp3))))))));
|
||||
float fTemp13 = (fRec13 + fRec17);
|
||||
float fTemp14 = (fRec9 + fRec21);
|
||||
fRec4[0] = (0 - ((fRec8[1] + (fRec20[1] + (fRec28[1] + (fRec36[1] + (fRec37 + (fRec29 + fTemp14)))))) - (fRec12[1] + (fRec16[1] + (fRec24[1] + (fRec32[1] + (fRec33 + (fRec25 + fTemp13))))))));
|
||||
fRec5[0] = (0 - ((fRec8[1] + (fRec20[1] + (fRec24[1] + (fRec32[1] + (fRec33 + (fRec25 + fTemp14)))))) - (fRec12[1] + (fRec16[1] + (fRec28[1] + (fRec36[1] + (fRec37 + (fRec29 + fTemp13))))))));
|
||||
float fTemp15 = (fRec13 + fRec21);
|
||||
float fTemp16 = (fRec9 + fRec17);
|
||||
fRec6[0] = (0 - ((fRec8[1] + (fRec16[1] + (fRec28[1] + (fRec32[1] + (fRec33 + (fRec29 + fTemp16)))))) - (fRec12[1] + (fRec20[1] + (fRec24[1] + (fRec36[1] + (fRec37 + (fRec25 + fTemp15))))))));
|
||||
fRec7[0] = (0 - ((fRec8[1] + (fRec16[1] + (fRec24[1] + (fRec36[1] + (fRec37 + (fRec25 + fTemp16)))))) - (fRec12[1] + (fRec20[1] + (fRec28[1] + (fRec32[1] + (fRec33 + (fRec29 + fTemp15))))))));
|
||||
|
||||
|
||||
float reverb0 = (float)(0.37f * (fRec1[0] + fRec2[0]));
|
||||
float reverb1 = (float)(0.37f * (fRec1[0] - fRec2[0]));
|
||||
|
||||
output0[i] = (input0[i] * (1-_dryWet)) + (reverb0 * _dryWet );
|
||||
output1[i] = (input1[i] * (1-_dryWet)) + (reverb1 * _dryWet );
|
||||
|
||||
// post processing
|
||||
fRec7[2] = fRec7[1]; fRec7[1] = fRec7[0];
|
||||
fRec6[2] = fRec6[1]; fRec6[1] = fRec6[0];
|
||||
fRec5[2] = fRec5[1]; fRec5[1] = fRec5[0];
|
||||
fRec4[2] = fRec4[1]; fRec4[1] = fRec4[0];
|
||||
fRec3[2] = fRec3[1]; fRec3[1] = fRec3[0];
|
||||
fRec2[2] = fRec2[1]; fRec2[1] = fRec2[0];
|
||||
fRec1[2] = fRec1[1]; fRec1[1] = fRec1[0];
|
||||
fRec0[2] = fRec0[1]; fRec0[1] = fRec0[0];
|
||||
fRec36[1] = fRec36[0];
|
||||
fRec38[1] = fRec38[0];
|
||||
fRec39[1] = fRec39[0];
|
||||
fRec32[1] = fRec32[0];
|
||||
fRec34[1] = fRec34[0];
|
||||
fRec35[1] = fRec35[0];
|
||||
fRec28[1] = fRec28[0];
|
||||
fRec30[1] = fRec30[0];
|
||||
fRec31[1] = fRec31[0];
|
||||
fRec24[1] = fRec24[0];
|
||||
fRec26[1] = fRec26[0];
|
||||
fRec27[1] = fRec27[0];
|
||||
fRec20[1] = fRec20[0];
|
||||
fRec22[1] = fRec22[0];
|
||||
fRec23[1] = fRec23[0];
|
||||
fRec16[1] = fRec16[0];
|
||||
fRec18[1] = fRec18[0];
|
||||
fRec19[1] = fRec19[0];
|
||||
fRec12[1] = fRec12[0];
|
||||
fRec14[1] = fRec14[0];
|
||||
fRec15[1] = fRec15[0];
|
||||
fRec8[1] = fRec8[0];
|
||||
IOTA = IOTA+1;
|
||||
fRec10[1] = fRec10[0];
|
||||
fRec11[1] = fRec11[0];
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
float _dryWet;
|
||||
float _rt60;
|
||||
int iConst0;
|
||||
float fConst1;
|
||||
float fConst2;
|
||||
float _damping;
|
||||
float fConst3;
|
||||
float fConst4;
|
||||
float fConst5;
|
||||
float fConst6;
|
||||
float fConst7;
|
||||
float fRec11[2];
|
||||
float fRec10[2];
|
||||
int IOTA;
|
||||
float fVec0[8192];
|
||||
float fConst8;
|
||||
int iConst9;
|
||||
float fVec1[2048];
|
||||
int iConst10;
|
||||
float fRec8[2];
|
||||
float fConst11;
|
||||
float fConst12;
|
||||
float fRec15[2];
|
||||
float fRec14[2];
|
||||
float fVec2[8192];
|
||||
float fConst13;
|
||||
int iConst14;
|
||||
float fVec3[1024];
|
||||
int iConst15;
|
||||
float fRec12[2];
|
||||
float fConst16;
|
||||
float fConst17;
|
||||
float fRec19[2];
|
||||
float fRec18[2];
|
||||
float fVec4[8192];
|
||||
float fConst18;
|
||||
int iConst19;
|
||||
float fVec5[2048];
|
||||
int iConst20;
|
||||
float fRec16[2];
|
||||
float fConst21;
|
||||
float fConst22;
|
||||
float fRec23[2];
|
||||
float fRec22[2];
|
||||
float fVec6[8192];
|
||||
float fConst23;
|
||||
int iConst24;
|
||||
float fVec7[1024];
|
||||
int iConst25;
|
||||
float fRec20[2];
|
||||
float fConst26;
|
||||
float fConst27;
|
||||
float fRec27[2];
|
||||
float fRec26[2];
|
||||
float fVec8[16384];
|
||||
float fConst28;
|
||||
int iConst29;
|
||||
float fVec9[2048];
|
||||
int iConst30;
|
||||
float fRec24[2];
|
||||
float fConst31;
|
||||
float fConst32;
|
||||
float fRec31[2];
|
||||
float fRec30[2];
|
||||
float fVec10[8192];
|
||||
float fConst33;
|
||||
int iConst34;
|
||||
float fVec11[2048];
|
||||
int iConst35;
|
||||
float fRec28[2];
|
||||
float fConst36;
|
||||
float fConst37;
|
||||
float fRec35[2];
|
||||
float fRec34[2];
|
||||
float fVec12[16384];
|
||||
float fConst38;
|
||||
int iConst39;
|
||||
float fVec13[2048];
|
||||
int iConst40;
|
||||
float fRec32[2];
|
||||
float fConst41;
|
||||
float fConst42;
|
||||
float fRec39[2];
|
||||
float fRec38[2];
|
||||
float fVec14[16384];
|
||||
float fConst43;
|
||||
int iConst44;
|
||||
float fVec15[1024];
|
||||
int iConst45;
|
||||
float fRec36[2];
|
||||
float fRec0[3];
|
||||
float fRec1[3];
|
||||
float fRec2[3];
|
||||
float fRec3[3];
|
||||
float fRec4[3];
|
||||
float fRec5[3];
|
||||
float fRec6[3];
|
||||
float fRec7[3];
|
||||
|
||||
/// Long nasty function setting initial values
|
||||
void init(int samplingFreq)
|
||||
{
|
||||
// wet by default!
|
||||
_dryWet = 1;
|
||||
|
||||
_rt60 = 5.0f;
|
||||
iConst0 = min(192000, max(1, samplingFreq));
|
||||
fConst1 = floorf((0.5f + (0.174713f * iConst0)));
|
||||
fConst2 = ((0 - (6.907755278982138f * fConst1)) / iConst0);
|
||||
_damping = 10000.f;
|
||||
fConst3 = (6.283185307179586f / float(iConst0));
|
||||
fConst4 = (1.0f / tanf((1256.6370614359173f / iConst0)));
|
||||
fConst5 = (1 + fConst4);
|
||||
fConst6 = (0 - ((1 - fConst4) / fConst5));
|
||||
fConst7 = (1.0f / fConst5);
|
||||
for (int i=0; i<2; i++) fRec11[i] = 0;
|
||||
for (int i=0; i<2; i++) fRec10[i] = 0;
|
||||
IOTA = 0;
|
||||
for (int i=0; i<8192; i++) fVec0[i] = 0;
|
||||
fConst8 = floorf((0.5f + (0.022904f * iConst0)));
|
||||
iConst9 = int((int((fConst1 - fConst8)) & 8191));
|
||||
for (int i=0; i<2048; i++) fVec1[i] = 0;
|
||||
iConst10 = int((int((fConst8 - 1)) & 2047));
|
||||
for (int i=0; i<2; i++) fRec8[i] = 0;
|
||||
fConst11 = floorf((0.5f + (0.153129f * iConst0)));
|
||||
fConst12 = ((0 - (6.907755278982138f * fConst11)) / iConst0);
|
||||
for (int i=0; i<2; i++) fRec15[i] = 0;
|
||||
for (int i=0; i<2; i++) fRec14[i] = 0;
|
||||
for (int i=0; i<8192; i++) fVec2[i] = 0;
|
||||
fConst13 = floorf((0.5f + (0.020346f * iConst0)));
|
||||
iConst14 = int((int((fConst11 - fConst13)) & 8191));
|
||||
for (int i=0; i<1024; i++) fVec3[i] = 0;
|
||||
iConst15 = int((int((fConst13 - 1)) & 1023));
|
||||
for (int i=0; i<2; i++) fRec12[i] = 0;
|
||||
fConst16 = floorf((0.5f + (0.127837f * iConst0)));
|
||||
fConst17 = ((0 - (6.907755278982138f * fConst16)) / iConst0);
|
||||
for (int i=0; i<2; i++) fRec19[i] = 0;
|
||||
for (int i=0; i<2; i++) fRec18[i] = 0;
|
||||
for (int i=0; i<8192; i++) fVec4[i] = 0;
|
||||
fConst18 = floorf((0.5f + (0.031604f * iConst0)));
|
||||
iConst19 = int((int((fConst16 - fConst18)) & 8191));
|
||||
for (int i=0; i<2048; i++) fVec5[i] = 0;
|
||||
iConst20 = int((int((fConst18 - 1)) & 2047));
|
||||
for (int i=0; i<2; i++) fRec16[i] = 0;
|
||||
fConst21 = floorf((0.5f + (0.125f * iConst0)));
|
||||
fConst22 = ((0 - (6.907755278982138f * fConst21)) / iConst0);
|
||||
for (int i=0; i<2; i++) fRec23[i] = 0;
|
||||
for (int i=0; i<2; i++) fRec22[i] = 0;
|
||||
for (int i=0; i<8192; i++) fVec6[i] = 0;
|
||||
fConst23 = floorf((0.5f + (0.013458f * iConst0)));
|
||||
iConst24 = int((int((fConst21 - fConst23)) & 8191));
|
||||
for (int i=0; i<1024; i++) fVec7[i] = 0;
|
||||
iConst25 = int((int((fConst23 - 1)) & 1023));
|
||||
for (int i=0; i<2; i++) fRec20[i] = 0;
|
||||
fConst26 = floorf((0.5f + (0.210389f * iConst0)));
|
||||
fConst27 = ((0 - (6.907755278982138f * fConst26)) / iConst0);
|
||||
for (int i=0; i<2; i++) fRec27[i] = 0;
|
||||
for (int i=0; i<2; i++) fRec26[i] = 0;
|
||||
for (int i=0; i<16384; i++) fVec8[i] = 0;
|
||||
fConst28 = floorf((0.5f + (0.024421f * iConst0)));
|
||||
iConst29 = int((int((fConst26 - fConst28)) & 16383));
|
||||
for (int i=0; i<2048; i++) fVec9[i] = 0;
|
||||
iConst30 = int((int((fConst28 - 1)) & 2047));
|
||||
for (int i=0; i<2; i++) fRec24[i] = 0;
|
||||
fConst31 = floorf((0.5f + (0.192303f * iConst0)));
|
||||
fConst32 = ((0 - (6.907755278982138f * fConst31)) / iConst0);
|
||||
for (int i=0; i<2; i++) fRec31[i] = 0;
|
||||
for (int i=0; i<2; i++) fRec30[i] = 0;
|
||||
for (int i=0; i<8192; i++) fVec10[i] = 0;
|
||||
fConst33 = floorf((0.5f + (0.029291f * iConst0)));
|
||||
iConst34 = int((int((fConst31 - fConst33)) & 8191));
|
||||
for (int i=0; i<2048; i++) fVec11[i] = 0;
|
||||
iConst35 = int((int((fConst33 - 1)) & 2047));
|
||||
for (int i=0; i<2; i++) fRec28[i] = 0;
|
||||
fConst36 = floorf((0.5f + (0.256891f * iConst0)));
|
||||
fConst37 = ((0 - (6.907755278982138f * fConst36)) / iConst0);
|
||||
for (int i=0; i<2; i++) fRec35[i] = 0;
|
||||
for (int i=0; i<2; i++) fRec34[i] = 0;
|
||||
for (int i=0; i<16384; i++) fVec12[i] = 0;
|
||||
fConst38 = floorf((0.5f + (0.027333f * iConst0)));
|
||||
iConst39 = int((int((fConst36 - fConst38)) & 16383));
|
||||
for (int i=0; i<2048; i++) fVec13[i] = 0;
|
||||
iConst40 = int((int((fConst38 - 1)) & 2047));
|
||||
for (int i=0; i<2; i++) fRec32[i] = 0;
|
||||
fConst41 = floorf((0.5f + (0.219991f * iConst0)));
|
||||
fConst42 = ((0 - (6.907755278982138f * fConst41)) / iConst0);
|
||||
for (int i=0; i<2; i++) fRec39[i] = 0;
|
||||
for (int i=0; i<2; i++) fRec38[i] = 0;
|
||||
for (int i=0; i<16384; i++) fVec14[i] = 0;
|
||||
fConst43 = floorf((0.5f + (0.019123f * iConst0)));
|
||||
iConst44 = int((int((fConst41 - fConst43)) & 16383));
|
||||
for (int i=0; i<1024; i++) fVec15[i] = 0;
|
||||
iConst45 = int((int((fConst43 - 1)) & 1023));
|
||||
for (int i=0; i<2; i++) fRec36[i] = 0;
|
||||
for (int i=0; i<3; i++) fRec0[i] = 0;
|
||||
for (int i=0; i<3; i++) fRec1[i] = 0;
|
||||
for (int i=0; i<3; i++) fRec2[i] = 0;
|
||||
for (int i=0; i<3; i++) fRec3[i] = 0;
|
||||
for (int i=0; i<3; i++) fRec4[i] = 0;
|
||||
for (int i=0; i<3; i++) fRec5[i] = 0;
|
||||
for (int i=0; i<3; i++) fRec6[i] = 0;
|
||||
for (int i=0; i<3; i++) fRec7[i] = 0;
|
||||
}
|
||||
public:
|
||||
Reverb(int sr)
|
||||
{
|
||||
init( sr );
|
||||
}
|
||||
|
||||
int getNumInputs()
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
int getNumOutputs()
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
void damping(float d)
|
||||
{
|
||||
if( d > 1.0 ) d = 1.0f;
|
||||
if( d < 0.0 ) d = 0.0f;
|
||||
|
||||
_damping = (1-d) * 18500 + 1500.f;
|
||||
}
|
||||
|
||||
void rt60(float rt)
|
||||
{
|
||||
if( rt > 1.0 ) rt = 1.0f;
|
||||
if( rt < 0.0 ) rt = 0.0f;
|
||||
|
||||
_rt60 = 1 + rt * 5;
|
||||
}
|
||||
|
||||
void dryWet(float dw)
|
||||
{
|
||||
if( dw > 1.0 ) dw = 1.0f;
|
||||
if( dw < 0.0 ) dw = 0.0f;
|
||||
_dryWet = dw;
|
||||
}
|
||||
|
||||
void process (int count, float** input, float** output)
|
||||
{
|
||||
float fSlow0 = _rt60;
|
||||
float fSlow1 = expf((fConst2 / fSlow0));
|
||||
float fSlow2 = faustpower<2>(fSlow1);
|
||||
float fSlow3 = (1.0f - fSlow2);
|
||||
float fSlow4 = cosf((fConst3 * _damping));
|
||||
float fSlow5 = (1.0f - (fSlow4 * fSlow2));
|
||||
float fSlow6 = sqrtf(max(0.f, ((faustpower<2>(fSlow5) / faustpower<2>(fSlow3)) - 1.0f)));
|
||||
float fSlow7 = (fSlow5 / fSlow3);
|
||||
float fSlow8 = (fSlow7 - fSlow6);
|
||||
float fSlow9 = (fSlow0 - 0.5f);
|
||||
float fSlow10 = ((expf((fConst2 / fSlow9)) / fSlow1) - 1);
|
||||
float fSlow11 = (fSlow1 * ((1.0f + fSlow6) - fSlow7));
|
||||
float fSlow12 = expf((fConst12 / fSlow0));
|
||||
float fSlow13 = faustpower<2>(fSlow12);
|
||||
float fSlow14 = (1.0f - fSlow13);
|
||||
float fSlow15 = (1.0f - (fSlow4 * fSlow13));
|
||||
float fSlow16 = sqrtf(max(0.f, ((faustpower<2>(fSlow15) / faustpower<2>(fSlow14)) - 1.0f)));
|
||||
float fSlow17 = (fSlow15 / fSlow14);
|
||||
float fSlow18 = (fSlow17 - fSlow16);
|
||||
float fSlow19 = ((expf((fConst12 / fSlow9)) / fSlow12) - 1);
|
||||
float fSlow20 = (fSlow12 * ((1.0f + fSlow16) - fSlow17));
|
||||
float fSlow21 = expf((fConst17 / fSlow0));
|
||||
float fSlow22 = faustpower<2>(fSlow21);
|
||||
float fSlow23 = (1.0f - fSlow22);
|
||||
float fSlow24 = (1.0f - (fSlow4 * fSlow22));
|
||||
float fSlow25 = sqrtf(max(0.f, ((faustpower<2>(fSlow24) / faustpower<2>(fSlow23)) - 1.0f)));
|
||||
float fSlow26 = (fSlow24 / fSlow23);
|
||||
float fSlow27 = (fSlow26 - fSlow25);
|
||||
float fSlow28 = ((expf((fConst17 / fSlow9)) / fSlow21) - 1);
|
||||
float fSlow29 = (fSlow21 * ((1.0f + fSlow25) - fSlow26));
|
||||
float fSlow30 = expf((fConst22 / fSlow0));
|
||||
float fSlow31 = faustpower<2>(fSlow30);
|
||||
float fSlow32 = (1.0f - fSlow31);
|
||||
float fSlow33 = (1.0f - (fSlow4 * fSlow31));
|
||||
float fSlow34 = sqrtf(max(0.f, ((faustpower<2>(fSlow33) / faustpower<2>(fSlow32)) - 1.0f)));
|
||||
float fSlow35 = (fSlow33 / fSlow32);
|
||||
float fSlow36 = (fSlow35 - fSlow34);
|
||||
float fSlow37 = ((expf((fConst22 / fSlow9)) / fSlow30) - 1);
|
||||
float fSlow38 = (fSlow30 * ((1.0f + fSlow34) - fSlow35));
|
||||
float fSlow39 = expf((fConst27 / fSlow0));
|
||||
float fSlow40 = faustpower<2>(fSlow39);
|
||||
float fSlow41 = (1.0f - fSlow40);
|
||||
float fSlow42 = (1.0f - (fSlow4 * fSlow40));
|
||||
float fSlow43 = sqrtf(max(0.f, ((faustpower<2>(fSlow42) / faustpower<2>(fSlow41)) - 1.0f)));
|
||||
float fSlow44 = (fSlow42 / fSlow41);
|
||||
float fSlow45 = (fSlow44 - fSlow43);
|
||||
float fSlow46 = ((expf((fConst27 / fSlow9)) / fSlow39) - 1);
|
||||
float fSlow47 = (fSlow39 * ((1.0f + fSlow43) - fSlow44));
|
||||
float fSlow48 = expf((fConst32 / fSlow0));
|
||||
float fSlow49 = faustpower<2>(fSlow48);
|
||||
float fSlow50 = (1.0f - fSlow49);
|
||||
float fSlow51 = (1.0f - (fSlow4 * fSlow49));
|
||||
float fSlow52 = sqrtf(max(0.f, ((faustpower<2>(fSlow51) / faustpower<2>(fSlow50)) - 1.0f)));
|
||||
float fSlow53 = (fSlow51 / fSlow50);
|
||||
float fSlow54 = (fSlow53 - fSlow52);
|
||||
float fSlow55 = ((expf((fConst32 / fSlow9)) / fSlow48) - 1);
|
||||
float fSlow56 = (fSlow48 * ((1.0f + fSlow52) - fSlow53));
|
||||
float fSlow57 = expf((fConst37 / fSlow0));
|
||||
float fSlow58 = faustpower<2>(fSlow57);
|
||||
float fSlow59 = (1.0f - fSlow58);
|
||||
float fSlow60 = (1.0f - (fSlow4 * fSlow58));
|
||||
float fSlow61 = sqrtf(max(0.f, ((faustpower<2>(fSlow60) / faustpower<2>(fSlow59)) - 1.0f)));
|
||||
float fSlow62 = (fSlow60 / fSlow59);
|
||||
float fSlow63 = (fSlow62 - fSlow61);
|
||||
float fSlow64 = ((expf((fConst37 / fSlow9)) / fSlow57) - 1);
|
||||
float fSlow65 = (fSlow57 * ((1.0f + fSlow61) - fSlow62));
|
||||
float fSlow66 = expf((fConst42 / fSlow0));
|
||||
float fSlow67 = faustpower<2>(fSlow66);
|
||||
float fSlow68 = (1.0f - fSlow67);
|
||||
float fSlow69 = (1.0f - (fSlow67 * fSlow4));
|
||||
float fSlow70 = sqrtf(max(0.f, ((faustpower<2>(fSlow69) / faustpower<2>(fSlow68)) - 1.0f)));
|
||||
float fSlow71 = (fSlow69 / fSlow68);
|
||||
float fSlow72 = (fSlow71 - fSlow70);
|
||||
float fSlow73 = ((expf((fConst42 / fSlow9)) / fSlow66) - 1);
|
||||
float fSlow74 = (fSlow66 * ((1.0f + fSlow70) - fSlow71));
|
||||
float* input0 = input[0];
|
||||
float* input1 = input[1];
|
||||
float* output0 = output[0];
|
||||
float* output1 = output[1];
|
||||
for (int i=0; i<count; i++) {
|
||||
fRec11[0] = ((fConst7 * (fRec4[1] + fRec4[2])) + (fConst6 * fRec11[1]));
|
||||
fRec10[0] = ((fSlow11 * (fRec4[1] + (fSlow10 * fRec11[0]))) + (fSlow8 * fRec10[1]));
|
||||
fVec0[IOTA&8191] = (1e-20f + (0.35355339059327373f * fRec10[0]));
|
||||
float fTemp0 = (0.3f * (float)input0[i]);
|
||||
float fTemp1 = ((fTemp0 + fVec0[(IOTA-iConst9)&8191]) - (0.6f * fRec8[1]));
|
||||
fVec1[IOTA&2047] = fTemp1;
|
||||
fRec8[0] = fVec1[(IOTA-iConst10)&2047];
|
||||
float fRec9 = (0.6f * fVec1[IOTA&2047]);
|
||||
fRec15[0] = ((fConst7 * (fRec0[1] + fRec0[2])) + (fConst6 * fRec15[1]));
|
||||
fRec14[0] = ((fSlow20 * (fRec0[1] + (fSlow19 * fRec15[0]))) + (fSlow18 * fRec14[1]));
|
||||
fVec2[IOTA&8191] = (1e-20f + (0.35355339059327373f * fRec14[0]));
|
||||
float fTemp2 = ((fTemp0 + fVec2[(IOTA-iConst14)&8191]) - (0.6f * fRec12[1]));
|
||||
fVec3[IOTA&1023] = fTemp2;
|
||||
fRec12[0] = fVec3[(IOTA-iConst15)&1023];
|
||||
float fRec13 = (0.6f * fVec3[IOTA&1023]);
|
||||
float fTemp3 = (fRec13 + fRec9);
|
||||
fRec19[0] = ((fConst7 * (fRec2[1] + fRec2[2])) + (fConst6 * fRec19[1]));
|
||||
fRec18[0] = ((fSlow29 * (fRec2[1] + (fSlow28 * fRec19[0]))) + (fSlow27 * fRec18[1]));
|
||||
fVec4[IOTA&8191] = (1e-20f + (0.35355339059327373f * fRec18[0]));
|
||||
float fTemp4 = (fVec4[(IOTA-iConst19)&8191] - (fTemp0 + (0.6f * fRec16[1])));
|
||||
fVec5[IOTA&2047] = fTemp4;
|
||||
fRec16[0] = fVec5[(IOTA-iConst20)&2047];
|
||||
float fRec17 = (0.6f * fVec5[IOTA&2047]);
|
||||
fRec23[0] = ((fConst7 * (fRec6[1] + fRec6[2])) + (fConst6 * fRec23[1]));
|
||||
fRec22[0] = ((fSlow38 * (fRec6[1] + (fSlow37 * fRec23[0]))) + (fSlow36 * fRec22[1]));
|
||||
fVec6[IOTA&8191] = (1e-20f + (0.35355339059327373f * fRec22[0]));
|
||||
float fTemp5 = (fVec6[(IOTA-iConst24)&8191] - (fTemp0 + (0.6f * fRec20[1])));
|
||||
fVec7[IOTA&1023] = fTemp5;
|
||||
fRec20[0] = fVec7[(IOTA-iConst25)&1023];
|
||||
float fRec21 = (0.6f * fVec7[IOTA&1023]);
|
||||
float fTemp6 = (fRec21 + (fRec17 + fTemp3));
|
||||
fRec27[0] = ((fConst7 * (fRec1[1] + fRec1[2])) + (fConst6 * fRec27[1]));
|
||||
fRec26[0] = ((fSlow47 * (fRec1[1] + (fSlow46 * fRec27[0]))) + (fSlow45 * fRec26[1]));
|
||||
fVec8[IOTA&16383] = (1e-20f + (0.35355339059327373f * fRec26[0]));
|
||||
float fTemp7 = (0.3f * (float)input1[i]);
|
||||
float fTemp8 = ((fTemp7 + fVec8[(IOTA-iConst29)&16383]) + (0.6f * fRec24[1]));
|
||||
fVec9[IOTA&2047] = fTemp8;
|
||||
fRec24[0] = fVec9[(IOTA-iConst30)&2047];
|
||||
float fRec25 = (0 - (0.6f * fVec9[IOTA&2047]));
|
||||
fRec31[0] = ((fConst7 * (fRec5[1] + fRec5[2])) + (fConst6 * fRec31[1]));
|
||||
fRec30[0] = ((fSlow56 * (fRec5[1] + (fSlow55 * fRec31[0]))) + (fSlow54 * fRec30[1]));
|
||||
fVec10[IOTA&8191] = (1e-20f + (0.35355339059327373f * fRec30[0]));
|
||||
float fTemp9 = ((fTemp7 + fVec10[(IOTA-iConst34)&8191]) + (0.6f * fRec28[1]));
|
||||
fVec11[IOTA&2047] = fTemp9;
|
||||
fRec28[0] = fVec11[(IOTA-iConst35)&2047];
|
||||
float fRec29 = (0 - (0.6f * fVec11[IOTA&2047]));
|
||||
fRec35[0] = ((fConst7 * (fRec3[1] + fRec3[2])) + (fConst6 * fRec35[1]));
|
||||
fRec34[0] = ((fSlow65 * (fRec3[1] + (fSlow64 * fRec35[0]))) + (fSlow63 * fRec34[1]));
|
||||
fVec12[IOTA&16383] = (1e-20f + (0.35355339059327373f * fRec34[0]));
|
||||
float fTemp10 = ((fVec12[(IOTA-iConst39)&16383] + (0.6f * fRec32[1])) - fTemp7);
|
||||
fVec13[IOTA&2047] = fTemp10;
|
||||
fRec32[0] = fVec13[(IOTA-iConst40)&2047];
|
||||
float fRec33 = (0 - (0.6f * fVec13[IOTA&2047]));
|
||||
fRec39[0] = ((fConst7 * (fRec7[1] + fRec7[2])) + (fConst6 * fRec39[1]));
|
||||
fRec38[0] = ((fSlow74 * (fRec7[1] + (fSlow73 * fRec39[0]))) + (fSlow72 * fRec38[1]));
|
||||
fVec14[IOTA&16383] = (1e-20f + (0.35355339059327373f * fRec38[0]));
|
||||
float fTemp11 = ((fVec14[(IOTA-iConst44)&16383] + (0.6f * fRec36[1])) - fTemp7);
|
||||
fVec15[IOTA&1023] = fTemp11;
|
||||
fRec36[0] = fVec15[(IOTA-iConst45)&1023];
|
||||
float fRec37 = (0 - (0.6f * fVec15[IOTA&1023]));
|
||||
fRec0[0] = (fRec12[1] + (fRec8[1] + (fRec16[1] + (fRec20[1] + (fRec24[1] + (fRec28[1] + (fRec32[1] + (fRec36[1] + (fRec37 + (fRec33 + (fRec29 + (fRec25 + fTemp6))))))))))));
|
||||
fRec1[0] = (0 - ((fRec24[1] + (fRec28[1] + (fRec32[1] + (fRec36[1] + (fRec37 + (fRec33 + (fRec25 + fRec29))))))) - (fRec12[1] + (fRec8[1] + (fRec16[1] + (fRec20[1] + fTemp6))))));
|
||||
float fTemp12 = (fRec17 + fRec21);
|
||||
fRec2[0] = (0 - ((fRec16[1] + (fRec20[1] + (fRec32[1] + (fRec36[1] + (fRec37 + (fRec33 + fTemp12)))))) - (fRec12[1] + (fRec8[1] + (fRec24[1] + (fRec28[1] + (fRec29 + (fRec25 + fTemp3))))))));
|
||||
fRec3[0] = (0 - ((fRec16[1] + (fRec20[1] + (fRec24[1] + (fRec28[1] + (fRec29 + (fRec25 + fTemp12)))))) - (fRec12[1] + (fRec8[1] + (fRec32[1] + (fRec36[1] + (fRec37 + (fRec33 + fTemp3))))))));
|
||||
float fTemp13 = (fRec13 + fRec17);
|
||||
float fTemp14 = (fRec9 + fRec21);
|
||||
fRec4[0] = (0 - ((fRec8[1] + (fRec20[1] + (fRec28[1] + (fRec36[1] + (fRec37 + (fRec29 + fTemp14)))))) - (fRec12[1] + (fRec16[1] + (fRec24[1] + (fRec32[1] + (fRec33 + (fRec25 + fTemp13))))))));
|
||||
fRec5[0] = (0 - ((fRec8[1] + (fRec20[1] + (fRec24[1] + (fRec32[1] + (fRec33 + (fRec25 + fTemp14)))))) - (fRec12[1] + (fRec16[1] + (fRec28[1] + (fRec36[1] + (fRec37 + (fRec29 + fTemp13))))))));
|
||||
float fTemp15 = (fRec13 + fRec21);
|
||||
float fTemp16 = (fRec9 + fRec17);
|
||||
fRec6[0] = (0 - ((fRec8[1] + (fRec16[1] + (fRec28[1] + (fRec32[1] + (fRec33 + (fRec29 + fTemp16)))))) - (fRec12[1] + (fRec20[1] + (fRec24[1] + (fRec36[1] + (fRec37 + (fRec25 + fTemp15))))))));
|
||||
fRec7[0] = (0 - ((fRec8[1] + (fRec16[1] + (fRec24[1] + (fRec36[1] + (fRec37 + (fRec25 + fTemp16)))))) - (fRec12[1] + (fRec20[1] + (fRec28[1] + (fRec32[1] + (fRec33 + (fRec29 + fTemp15))))))));
|
||||
|
||||
|
||||
float reverb0 = (float)(0.37f * (fRec1[0] + fRec2[0]));
|
||||
float reverb1 = (float)(0.37f * (fRec1[0] - fRec2[0]));
|
||||
|
||||
output0[i] = (input0[i] * (1-_dryWet)) + (reverb0 * _dryWet );
|
||||
output1[i] = (input1[i] * (1-_dryWet)) + (reverb1 * _dryWet );
|
||||
|
||||
// post processing
|
||||
fRec7[2] = fRec7[1];
|
||||
fRec7[1] = fRec7[0];
|
||||
fRec6[2] = fRec6[1];
|
||||
fRec6[1] = fRec6[0];
|
||||
fRec5[2] = fRec5[1];
|
||||
fRec5[1] = fRec5[0];
|
||||
fRec4[2] = fRec4[1];
|
||||
fRec4[1] = fRec4[0];
|
||||
fRec3[2] = fRec3[1];
|
||||
fRec3[1] = fRec3[0];
|
||||
fRec2[2] = fRec2[1];
|
||||
fRec2[1] = fRec2[0];
|
||||
fRec1[2] = fRec1[1];
|
||||
fRec1[1] = fRec1[0];
|
||||
fRec0[2] = fRec0[1];
|
||||
fRec0[1] = fRec0[0];
|
||||
fRec36[1] = fRec36[0];
|
||||
fRec38[1] = fRec38[0];
|
||||
fRec39[1] = fRec39[0];
|
||||
fRec32[1] = fRec32[0];
|
||||
fRec34[1] = fRec34[0];
|
||||
fRec35[1] = fRec35[0];
|
||||
fRec28[1] = fRec28[0];
|
||||
fRec30[1] = fRec30[0];
|
||||
fRec31[1] = fRec31[0];
|
||||
fRec24[1] = fRec24[0];
|
||||
fRec26[1] = fRec26[0];
|
||||
fRec27[1] = fRec27[0];
|
||||
fRec20[1] = fRec20[0];
|
||||
fRec22[1] = fRec22[0];
|
||||
fRec23[1] = fRec23[0];
|
||||
fRec16[1] = fRec16[0];
|
||||
fRec18[1] = fRec18[0];
|
||||
fRec19[1] = fRec19[0];
|
||||
fRec12[1] = fRec12[0];
|
||||
fRec14[1] = fRec14[0];
|
||||
fRec15[1] = fRec15[0];
|
||||
fRec8[1] = fRec8[0];
|
||||
IOTA = IOTA+1;
|
||||
fRec10[1] = fRec10[0];
|
||||
fRec11[1] = fRec11[0];
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
float _dryWet;
|
||||
float _rt60;
|
||||
int iConst0;
|
||||
float fConst1;
|
||||
float fConst2;
|
||||
float _damping;
|
||||
float fConst3;
|
||||
float fConst4;
|
||||
float fConst5;
|
||||
float fConst6;
|
||||
float fConst7;
|
||||
float fRec11[2];
|
||||
float fRec10[2];
|
||||
int IOTA;
|
||||
float fVec0[8192];
|
||||
float fConst8;
|
||||
int iConst9;
|
||||
float fVec1[2048];
|
||||
int iConst10;
|
||||
float fRec8[2];
|
||||
float fConst11;
|
||||
float fConst12;
|
||||
float fRec15[2];
|
||||
float fRec14[2];
|
||||
float fVec2[8192];
|
||||
float fConst13;
|
||||
int iConst14;
|
||||
float fVec3[1024];
|
||||
int iConst15;
|
||||
float fRec12[2];
|
||||
float fConst16;
|
||||
float fConst17;
|
||||
float fRec19[2];
|
||||
float fRec18[2];
|
||||
float fVec4[8192];
|
||||
float fConst18;
|
||||
int iConst19;
|
||||
float fVec5[2048];
|
||||
int iConst20;
|
||||
float fRec16[2];
|
||||
float fConst21;
|
||||
float fConst22;
|
||||
float fRec23[2];
|
||||
float fRec22[2];
|
||||
float fVec6[8192];
|
||||
float fConst23;
|
||||
int iConst24;
|
||||
float fVec7[1024];
|
||||
int iConst25;
|
||||
float fRec20[2];
|
||||
float fConst26;
|
||||
float fConst27;
|
||||
float fRec27[2];
|
||||
float fRec26[2];
|
||||
float fVec8[16384];
|
||||
float fConst28;
|
||||
int iConst29;
|
||||
float fVec9[2048];
|
||||
int iConst30;
|
||||
float fRec24[2];
|
||||
float fConst31;
|
||||
float fConst32;
|
||||
float fRec31[2];
|
||||
float fRec30[2];
|
||||
float fVec10[8192];
|
||||
float fConst33;
|
||||
int iConst34;
|
||||
float fVec11[2048];
|
||||
int iConst35;
|
||||
float fRec28[2];
|
||||
float fConst36;
|
||||
float fConst37;
|
||||
float fRec35[2];
|
||||
float fRec34[2];
|
||||
float fVec12[16384];
|
||||
float fConst38;
|
||||
int iConst39;
|
||||
float fVec13[2048];
|
||||
int iConst40;
|
||||
float fRec32[2];
|
||||
float fConst41;
|
||||
float fConst42;
|
||||
float fRec39[2];
|
||||
float fRec38[2];
|
||||
float fVec14[16384];
|
||||
float fConst43;
|
||||
int iConst44;
|
||||
float fVec15[1024];
|
||||
int iConst45;
|
||||
float fRec36[2];
|
||||
float fRec0[3];
|
||||
float fRec1[3];
|
||||
float fRec2[3];
|
||||
float fRec3[3];
|
||||
float fRec4[3];
|
||||
float fRec5[3];
|
||||
float fRec6[3];
|
||||
float fRec7[3];
|
||||
|
||||
/// Long nasty function setting initial values
|
||||
void init(int samplingFreq)
|
||||
{
|
||||
// wet by default!
|
||||
_dryWet = 1;
|
||||
|
||||
_rt60 = 5.0f;
|
||||
iConst0 = min(192000, max(1, samplingFreq));
|
||||
fConst1 = floorf((0.5f + (0.174713f * iConst0)));
|
||||
fConst2 = ((0 - (6.907755278982138f * fConst1)) / iConst0);
|
||||
_damping = 10000.f;
|
||||
fConst3 = (6.283185307179586f / float(iConst0));
|
||||
fConst4 = (1.0f / tanf((1256.6370614359173f / iConst0)));
|
||||
fConst5 = (1 + fConst4);
|
||||
fConst6 = (0 - ((1 - fConst4) / fConst5));
|
||||
fConst7 = (1.0f / fConst5);
|
||||
for (int i=0; i<2; i++) fRec11[i] = 0;
|
||||
for (int i=0; i<2; i++) fRec10[i] = 0;
|
||||
IOTA = 0;
|
||||
for (int i=0; i<8192; i++) fVec0[i] = 0;
|
||||
fConst8 = floorf((0.5f + (0.022904f * iConst0)));
|
||||
iConst9 = int((int((fConst1 - fConst8)) & 8191));
|
||||
for (int i=0; i<2048; i++) fVec1[i] = 0;
|
||||
iConst10 = int((int((fConst8 - 1)) & 2047));
|
||||
for (int i=0; i<2; i++) fRec8[i] = 0;
|
||||
fConst11 = floorf((0.5f + (0.153129f * iConst0)));
|
||||
fConst12 = ((0 - (6.907755278982138f * fConst11)) / iConst0);
|
||||
for (int i=0; i<2; i++) fRec15[i] = 0;
|
||||
for (int i=0; i<2; i++) fRec14[i] = 0;
|
||||
for (int i=0; i<8192; i++) fVec2[i] = 0;
|
||||
fConst13 = floorf((0.5f + (0.020346f * iConst0)));
|
||||
iConst14 = int((int((fConst11 - fConst13)) & 8191));
|
||||
for (int i=0; i<1024; i++) fVec3[i] = 0;
|
||||
iConst15 = int((int((fConst13 - 1)) & 1023));
|
||||
for (int i=0; i<2; i++) fRec12[i] = 0;
|
||||
fConst16 = floorf((0.5f + (0.127837f * iConst0)));
|
||||
fConst17 = ((0 - (6.907755278982138f * fConst16)) / iConst0);
|
||||
for (int i=0; i<2; i++) fRec19[i] = 0;
|
||||
for (int i=0; i<2; i++) fRec18[i] = 0;
|
||||
for (int i=0; i<8192; i++) fVec4[i] = 0;
|
||||
fConst18 = floorf((0.5f + (0.031604f * iConst0)));
|
||||
iConst19 = int((int((fConst16 - fConst18)) & 8191));
|
||||
for (int i=0; i<2048; i++) fVec5[i] = 0;
|
||||
iConst20 = int((int((fConst18 - 1)) & 2047));
|
||||
for (int i=0; i<2; i++) fRec16[i] = 0;
|
||||
fConst21 = floorf((0.5f + (0.125f * iConst0)));
|
||||
fConst22 = ((0 - (6.907755278982138f * fConst21)) / iConst0);
|
||||
for (int i=0; i<2; i++) fRec23[i] = 0;
|
||||
for (int i=0; i<2; i++) fRec22[i] = 0;
|
||||
for (int i=0; i<8192; i++) fVec6[i] = 0;
|
||||
fConst23 = floorf((0.5f + (0.013458f * iConst0)));
|
||||
iConst24 = int((int((fConst21 - fConst23)) & 8191));
|
||||
for (int i=0; i<1024; i++) fVec7[i] = 0;
|
||||
iConst25 = int((int((fConst23 - 1)) & 1023));
|
||||
for (int i=0; i<2; i++) fRec20[i] = 0;
|
||||
fConst26 = floorf((0.5f + (0.210389f * iConst0)));
|
||||
fConst27 = ((0 - (6.907755278982138f * fConst26)) / iConst0);
|
||||
for (int i=0; i<2; i++) fRec27[i] = 0;
|
||||
for (int i=0; i<2; i++) fRec26[i] = 0;
|
||||
for (int i=0; i<16384; i++) fVec8[i] = 0;
|
||||
fConst28 = floorf((0.5f + (0.024421f * iConst0)));
|
||||
iConst29 = int((int((fConst26 - fConst28)) & 16383));
|
||||
for (int i=0; i<2048; i++) fVec9[i] = 0;
|
||||
iConst30 = int((int((fConst28 - 1)) & 2047));
|
||||
for (int i=0; i<2; i++) fRec24[i] = 0;
|
||||
fConst31 = floorf((0.5f + (0.192303f * iConst0)));
|
||||
fConst32 = ((0 - (6.907755278982138f * fConst31)) / iConst0);
|
||||
for (int i=0; i<2; i++) fRec31[i] = 0;
|
||||
for (int i=0; i<2; i++) fRec30[i] = 0;
|
||||
for (int i=0; i<8192; i++) fVec10[i] = 0;
|
||||
fConst33 = floorf((0.5f + (0.029291f * iConst0)));
|
||||
iConst34 = int((int((fConst31 - fConst33)) & 8191));
|
||||
for (int i=0; i<2048; i++) fVec11[i] = 0;
|
||||
iConst35 = int((int((fConst33 - 1)) & 2047));
|
||||
for (int i=0; i<2; i++) fRec28[i] = 0;
|
||||
fConst36 = floorf((0.5f + (0.256891f * iConst0)));
|
||||
fConst37 = ((0 - (6.907755278982138f * fConst36)) / iConst0);
|
||||
for (int i=0; i<2; i++) fRec35[i] = 0;
|
||||
for (int i=0; i<2; i++) fRec34[i] = 0;
|
||||
for (int i=0; i<16384; i++) fVec12[i] = 0;
|
||||
fConst38 = floorf((0.5f + (0.027333f * iConst0)));
|
||||
iConst39 = int((int((fConst36 - fConst38)) & 16383));
|
||||
for (int i=0; i<2048; i++) fVec13[i] = 0;
|
||||
iConst40 = int((int((fConst38 - 1)) & 2047));
|
||||
for (int i=0; i<2; i++) fRec32[i] = 0;
|
||||
fConst41 = floorf((0.5f + (0.219991f * iConst0)));
|
||||
fConst42 = ((0 - (6.907755278982138f * fConst41)) / iConst0);
|
||||
for (int i=0; i<2; i++) fRec39[i] = 0;
|
||||
for (int i=0; i<2; i++) fRec38[i] = 0;
|
||||
for (int i=0; i<16384; i++) fVec14[i] = 0;
|
||||
fConst43 = floorf((0.5f + (0.019123f * iConst0)));
|
||||
iConst44 = int((int((fConst41 - fConst43)) & 16383));
|
||||
for (int i=0; i<1024; i++) fVec15[i] = 0;
|
||||
iConst45 = int((int((fConst43 - 1)) & 1023));
|
||||
for (int i=0; i<2; i++) fRec36[i] = 0;
|
||||
for (int i=0; i<3; i++) fRec0[i] = 0;
|
||||
for (int i=0; i<3; i++) fRec1[i] = 0;
|
||||
for (int i=0; i<3; i++) fRec2[i] = 0;
|
||||
for (int i=0; i<3; i++) fRec3[i] = 0;
|
||||
for (int i=0; i<3; i++) fRec4[i] = 0;
|
||||
for (int i=0; i<3; i++) fRec5[i] = 0;
|
||||
for (int i=0; i<3; i++) fRec6[i] = 0;
|
||||
for (int i=0; i<3; i++) fRec7[i] = 0;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // OPENAV_DSP_REVERB_H
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -22,84 +22,77 @@
|
|||
#include <cmath>
|
||||
|
||||
SidechainGain::SidechainGain(int rate) :
|
||||
/// initial control values
|
||||
controlThreshold(0.2),
|
||||
controlReduction(1),
|
||||
controlReleaseTime(0.5),
|
||||
|
||||
/// filter state init
|
||||
w(10.0f / (rate * 0.02)),
|
||||
a(0.07f),
|
||||
b(1.0f / (1.0f - a)),
|
||||
g1(0.0f),
|
||||
g2(0.0f),
|
||||
|
||||
|
||||
peakFrameCounter(0),
|
||||
peakCountDuration( rate / 4 ),
|
||||
currentTarget(0)
|
||||
/// initial control values
|
||||
controlThreshold(0.2),
|
||||
controlReduction(1),
|
||||
controlReleaseTime(0.5),
|
||||
|
||||
/// filter state init
|
||||
w(10.0f / (rate * 0.02)),
|
||||
a(0.07f),
|
||||
b(1.0f / (1.0f - a)),
|
||||
g1(0.0f),
|
||||
g2(0.0f),
|
||||
|
||||
|
||||
peakFrameCounter(0),
|
||||
peakCountDuration( rate / 4 ),
|
||||
currentTarget(0)
|
||||
{
|
||||
}
|
||||
|
||||
void SidechainGain::process(unsigned int n_samples, float** inputs, float** outputs)
|
||||
{
|
||||
/// audio inputs
|
||||
float* inL = inputs[0];
|
||||
float* inR = inputs[1];
|
||||
float* side = inputs[2];
|
||||
float* outL = outputs[0];
|
||||
float* outR = outputs[1];
|
||||
|
||||
/// control inputs
|
||||
float threshold = controlThreshold;
|
||||
float reduction = controlReduction;
|
||||
float releaseTime = controlReleaseTime;
|
||||
|
||||
|
||||
/// analyse sidechain input for peak
|
||||
float sum = 0.f;
|
||||
for( unsigned int i = 0; i < n_samples; i++ )
|
||||
{
|
||||
if ( *side > 0.000001 )
|
||||
sum += *side++;
|
||||
else
|
||||
sum += -*side++;
|
||||
}
|
||||
|
||||
currentTarget = 0.f;
|
||||
|
||||
/// check for peak level (offset to avoid "always on" peak)
|
||||
if ( sum / n_samples > threshold + 0.05 )
|
||||
{
|
||||
peakFrameCounter = peakCountDuration * releaseTime;
|
||||
currentTarget = 1.f - reduction;
|
||||
}
|
||||
else if ( peakFrameCounter < 0 )
|
||||
{
|
||||
currentTarget = 1.f;
|
||||
}
|
||||
else
|
||||
{
|
||||
currentTarget = 1.f - reduction;
|
||||
}
|
||||
|
||||
if ( currentTarget < 0.f )
|
||||
currentTarget = 0.f;
|
||||
|
||||
peakFrameCounter -= n_samples;
|
||||
|
||||
for( unsigned int i = 0; i < n_samples; i++ )
|
||||
{
|
||||
/// smoothing algo is a lowpass, to de-zip the fades
|
||||
/// x^^4 approximates linear volume increase for human ears
|
||||
g1 += w * ( pow ( currentTarget, 4.f ) - g1 - a * g2 - 1e-20f);
|
||||
g2 += w * (b * g1 - g2 + 1e-20f);
|
||||
float gain = g2;
|
||||
|
||||
*outL++ = *inL++ * gain;
|
||||
*outR++ = *inR++ * gain;
|
||||
}
|
||||
|
||||
/// update output value
|
||||
controlSidechainAmp = currentTarget;
|
||||
/// audio inputs
|
||||
float* inL = inputs[0];
|
||||
float* inR = inputs[1];
|
||||
float* side = inputs[2];
|
||||
float* outL = outputs[0];
|
||||
float* outR = outputs[1];
|
||||
|
||||
/// control inputs
|
||||
float threshold = controlThreshold;
|
||||
float reduction = controlReduction;
|
||||
float releaseTime = controlReleaseTime;
|
||||
|
||||
|
||||
/// analyse sidechain input for peak
|
||||
float sum = 0.f;
|
||||
for( unsigned int i = 0; i < n_samples; i++ ) {
|
||||
if ( *side > 0.000001 )
|
||||
sum += *side++;
|
||||
else
|
||||
sum += -*side++;
|
||||
}
|
||||
|
||||
currentTarget = 0.f;
|
||||
|
||||
/// check for peak level (offset to avoid "always on" peak)
|
||||
if ( sum / n_samples > threshold + 0.05 ) {
|
||||
peakFrameCounter = peakCountDuration * releaseTime;
|
||||
currentTarget = 1.f - reduction;
|
||||
} else if ( peakFrameCounter < 0 ) {
|
||||
currentTarget = 1.f;
|
||||
} else {
|
||||
currentTarget = 1.f - reduction;
|
||||
}
|
||||
|
||||
if ( currentTarget < 0.f )
|
||||
currentTarget = 0.f;
|
||||
|
||||
peakFrameCounter -= n_samples;
|
||||
|
||||
for( unsigned int i = 0; i < n_samples; i++ ) {
|
||||
/// smoothing algo is a lowpass, to de-zip the fades
|
||||
/// x^^4 approximates linear volume increase for human ears
|
||||
g1 += w * ( pow ( currentTarget, 4.f ) - g1 - a * g2 - 1e-20f);
|
||||
g2 += w * (b * g1 - g2 + 1e-20f);
|
||||
float gain = g2;
|
||||
|
||||
*outL++ = *inL++ * gain;
|
||||
*outR++ = *inR++ * gain;
|
||||
}
|
||||
|
||||
/// update output value
|
||||
controlSidechainAmp = currentTarget;
|
||||
}
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -25,42 +25,51 @@
|
|||
|
||||
class SidechainGain
|
||||
{
|
||||
public:
|
||||
SidechainGain(int rate);
|
||||
~SidechainGain(){}
|
||||
|
||||
void threshold(float t){controlThreshold = t;}
|
||||
void reduction(float r){controlReduction = r;}
|
||||
void time (float t){controlReleaseTime = t;}
|
||||
|
||||
void process(unsigned int n_samples, float** inputs, float** outputs);
|
||||
|
||||
private:
|
||||
/// audio buffers
|
||||
float* audioInputL;
|
||||
float* audioInputR;
|
||||
float* audioSidechain;
|
||||
float* audioOutputL;
|
||||
float* audioOutputR;
|
||||
|
||||
/// control signals
|
||||
float controlThreshold;
|
||||
float controlReduction;
|
||||
float controlReleaseTime;
|
||||
float controlSidechainAmp;
|
||||
|
||||
/// filter state
|
||||
float w, a, b, g1, g2;
|
||||
|
||||
/// last peak history
|
||||
bool nowIsAPeak;
|
||||
long peakFrameCounter;
|
||||
|
||||
/// nframes available for countdown
|
||||
long peakCountDuration;
|
||||
|
||||
/// control output
|
||||
float currentTarget;
|
||||
public:
|
||||
SidechainGain(int rate);
|
||||
~SidechainGain() {}
|
||||
|
||||
void threshold(float t)
|
||||
{
|
||||
controlThreshold = t;
|
||||
}
|
||||
void reduction(float r)
|
||||
{
|
||||
controlReduction = r;
|
||||
}
|
||||
void time (float t)
|
||||
{
|
||||
controlReleaseTime = t;
|
||||
}
|
||||
|
||||
void process(unsigned int n_samples, float** inputs, float** outputs);
|
||||
|
||||
private:
|
||||
/// audio buffers
|
||||
float* audioInputL;
|
||||
float* audioInputR;
|
||||
float* audioSidechain;
|
||||
float* audioOutputL;
|
||||
float* audioOutputR;
|
||||
|
||||
/// control signals
|
||||
float controlThreshold;
|
||||
float controlReduction;
|
||||
float controlReleaseTime;
|
||||
float controlSidechainAmp;
|
||||
|
||||
/// filter state
|
||||
float w, a, b, g1, g2;
|
||||
|
||||
/// last peak history
|
||||
bool nowIsAPeak;
|
||||
long peakFrameCounter;
|
||||
|
||||
/// nframes available for countdown
|
||||
long peakCountDuration;
|
||||
|
||||
/// control output
|
||||
float currentTarget;
|
||||
};
|
||||
|
||||
#endif // OPENAV_DSP_SIDECHAIN_GAIN_H
|
||||
|
|
114
src/event.cxx
114
src/event.cxx
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -42,46 +42,78 @@ const char* EventGridLaunchScene::prettyName = "grid:launch_scene";
|
|||
|
||||
EVENT_TYPE Event::getTypeFromName(const char* name)
|
||||
{
|
||||
for(int i = 0; i < EVENT_TYPE_FINAL; i++)
|
||||
{
|
||||
const char* tmp = getPrettyName(i);
|
||||
if ( tmp )
|
||||
{
|
||||
if ( strcmp( name, tmp ) == 0 ) {
|
||||
return (EVENT_TYPE)i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return EVENT_NULL;
|
||||
for(int i = 0; i < EVENT_TYPE_FINAL; i++) {
|
||||
const char* tmp = getPrettyName(i);
|
||||
if ( tmp ) {
|
||||
if ( strcmp( name, tmp ) == 0 ) {
|
||||
return (EVENT_TYPE)i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return EVENT_NULL;
|
||||
}
|
||||
|
||||
const char* Event::getPrettyName( int type )
|
||||
{
|
||||
switch ( type )
|
||||
{
|
||||
case MASTER_VOL:{ return EventMasterVol::prettyName; }
|
||||
case MASTER_RETURN:{ return EventMasterReturn::prettyName; }
|
||||
case MASTER_INPUT_VOL:{ return EventMasterInputVol::prettyName; }
|
||||
case MASTER_INPUT_TO:{ return EventMasterInputTo::prettyName; }
|
||||
case MASTER_INPUT_TO_ACTIVE:{ return EventMasterInputToActive::prettyName; }
|
||||
|
||||
case TRACK_VOLUME:{ return EventTrackVol::prettyName; }
|
||||
case TRACK_SEND:{ return EventTrackSend::prettyName; }
|
||||
case TRACK_SEND_ACTIVE:{ return EventTrackSendActive::prettyName; }
|
||||
case TRACK_JACKSEND:{ return EventTrackJackSend::prettyName; }
|
||||
case TRACK_JACKSEND_ACTIVATE:{ return EventTrackJackSendActivate::prettyName; }
|
||||
case TRACK_RECORD_ARM:{ return EventTrackRecordArm::prettyName; }
|
||||
|
||||
case TIME_BPM:{ return EventTimeBPM::prettyName; }
|
||||
case TIME_TEMPO_TAP:{ return EventTimeTempoTap::prettyName; }
|
||||
|
||||
case GRID_EVENT:{ return EventGridEvent::prettyName; }
|
||||
case GRID_LAUNCH_SCENE:{ return EventGridLaunchScene::prettyName; }
|
||||
|
||||
case METRONOME_ACTIVE:{ return EventMetronomeActive::prettyName; }
|
||||
case METRONOME_VOLUME:{ return EventMetronomeVolume::prettyName; }
|
||||
|
||||
default: return 0;
|
||||
}
|
||||
switch ( type ) {
|
||||
case MASTER_VOL: {
|
||||
return EventMasterVol::prettyName;
|
||||
}
|
||||
case MASTER_RETURN: {
|
||||
return EventMasterReturn::prettyName;
|
||||
}
|
||||
case MASTER_INPUT_VOL: {
|
||||
return EventMasterInputVol::prettyName;
|
||||
}
|
||||
case MASTER_INPUT_TO: {
|
||||
return EventMasterInputTo::prettyName;
|
||||
}
|
||||
case MASTER_INPUT_TO_ACTIVE: {
|
||||
return EventMasterInputToActive::prettyName;
|
||||
}
|
||||
|
||||
case TRACK_VOLUME: {
|
||||
return EventTrackVol::prettyName;
|
||||
}
|
||||
case TRACK_SEND: {
|
||||
return EventTrackSend::prettyName;
|
||||
}
|
||||
case TRACK_SEND_ACTIVE: {
|
||||
return EventTrackSendActive::prettyName;
|
||||
}
|
||||
case TRACK_JACKSEND: {
|
||||
return EventTrackJackSend::prettyName;
|
||||
}
|
||||
case TRACK_JACKSEND_ACTIVATE: {
|
||||
return EventTrackJackSendActivate::prettyName;
|
||||
}
|
||||
case TRACK_RECORD_ARM: {
|
||||
return EventTrackRecordArm::prettyName;
|
||||
}
|
||||
|
||||
case TIME_BPM: {
|
||||
return EventTimeBPM::prettyName;
|
||||
}
|
||||
case TIME_TEMPO_TAP: {
|
||||
return EventTimeTempoTap::prettyName;
|
||||
}
|
||||
|
||||
case GRID_EVENT: {
|
||||
return EventGridEvent::prettyName;
|
||||
}
|
||||
case GRID_LAUNCH_SCENE: {
|
||||
return EventGridLaunchScene::prettyName;
|
||||
}
|
||||
|
||||
case METRONOME_ACTIVE: {
|
||||
return EventMetronomeActive::prettyName;
|
||||
}
|
||||
case METRONOME_VOLUME: {
|
||||
return EventMetronomeVolume::prettyName;
|
||||
}
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
1435
src/event.hxx
1435
src/event.hxx
File diff suppressed because it is too large
Load diff
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -44,394 +44,447 @@ extern Jack* jack;
|
|||
|
||||
void handleDspEvents()
|
||||
{
|
||||
uint availableRead = jack_ringbuffer_read_space( rbToDsp );
|
||||
|
||||
while ( availableRead >= sizeof(EventBase) )
|
||||
{
|
||||
jack_ringbuffer_peek( rbToDsp, (char*)processDspMem, sizeof(EventBase) );
|
||||
|
||||
EventBase* e = (EventBase*)processDspMem;
|
||||
|
||||
// recheck the size against the actual event size
|
||||
if ( availableRead >= e->size() )
|
||||
{
|
||||
|
||||
// MIDI binding creation: sample the Event.
|
||||
if( jack->bindingEventRecordEnable )
|
||||
{
|
||||
//printf("event %i\n", e->type() );
|
||||
jack->bindingEventType = e->type();
|
||||
|
||||
const char* target = e->name();
|
||||
if ( target )
|
||||
{
|
||||
EventControllerBindingTarget event( target );
|
||||
writeToGuiRingbuffer( &event );
|
||||
}
|
||||
}
|
||||
|
||||
switch ( e->type() )
|
||||
{
|
||||
case Event::QUIT: {
|
||||
if ( availableRead >= sizeof(EventQuit) ) {
|
||||
EventQuit ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventQuit) );
|
||||
jack->quit();
|
||||
// we want to *quit* *fast*: remaining events don't matter!
|
||||
return;
|
||||
|
||||
} break; }
|
||||
|
||||
|
||||
// ======== TRANSPORT ==
|
||||
case Event::TRANSPORT: {
|
||||
if ( availableRead >= sizeof(EventTransportState) ) {
|
||||
EventTransportState ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventTransportState) );
|
||||
jack->getTimeManager()->setTransportState( ev.ts );
|
||||
} break; }
|
||||
|
||||
// ========= SAVE =====
|
||||
case Event::STATE_SAVE: {
|
||||
if ( availableRead >= sizeof(EventStateSave) ) {
|
||||
EventStateSave ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventStateSave) );
|
||||
jack->getState()->save();
|
||||
} break; }
|
||||
case Event::STATE_RESET: {
|
||||
if ( availableRead >= sizeof(EventStateReset) ) {
|
||||
EventStateReset ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventStateReset) );
|
||||
jack->getState()->reset();
|
||||
} break; }
|
||||
case Event::STATE_SAVE_BUFFER: {
|
||||
if ( availableRead >= sizeof(EventStateReset) ) {
|
||||
EventStateSaveBuffer ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventStateSaveBuffer) );
|
||||
printf("jack got save buffer in %d, %d\n", ev.track, ev.scene);
|
||||
LooperClip* lc = jack->getLooper(ev.track)->getClip(ev.scene);
|
||||
if(!lc) break;
|
||||
EventStateSaveBuffer e;
|
||||
e.track = ev.track;
|
||||
e.scene = ev.scene;
|
||||
e.ab = lc->getAudioBuffer();
|
||||
e.no_dealloc = 1;
|
||||
writeToGuiRingbuffer( &e );
|
||||
} break; }
|
||||
|
||||
// ========= MASTER ===
|
||||
case Event::MASTER_VOL: {
|
||||
if ( availableRead >= sizeof(EventMasterVol) ) {
|
||||
EventMasterVol ev(0);
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventMasterVol) );
|
||||
jack->masterVolume( ev.vol );
|
||||
} break; }
|
||||
case Event::MASTER_RETURN: {
|
||||
if ( availableRead >= sizeof(EventMasterReturn) ) {
|
||||
EventMasterReturn ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventMasterReturn) );
|
||||
if ( ev.ret == RETURN_MAIN ) {
|
||||
jack->returnVolume( ev.vol );
|
||||
}
|
||||
} break; }
|
||||
case Event::MASTER_INPUT_VOL: {
|
||||
if ( availableRead >= sizeof(EventMasterVol) ) {
|
||||
EventMasterVol ev(0);
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventMasterVol) );
|
||||
jack->getLogic()->masterInputVol( ev.vol );
|
||||
} break; }
|
||||
case Event::MASTER_INPUT_TO: {
|
||||
if ( availableRead >= sizeof(EventMasterInputTo) ) {
|
||||
EventMasterInputTo ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventMasterInputTo) );
|
||||
jack->bindingSend = ev.place;
|
||||
jack->getLogic()->masterInputTo( ev.place, ev.value );
|
||||
} break; }
|
||||
case Event::MASTER_INPUT_TO_ACTIVE: {
|
||||
if ( availableRead >= sizeof(EventMasterInputToActive) ) {
|
||||
EventMasterInputToActive ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventMasterInputToActive) );
|
||||
jack->bindingSend = ev.place;
|
||||
jack->bindingActive = ev.active;
|
||||
jack->getLogic()->masterInputToActive( ev.place, ev.active );
|
||||
} break; }
|
||||
|
||||
// ========= GRID =====
|
||||
case Event::GRID_STATE: {
|
||||
if ( availableRead >= sizeof(EventGridState) ) {
|
||||
EventGridState ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventGridState) );
|
||||
// clear clips in Controllers
|
||||
if ( ev.state == GridLogic::STATE_EMPTY )
|
||||
{
|
||||
jack->getLooper( ev.track )->getClip( ev.scene )->init();
|
||||
jack->getControllerUpdater()->setTrackSceneProgress(ev.track, ev.scene, 0 );
|
||||
jack->getControllerUpdater()->setSceneState( ev.track, ev.scene, GridLogic::STATE_EMPTY );
|
||||
}
|
||||
} break; }
|
||||
|
||||
case Event::GRID_EVENT: {
|
||||
if ( availableRead >= sizeof(EventGridEvent) ) {
|
||||
EventGridEvent ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventGridEvent) );
|
||||
jack->bindingTrack = ev.track;
|
||||
jack->bindingScene = ev.scene;
|
||||
if ( ev.pressed )
|
||||
jack->getGridLogic()->pressed( ev.track, ev.scene );
|
||||
else
|
||||
jack->getGridLogic()->released( ev.track, ev.scene );
|
||||
} break; }
|
||||
|
||||
case Event::GRID_LAUNCH_SCENE: {
|
||||
EventGridLaunchScene ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventGridLaunchScene) );
|
||||
jack->getGridLogic()->launchScene( ev.scene );
|
||||
jack->bindingScene = ev.scene;
|
||||
break; }
|
||||
|
||||
case Event::GRID_SELECT_CLIP_ENABLE: {
|
||||
EventGridSelectClipEnable ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventGridSelectClipEnable) );
|
||||
jack->getGridLogic()->setSelectTrackScene( ev.enable );
|
||||
break; }
|
||||
case Event::GRID_SELECT_CLIP_EVENT: {
|
||||
EventGridSelectClipEvent ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventGridSelectClipEvent) );
|
||||
jack->getGridLogic()->selectedTrackSceneEvent( ev.pressed );
|
||||
break; }
|
||||
|
||||
case Event::GRID_SELECT_NEW_CHOSEN: {
|
||||
EventGridSelectNewChosen ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventGridSelectNewChosen) );
|
||||
jack->getGridLogic()->specialScene( ev.track, ev.scene );
|
||||
break; }
|
||||
|
||||
|
||||
case Event::LOOPER_LOAD: {
|
||||
if ( availableRead >= sizeof(EventLooperLoad) ) {
|
||||
EventLooperLoad ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventLooperLoad) );
|
||||
jack->getGridLogic()->load( ev.track, ev.clip, (AudioBuffer*)ev.audioBuffer );
|
||||
} break; }
|
||||
case Event::METRONOME_ACTIVE: {
|
||||
if ( availableRead >= sizeof(EventMetronomeActive) ) {
|
||||
EventMetronomeActive ev(false);
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventMetronomeActive) );
|
||||
jack->getLogic()->metronomeEnable(ev.active);
|
||||
} break; }
|
||||
case Event::METRONOME_VOLUME: {
|
||||
if ( availableRead >= sizeof(EventMetronomeVolume) ) {
|
||||
EventMetronomeVolume ev(false);
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventMetronomeVolume) );
|
||||
LUPPP_NOTE("EventDSP: MetroVol %f", ev.vol );
|
||||
jack->getMetronome()->setVolume(ev.vol);
|
||||
} break; }
|
||||
case Event::LOOPER_STATE: {
|
||||
if ( availableRead >= sizeof(EventLooperState) ) {
|
||||
EventLooperState ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventLooperState) );
|
||||
//jack->setLooperState( ev.track, ev.scene, ev.state );
|
||||
} break; }
|
||||
case Event::LOOPER_LOOP_LENGTH: {
|
||||
if ( availableRead >= sizeof(EventLooperLoopLength) ) {
|
||||
EventLooperLoopLength ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventLooperLoopLength) );
|
||||
jack->getLogic()->looperClipLenght( ev.track, ev.scene, ev.beats );
|
||||
} break; }
|
||||
|
||||
|
||||
case Event::LOOPER_LOOP_USE_AS_TEMPO: {
|
||||
if ( availableRead >= sizeof(EventLooperUseAsTempo) ) {
|
||||
EventLooperUseAsTempo ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventLooperUseAsTempo) );
|
||||
jack->getLogic()->looperUseAsTempo( ev.track, ev.scene );
|
||||
} break; }
|
||||
|
||||
|
||||
|
||||
case Event::TIME_BPM: {
|
||||
if ( availableRead >= sizeof(EventTimeBPM) ) {
|
||||
EventTimeBPM ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventTimeBPM) );
|
||||
jack->getTimeManager()->setBpm(ev.bpm);
|
||||
} break; }
|
||||
case Event::TIME_TEMPO_TAP: {
|
||||
if ( availableRead >= sizeof(EventTimeTempoTap) ) {
|
||||
EventTimeTempoTap ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventTimeTempoTap) );
|
||||
jack->getTimeManager()->tap();
|
||||
} break; }
|
||||
|
||||
// ======== FX ===========
|
||||
|
||||
case Event::FX_REVERB: break;
|
||||
/*{
|
||||
if ( availableRead >= sizeof(EventFxReverb) ) {
|
||||
EventFxReverb ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventFxReverb) );
|
||||
// TODO implement reverb
|
||||
break; }
|
||||
}
|
||||
*/
|
||||
case Event::TRACK_VOLUME: {
|
||||
if ( availableRead >= sizeof(EventTrackVol) ) {
|
||||
EventTrackVol ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventTrackVol) );
|
||||
jack->getLogic()->trackVolume( ev.track, ev.vol );
|
||||
jack->bindingTrack = ev.track;
|
||||
break; }
|
||||
}
|
||||
|
||||
case Event::TRACK_RECORD_ARM: {
|
||||
if ( availableRead >= sizeof(EventTrackRecordArm) ) {
|
||||
EventTrackRecordArm ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventTrackRecordArm) );
|
||||
jack->getLogic()->trackRecordArm( ev.track, ev.recordArm );
|
||||
jack->bindingTrack = ev.track;
|
||||
jack->bindingActive = ev.recordArm;
|
||||
break; }
|
||||
}
|
||||
|
||||
case Event::TRACK_SEND_ACTIVE: {
|
||||
if ( availableRead >= sizeof(EventTrackSendActive) ) {
|
||||
EventTrackSendActive ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventTrackSendActive) );
|
||||
jack->getLogic()->trackSendActive( ev.track, ev.send, ev.active );
|
||||
jack->bindingTrack = ev.track;
|
||||
jack->bindingSend = ev.send;
|
||||
jack->bindingActive = ev.active;
|
||||
} break; }
|
||||
uint availableRead = jack_ringbuffer_read_space( rbToDsp );
|
||||
|
||||
case Event::TRACK_JACKSEND_ACTIVATE: {
|
||||
if ( availableRead >= sizeof(EventTrackJackSendActivate) ) {
|
||||
EventTrackJackSendActivate ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventTrackJackSendActivate) );
|
||||
jack->getLogic()->trackJackSendActivate(ev.track,ev.active);
|
||||
jack->bindingTrack = ev.track;
|
||||
while ( availableRead >= sizeof(EventBase) ) {
|
||||
jack_ringbuffer_peek( rbToDsp, (char*)processDspMem, sizeof(EventBase) );
|
||||
|
||||
jack->bindingActive = ev.active;
|
||||
} break; }
|
||||
EventBase* e = (EventBase*)processDspMem;
|
||||
|
||||
case Event::TRACK_JACKSEND: {
|
||||
if ( availableRead >= sizeof(EventTrackJackSend) ) {
|
||||
EventTrackJackSend ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventTrackJackSend) );
|
||||
jack->getLogic()->trackJackSend(ev.track,ev.value);
|
||||
jack->bindingTrack = ev.track;
|
||||
} break; }
|
||||
|
||||
case Event::TRACK_SEND: {
|
||||
if ( availableRead >= sizeof(EventTrackSend) ) {
|
||||
EventTrackSend ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventTrackSend) );
|
||||
jack->getLogic()->trackSend( ev.track, ev.send, ev.value );
|
||||
jack->bindingTrack = ev.track;
|
||||
jack->bindingSend = ev.send;
|
||||
} break; }
|
||||
|
||||
|
||||
// ========= LUPPP INTERNAL =====
|
||||
case Event::LOOPER_REQUEST_BUFFER: {
|
||||
if ( availableRead >= sizeof(EventLooperClipRequestBuffer) ) {
|
||||
EventLooperClipRequestBuffer ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventLooperClipRequestBuffer) );
|
||||
jack->getLooper( ev.track )->setRequestedBuffer( ev.scene, ev.ab );
|
||||
} break; }
|
||||
|
||||
case Event::REQUEST_SAVE_BUFFER: {
|
||||
if ( availableRead >= sizeof(EventRequestSaveBuffer) ) {
|
||||
EventRequestSaveBuffer ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventRequestSaveBuffer) );
|
||||
jack->getLooper( ev.track )->getClip(ev.scene)->recieveSaveBuffer( ev.ab );
|
||||
} break; }
|
||||
|
||||
case Event::CONTROLLER_INSTANCE: {
|
||||
if ( availableRead >= sizeof(EventControllerInstance) ) {
|
||||
EventControllerInstance ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventControllerInstance) );
|
||||
jack->getControllerUpdater()->registerController( static_cast<Controller*>(ev.controller) );
|
||||
} break; }
|
||||
|
||||
case Event::CONTROLLER_INSTANCE_REMOVE: {
|
||||
if ( availableRead >= sizeof(EventControllerInstanceRemove) ) {
|
||||
EventControllerInstanceRemove ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventControllerInstanceRemove) );
|
||||
|
||||
jack->getControllerUpdater()->removeController( ev.ID );
|
||||
} break; }
|
||||
|
||||
case Event::CONTROLLER_BINDING_ENABLE: {
|
||||
if ( availableRead >= sizeof(EventControllerBindingEnable) ) {
|
||||
EventControllerBindingEnable ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventControllerBindingEnable) );
|
||||
jack->bindingEventRecordEnable = ev.enable;
|
||||
} break; }
|
||||
|
||||
|
||||
case Event::CONTROLLER_BINDING_REMOVE: {
|
||||
if ( availableRead >= sizeof(EventControllerBindingRemove) ) {
|
||||
EventControllerBindingRemove ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventControllerBindingRemove) );
|
||||
// get Controller* from controllerID
|
||||
Controller* c =jack->getControllerUpdater()->getController(ev.controllerID);
|
||||
// dynamic cast to check for GenericMIDI controller
|
||||
GenericMIDI* g = dynamic_cast<GenericMIDI*>(c);
|
||||
if ( g )
|
||||
{
|
||||
// kick out BindingID
|
||||
g->removeBinding( ev.bindingID );
|
||||
}
|
||||
else
|
||||
{
|
||||
// GUI print notify of error removing binding
|
||||
}
|
||||
} break; }
|
||||
|
||||
case Event::CONTROLLER_INSTANCE_GET_TO_WRITE: {
|
||||
if ( availableRead >= sizeof(EventControllerInstanceGetToWrite) ) {
|
||||
EventControllerInstanceGetToWrite ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventControllerInstanceGetToWrite) );
|
||||
|
||||
// get the corresponding Controller with ID, and return it
|
||||
|
||||
Controller* c = jack->getControllerUpdater()->getController( ev.ID );
|
||||
|
||||
cout << "controller instance get to write id " << ev.ID << endl;
|
||||
|
||||
EventControllerInstanceGetToWrite tmp( ev.ID, c );
|
||||
writeToGuiRingbuffer( &tmp );
|
||||
} break; }
|
||||
|
||||
default:
|
||||
{
|
||||
cout << "DSP: Unkown message!! Will clog ringbuffer" << endl;
|
||||
// just do nothing
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// next call will get the half-written event
|
||||
return;
|
||||
}
|
||||
|
||||
// update available read, and loop over events
|
||||
availableRead = jack_ringbuffer_read_space( rbToDsp );
|
||||
}
|
||||
// recheck the size against the actual event size
|
||||
if ( availableRead >= e->size() ) {
|
||||
|
||||
// MIDI binding creation: sample the Event.
|
||||
if( jack->bindingEventRecordEnable ) {
|
||||
//printf("event %i\n", e->type() );
|
||||
jack->bindingEventType = e->type();
|
||||
|
||||
const char* target = e->name();
|
||||
if ( target ) {
|
||||
EventControllerBindingTarget event( target );
|
||||
writeToGuiRingbuffer( &event );
|
||||
}
|
||||
}
|
||||
|
||||
switch ( e->type() ) {
|
||||
case Event::QUIT: {
|
||||
if ( availableRead >= sizeof(EventQuit) ) {
|
||||
EventQuit ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventQuit) );
|
||||
jack->quit();
|
||||
// we want to *quit* *fast*: remaining events don't matter!
|
||||
return;
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// ======== TRANSPORT ==
|
||||
case Event::TRANSPORT: {
|
||||
if ( availableRead >= sizeof(EventTransportState) ) {
|
||||
EventTransportState ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventTransportState) );
|
||||
jack->getTimeManager()->setTransportState( ev.ts );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// ========= SAVE =====
|
||||
case Event::STATE_SAVE: {
|
||||
if ( availableRead >= sizeof(EventStateSave) ) {
|
||||
EventStateSave ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventStateSave) );
|
||||
jack->getState()->save();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Event::STATE_RESET: {
|
||||
if ( availableRead >= sizeof(EventStateReset) ) {
|
||||
EventStateReset ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventStateReset) );
|
||||
jack->getState()->reset();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Event::STATE_SAVE_BUFFER: {
|
||||
if ( availableRead >= sizeof(EventStateReset) ) {
|
||||
EventStateSaveBuffer ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventStateSaveBuffer) );
|
||||
printf("jack got save buffer in %d, %d\n", ev.track, ev.scene);
|
||||
LooperClip* lc = jack->getLooper(ev.track)->getClip(ev.scene);
|
||||
if(!lc) break;
|
||||
EventStateSaveBuffer e;
|
||||
e.track = ev.track;
|
||||
e.scene = ev.scene;
|
||||
e.ab = lc->getAudioBuffer();
|
||||
e.no_dealloc = 1;
|
||||
writeToGuiRingbuffer( &e );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// ========= MASTER ===
|
||||
case Event::MASTER_VOL: {
|
||||
if ( availableRead >= sizeof(EventMasterVol) ) {
|
||||
EventMasterVol ev(0);
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventMasterVol) );
|
||||
jack->masterVolume( ev.vol );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Event::MASTER_RETURN: {
|
||||
if ( availableRead >= sizeof(EventMasterReturn) ) {
|
||||
EventMasterReturn ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventMasterReturn) );
|
||||
if ( ev.ret == RETURN_MAIN ) {
|
||||
jack->returnVolume( ev.vol );
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Event::MASTER_INPUT_VOL: {
|
||||
if ( availableRead >= sizeof(EventMasterVol) ) {
|
||||
EventMasterVol ev(0);
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventMasterVol) );
|
||||
jack->getLogic()->masterInputVol( ev.vol );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Event::MASTER_INPUT_TO: {
|
||||
if ( availableRead >= sizeof(EventMasterInputTo) ) {
|
||||
EventMasterInputTo ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventMasterInputTo) );
|
||||
jack->bindingSend = ev.place;
|
||||
jack->getLogic()->masterInputTo( ev.place, ev.value );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Event::MASTER_INPUT_TO_ACTIVE: {
|
||||
if ( availableRead >= sizeof(EventMasterInputToActive) ) {
|
||||
EventMasterInputToActive ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventMasterInputToActive) );
|
||||
jack->bindingSend = ev.place;
|
||||
jack->bindingActive = ev.active;
|
||||
jack->getLogic()->masterInputToActive( ev.place, ev.active );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// ========= GRID =====
|
||||
case Event::GRID_STATE: {
|
||||
if ( availableRead >= sizeof(EventGridState) ) {
|
||||
EventGridState ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventGridState) );
|
||||
// clear clips in Controllers
|
||||
if ( ev.state == GridLogic::STATE_EMPTY ) {
|
||||
jack->getLooper( ev.track )->getClip( ev.scene )->init();
|
||||
jack->getControllerUpdater()->setTrackSceneProgress(ev.track, ev.scene, 0 );
|
||||
jack->getControllerUpdater()->setSceneState( ev.track, ev.scene, GridLogic::STATE_EMPTY );
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Event::GRID_EVENT: {
|
||||
if ( availableRead >= sizeof(EventGridEvent) ) {
|
||||
EventGridEvent ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventGridEvent) );
|
||||
jack->bindingTrack = ev.track;
|
||||
jack->bindingScene = ev.scene;
|
||||
if ( ev.pressed )
|
||||
jack->getGridLogic()->pressed( ev.track, ev.scene );
|
||||
else
|
||||
jack->getGridLogic()->released( ev.track, ev.scene );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Event::GRID_LAUNCH_SCENE: {
|
||||
EventGridLaunchScene ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventGridLaunchScene) );
|
||||
jack->getGridLogic()->launchScene( ev.scene );
|
||||
jack->bindingScene = ev.scene;
|
||||
break;
|
||||
}
|
||||
|
||||
case Event::GRID_SELECT_CLIP_ENABLE: {
|
||||
EventGridSelectClipEnable ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventGridSelectClipEnable) );
|
||||
jack->getGridLogic()->setSelectTrackScene( ev.enable );
|
||||
break;
|
||||
}
|
||||
case Event::GRID_SELECT_CLIP_EVENT: {
|
||||
EventGridSelectClipEvent ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventGridSelectClipEvent) );
|
||||
jack->getGridLogic()->selectedTrackSceneEvent( ev.pressed );
|
||||
break;
|
||||
}
|
||||
|
||||
case Event::GRID_SELECT_NEW_CHOSEN: {
|
||||
EventGridSelectNewChosen ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventGridSelectNewChosen) );
|
||||
jack->getGridLogic()->specialScene( ev.track, ev.scene );
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case Event::LOOPER_LOAD: {
|
||||
if ( availableRead >= sizeof(EventLooperLoad) ) {
|
||||
EventLooperLoad ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventLooperLoad) );
|
||||
jack->getGridLogic()->load( ev.track, ev.clip, (AudioBuffer*)ev.audioBuffer );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Event::METRONOME_ACTIVE: {
|
||||
if ( availableRead >= sizeof(EventMetronomeActive) ) {
|
||||
EventMetronomeActive ev(false);
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventMetronomeActive) );
|
||||
jack->getLogic()->metronomeEnable(ev.active);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Event::METRONOME_VOLUME: {
|
||||
if ( availableRead >= sizeof(EventMetronomeVolume) ) {
|
||||
EventMetronomeVolume ev(false);
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventMetronomeVolume) );
|
||||
LUPPP_NOTE("EventDSP: MetroVol %f", ev.vol );
|
||||
jack->getMetronome()->setVolume(ev.vol);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Event::LOOPER_STATE: {
|
||||
if ( availableRead >= sizeof(EventLooperState) ) {
|
||||
EventLooperState ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventLooperState) );
|
||||
//jack->setLooperState( ev.track, ev.scene, ev.state );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Event::LOOPER_LOOP_LENGTH: {
|
||||
if ( availableRead >= sizeof(EventLooperLoopLength) ) {
|
||||
EventLooperLoopLength ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventLooperLoopLength) );
|
||||
jack->getLogic()->looperClipLenght( ev.track, ev.scene, ev.beats );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case Event::LOOPER_LOOP_USE_AS_TEMPO: {
|
||||
if ( availableRead >= sizeof(EventLooperUseAsTempo) ) {
|
||||
EventLooperUseAsTempo ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventLooperUseAsTempo) );
|
||||
jack->getLogic()->looperUseAsTempo( ev.track, ev.scene );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
|
||||
case Event::TIME_BPM: {
|
||||
if ( availableRead >= sizeof(EventTimeBPM) ) {
|
||||
EventTimeBPM ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventTimeBPM) );
|
||||
jack->getTimeManager()->setBpm(ev.bpm);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Event::TIME_TEMPO_TAP: {
|
||||
if ( availableRead >= sizeof(EventTimeTempoTap) ) {
|
||||
EventTimeTempoTap ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventTimeTempoTap) );
|
||||
jack->getTimeManager()->tap();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// ======== FX ===========
|
||||
|
||||
case Event::FX_REVERB:
|
||||
break;
|
||||
/*{
|
||||
if ( availableRead >= sizeof(EventFxReverb) ) {
|
||||
EventFxReverb ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventFxReverb) );
|
||||
// TODO implement reverb
|
||||
break; }
|
||||
}
|
||||
*/
|
||||
case Event::TRACK_VOLUME: {
|
||||
if ( availableRead >= sizeof(EventTrackVol) ) {
|
||||
EventTrackVol ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventTrackVol) );
|
||||
jack->getLogic()->trackVolume( ev.track, ev.vol );
|
||||
jack->bindingTrack = ev.track;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
case Event::TRACK_RECORD_ARM: {
|
||||
if ( availableRead >= sizeof(EventTrackRecordArm) ) {
|
||||
EventTrackRecordArm ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventTrackRecordArm) );
|
||||
jack->getLogic()->trackRecordArm( ev.track, ev.recordArm );
|
||||
jack->bindingTrack = ev.track;
|
||||
jack->bindingActive = ev.recordArm;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
case Event::TRACK_SEND_ACTIVE: {
|
||||
if ( availableRead >= sizeof(EventTrackSendActive) ) {
|
||||
EventTrackSendActive ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventTrackSendActive) );
|
||||
jack->getLogic()->trackSendActive( ev.track, ev.send, ev.active );
|
||||
jack->bindingTrack = ev.track;
|
||||
jack->bindingSend = ev.send;
|
||||
jack->bindingActive = ev.active;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Event::TRACK_JACKSEND_ACTIVATE: {
|
||||
if ( availableRead >= sizeof(EventTrackJackSendActivate) ) {
|
||||
EventTrackJackSendActivate ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventTrackJackSendActivate) );
|
||||
jack->getLogic()->trackJackSendActivate(ev.track,ev.active);
|
||||
jack->bindingTrack = ev.track;
|
||||
|
||||
jack->bindingActive = ev.active;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Event::TRACK_JACKSEND: {
|
||||
if ( availableRead >= sizeof(EventTrackJackSend) ) {
|
||||
EventTrackJackSend ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventTrackJackSend) );
|
||||
jack->getLogic()->trackJackSend(ev.track,ev.value);
|
||||
jack->bindingTrack = ev.track;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Event::TRACK_SEND: {
|
||||
if ( availableRead >= sizeof(EventTrackSend) ) {
|
||||
EventTrackSend ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventTrackSend) );
|
||||
jack->getLogic()->trackSend( ev.track, ev.send, ev.value );
|
||||
jack->bindingTrack = ev.track;
|
||||
jack->bindingSend = ev.send;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// ========= LUPPP INTERNAL =====
|
||||
case Event::LOOPER_REQUEST_BUFFER: {
|
||||
if ( availableRead >= sizeof(EventLooperClipRequestBuffer) ) {
|
||||
EventLooperClipRequestBuffer ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventLooperClipRequestBuffer) );
|
||||
jack->getLooper( ev.track )->setRequestedBuffer( ev.scene, ev.ab );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Event::REQUEST_SAVE_BUFFER: {
|
||||
if ( availableRead >= sizeof(EventRequestSaveBuffer) ) {
|
||||
EventRequestSaveBuffer ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventRequestSaveBuffer) );
|
||||
jack->getLooper( ev.track )->getClip(ev.scene)->recieveSaveBuffer( ev.ab );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Event::CONTROLLER_INSTANCE: {
|
||||
if ( availableRead >= sizeof(EventControllerInstance) ) {
|
||||
EventControllerInstance ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventControllerInstance) );
|
||||
jack->getControllerUpdater()->registerController( static_cast<Controller*>(ev.controller) );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Event::CONTROLLER_INSTANCE_REMOVE: {
|
||||
if ( availableRead >= sizeof(EventControllerInstanceRemove) ) {
|
||||
EventControllerInstanceRemove ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventControllerInstanceRemove) );
|
||||
|
||||
jack->getControllerUpdater()->removeController( ev.ID );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Event::CONTROLLER_BINDING_ENABLE: {
|
||||
if ( availableRead >= sizeof(EventControllerBindingEnable) ) {
|
||||
EventControllerBindingEnable ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventControllerBindingEnable) );
|
||||
jack->bindingEventRecordEnable = ev.enable;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case Event::CONTROLLER_BINDING_REMOVE: {
|
||||
if ( availableRead >= sizeof(EventControllerBindingRemove) ) {
|
||||
EventControllerBindingRemove ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventControllerBindingRemove) );
|
||||
// get Controller* from controllerID
|
||||
Controller* c =jack->getControllerUpdater()->getController(ev.controllerID);
|
||||
// dynamic cast to check for GenericMIDI controller
|
||||
GenericMIDI* g = dynamic_cast<GenericMIDI*>(c);
|
||||
if ( g ) {
|
||||
// kick out BindingID
|
||||
g->removeBinding( ev.bindingID );
|
||||
} else {
|
||||
// GUI print notify of error removing binding
|
||||
}
|
||||
} break;
|
||||
}
|
||||
|
||||
case Event::CONTROLLER_INSTANCE_GET_TO_WRITE: {
|
||||
if ( availableRead >= sizeof(EventControllerInstanceGetToWrite) ) {
|
||||
EventControllerInstanceGetToWrite ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventControllerInstanceGetToWrite) );
|
||||
|
||||
// get the corresponding Controller with ID, and return it
|
||||
|
||||
Controller* c = jack->getControllerUpdater()->getController( ev.ID );
|
||||
|
||||
cout << "controller instance get to write id " << ev.ID << endl;
|
||||
|
||||
EventControllerInstanceGetToWrite tmp( ev.ID, c );
|
||||
writeToGuiRingbuffer( &tmp );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
cout << "DSP: Unkown message!! Will clog ringbuffer" << endl;
|
||||
// just do nothing
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// next call will get the half-written event
|
||||
return;
|
||||
}
|
||||
|
||||
// update available read, and loop over events
|
||||
availableRead = jack_ringbuffer_read_space( rbToDsp );
|
||||
}
|
||||
}
|
||||
|
||||
void writeToDspRingbuffer(EventBase* e)
|
||||
{
|
||||
if ( jack_ringbuffer_write_space(rbToDsp) >= e->size() )
|
||||
{
|
||||
jack_ringbuffer_write( rbToDsp, (const char*)e, e->size() );
|
||||
}
|
||||
else
|
||||
{
|
||||
// non-RT context, printing is OK!
|
||||
cout << "->DSP ringbuffer full!" << endl;
|
||||
}
|
||||
if ( jack_ringbuffer_write_space(rbToDsp) >= e->size() ) {
|
||||
jack_ringbuffer_write( rbToDsp, (const char*)e, e->size() );
|
||||
} else {
|
||||
// non-RT context, printing is OK!
|
||||
cout << "->DSP ringbuffer full!" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // LUPPP_EVENT_HANDLER_DSP_H
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -41,395 +41,445 @@ using namespace std;
|
|||
|
||||
void handleGuiEvents()
|
||||
{
|
||||
uint availableRead = jack_ringbuffer_read_space( rbToGui );
|
||||
|
||||
while ( availableRead >= sizeof(EventBase) )
|
||||
{
|
||||
jack_ringbuffer_peek( rbToGui, (char*)processGuiMem, sizeof(EventBase) );
|
||||
|
||||
EventBase* e = (EventBase*)processGuiMem;
|
||||
|
||||
// recheck the size against the actual event size
|
||||
if ( availableRead >= e->size() )
|
||||
{
|
||||
//cout << "reading event type " << e->type() << endl;
|
||||
|
||||
switch ( e->type() )
|
||||
{
|
||||
case Event::QUIT: {
|
||||
if ( availableRead >= sizeof(EventQuit) ) {
|
||||
EventQuit ev;
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventQuit) );
|
||||
LUPPP_NOTE("%s","GUI QUIT");
|
||||
gui->quit();
|
||||
} break; }
|
||||
|
||||
case Event::SAMPLERATE: {
|
||||
if ( availableRead >= sizeof(EventSamplerate) ) {
|
||||
EventSamplerate ev;
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventSamplerate) );
|
||||
gui->samplerate = ev.samplerate;
|
||||
//LUPPP_NOTE("Gui Samplerate: %i", gui->samplerate);
|
||||
} break; }
|
||||
|
||||
/// master
|
||||
case Event::MASTER_INPUT_TO: {
|
||||
if ( availableRead >= sizeof(EventMasterInputTo) ) {
|
||||
EventMasterInputTo ev;
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventMasterInputTo) );
|
||||
gui->getMasterTrack()->setInputTo( (int)ev.place, ev.value );
|
||||
} break; }
|
||||
case Event::MASTER_INPUT_TO_ACTIVE: {
|
||||
if ( availableRead >= sizeof(EventMasterInputToActive) ) {
|
||||
EventMasterInputToActive ev;
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventMasterInputToActive) );
|
||||
gui->getMasterTrack()->setInputToActive( (int)ev.place, ev.active );
|
||||
} break; }
|
||||
case Event::MASTER_INPUT_VOL: {
|
||||
if ( availableRead >= sizeof(EventMasterInputVol) ) {
|
||||
EventMasterInputVol ev;
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventMasterInputVol) );
|
||||
gui->getMasterTrack()->setInputVol( ev.vol );
|
||||
} break; }
|
||||
case Event::MASTER_RETURN: {
|
||||
if ( availableRead >= sizeof(EventMasterReturn) ) {
|
||||
EventMasterReturn ev;
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventMasterReturn) );
|
||||
gui->getMasterTrack()->setReturnVol( ev.vol );
|
||||
} break; }
|
||||
case Event::MASTER_VOL: {
|
||||
if ( availableRead >= sizeof(EventMasterVol) ) {
|
||||
EventMasterVol ev(0);
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventMasterVol) );
|
||||
gui->getMasterTrack()->getVolume()->fader( ev.vol );
|
||||
} break; }
|
||||
|
||||
|
||||
case Event::METRONOME_ACTIVE: {
|
||||
if ( availableRead >= sizeof(EventMetronomeActive) ) {
|
||||
EventMetronomeActive ev(false);
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventMetronomeActive) );
|
||||
gui->getMasterTrack()->metronomeEnable(ev.active);
|
||||
} break; }
|
||||
case Event::LOOPER_STATE: {
|
||||
if ( availableRead >= sizeof(EventLooperState) ) {
|
||||
EventLooperState ev;
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventLooperState) );
|
||||
//gui->getTrack(ev.track)->getClipSelector()->setState(ev.scene, ev.state);
|
||||
//jack->setLooperState( ev.track, ev.state );
|
||||
} break; }
|
||||
case Event::LOOPER_LOOP_LENGTH: {
|
||||
if ( availableRead >= sizeof(EventLooperLoopLength) ) {
|
||||
//EventLooperLoopLength ev;
|
||||
//jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventLooperLoopLength) );
|
||||
//jack->setLooperLoopLength( ev.track, ev.scale );
|
||||
} break; }
|
||||
case Event::LOOPER_PROGRESS: {
|
||||
if ( availableRead >= sizeof(EventLooperProgress) ) {
|
||||
EventLooperProgress ev;
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventLooperProgress) );
|
||||
|
||||
// only update if significant change
|
||||
//if ( ev.progress - gui->getTrack(ev.track)->radial.value() >= 0.05 ||
|
||||
// ev.progress > 0.9 )
|
||||
gui->getTrack(ev.track)->radial.value(ev.progress);
|
||||
|
||||
} break; }
|
||||
|
||||
|
||||
// FIXME: reset signal level to 0
|
||||
case Event::TRACK_SIGNAL_LEVEL: {
|
||||
if ( availableRead >= sizeof(EventTrackSignalLevel) ) {
|
||||
EventTrackSignalLevel ev;
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventTrackSignalLevel) );
|
||||
if ( ev.track == -2 ) {
|
||||
gui->getMasterTrack()->getInputVolume()->amplitude( ev.left, ev.right );
|
||||
} else if ( ev.track == -1 ) {
|
||||
gui->getMasterTrack()->getVolume()->amplitude( ev.left, ev.right );
|
||||
} else {
|
||||
gui->getTrack(ev.track)->getVolume()->amplitude( ev.left, ev.right ); }
|
||||
} break; }
|
||||
case Event::TRACK_VOLUME: {
|
||||
if ( availableRead >= sizeof(EventTrackVol) ) {
|
||||
EventTrackVol ev;
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventTrackVol) );
|
||||
gui->getTrack(ev.track)->getVolume()->fader( ev.vol );
|
||||
} break; }
|
||||
|
||||
|
||||
case Event::TRACK_RECORD_ARM: {
|
||||
if ( availableRead >= sizeof(EventTrackRecordArm) ) {
|
||||
EventTrackRecordArm ev;
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventTrackRecordArm) );
|
||||
gui->getTrack(ev.track)->setRecordActive( ev.recordArm );
|
||||
break; }
|
||||
}
|
||||
|
||||
case Event::TIME_BPM: {
|
||||
if ( availableRead >= sizeof(EventTimeBPM) ) {
|
||||
EventTimeBPM ev;
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventTimeBPM) );
|
||||
gui->getMasterTrack()->setBpm( ev.bpm );
|
||||
} break; }
|
||||
|
||||
|
||||
case Event::STATE_SAVE_BUFFER: {
|
||||
if ( availableRead >= sizeof(EventStateSaveBuffer) ) {
|
||||
EventStateSaveBuffer ev;
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventStateSaveBuffer) );
|
||||
uint availableRead = jack_ringbuffer_read_space( rbToGui );
|
||||
|
||||
while ( availableRead >= sizeof(EventBase) ) {
|
||||
jack_ringbuffer_peek( rbToGui, (char*)processGuiMem, sizeof(EventBase) );
|
||||
|
||||
EventBase* e = (EventBase*)processGuiMem;
|
||||
|
||||
// recheck the size against the actual event size
|
||||
if ( availableRead >= e->size() ) {
|
||||
//cout << "reading event type " << e->type() << endl;
|
||||
|
||||
switch ( e->type() ) {
|
||||
case Event::QUIT: {
|
||||
if ( availableRead >= sizeof(EventQuit) ) {
|
||||
EventQuit ev;
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventQuit) );
|
||||
LUPPP_NOTE("%s","GUI QUIT");
|
||||
gui->quit();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Event::SAMPLERATE: {
|
||||
if ( availableRead >= sizeof(EventSamplerate) ) {
|
||||
EventSamplerate ev;
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventSamplerate) );
|
||||
gui->samplerate = ev.samplerate;
|
||||
//LUPPP_NOTE("Gui Samplerate: %i", gui->samplerate);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/// master
|
||||
case Event::MASTER_INPUT_TO: {
|
||||
if ( availableRead >= sizeof(EventMasterInputTo) ) {
|
||||
EventMasterInputTo ev;
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventMasterInputTo) );
|
||||
gui->getMasterTrack()->setInputTo( (int)ev.place, ev.value );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Event::MASTER_INPUT_TO_ACTIVE: {
|
||||
if ( availableRead >= sizeof(EventMasterInputToActive) ) {
|
||||
EventMasterInputToActive ev;
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventMasterInputToActive) );
|
||||
gui->getMasterTrack()->setInputToActive( (int)ev.place, ev.active );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Event::MASTER_INPUT_VOL: {
|
||||
if ( availableRead >= sizeof(EventMasterInputVol) ) {
|
||||
EventMasterInputVol ev;
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventMasterInputVol) );
|
||||
gui->getMasterTrack()->setInputVol( ev.vol );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Event::MASTER_RETURN: {
|
||||
if ( availableRead >= sizeof(EventMasterReturn) ) {
|
||||
EventMasterReturn ev;
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventMasterReturn) );
|
||||
gui->getMasterTrack()->setReturnVol( ev.vol );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Event::MASTER_VOL: {
|
||||
if ( availableRead >= sizeof(EventMasterVol) ) {
|
||||
EventMasterVol ev(0);
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventMasterVol) );
|
||||
gui->getMasterTrack()->getVolume()->fader( ev.vol );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case Event::METRONOME_ACTIVE: {
|
||||
if ( availableRead >= sizeof(EventMetronomeActive) ) {
|
||||
EventMetronomeActive ev(false);
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventMetronomeActive) );
|
||||
gui->getMasterTrack()->metronomeEnable(ev.active);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Event::LOOPER_STATE: {
|
||||
if ( availableRead >= sizeof(EventLooperState) ) {
|
||||
EventLooperState ev;
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventLooperState) );
|
||||
//gui->getTrack(ev.track)->getClipSelector()->setState(ev.scene, ev.state);
|
||||
//jack->setLooperState( ev.track, ev.state );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Event::LOOPER_LOOP_LENGTH: {
|
||||
if ( availableRead >= sizeof(EventLooperLoopLength) ) {
|
||||
//EventLooperLoopLength ev;
|
||||
//jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventLooperLoopLength) );
|
||||
//jack->setLooperLoopLength( ev.track, ev.scale );
|
||||
} break;
|
||||
}
|
||||
case Event::LOOPER_PROGRESS: {
|
||||
if ( availableRead >= sizeof(EventLooperProgress) ) {
|
||||
EventLooperProgress ev;
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventLooperProgress) );
|
||||
|
||||
// only update if significant change
|
||||
//if ( ev.progress - gui->getTrack(ev.track)->radial.value() >= 0.05 ||
|
||||
// ev.progress > 0.9 )
|
||||
gui->getTrack(ev.track)->radial.value(ev.progress);
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// FIXME: reset signal level to 0
|
||||
case Event::TRACK_SIGNAL_LEVEL: {
|
||||
if ( availableRead >= sizeof(EventTrackSignalLevel) ) {
|
||||
EventTrackSignalLevel ev;
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventTrackSignalLevel) );
|
||||
if ( ev.track == -2 ) {
|
||||
gui->getMasterTrack()->getInputVolume()->amplitude( ev.left, ev.right );
|
||||
} else if ( ev.track == -1 ) {
|
||||
gui->getMasterTrack()->getVolume()->amplitude( ev.left, ev.right );
|
||||
} else {
|
||||
gui->getTrack(ev.track)->getVolume()->amplitude( ev.left, ev.right );
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Event::TRACK_VOLUME: {
|
||||
if ( availableRead >= sizeof(EventTrackVol) ) {
|
||||
EventTrackVol ev;
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventTrackVol) );
|
||||
gui->getTrack(ev.track)->getVolume()->fader( ev.vol );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case Event::TRACK_RECORD_ARM: {
|
||||
if ( availableRead >= sizeof(EventTrackRecordArm) ) {
|
||||
EventTrackRecordArm ev;
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventTrackRecordArm) );
|
||||
gui->getTrack(ev.track)->setRecordActive( ev.recordArm );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
case Event::TIME_BPM: {
|
||||
if ( availableRead >= sizeof(EventTimeBPM) ) {
|
||||
EventTimeBPM ev;
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventTimeBPM) );
|
||||
gui->getMasterTrack()->setBpm( ev.bpm );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case Event::STATE_SAVE_BUFFER: {
|
||||
if ( availableRead >= sizeof(EventStateSaveBuffer) ) {
|
||||
EventStateSaveBuffer ev;
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventStateSaveBuffer) );
|
||||
#ifdef DEBUG_SAVE
|
||||
cout << "EventSaveBuffer: " << ev.track << " " << ev.scene << " " << ev.ab->getID() << endl;
|
||||
cout << "EventSaveBuffer: " << ev.track << " " << ev.scene << " " << ev.ab->getID() << endl;
|
||||
#endif
|
||||
gui->getDiskWriter()->writeAudioBuffer( ev.track, ev.scene, ev.ab );
|
||||
// de allocate the AudioBuffer only if reqested
|
||||
if(!ev.no_dealloc) {
|
||||
gui->getDiskWriter()->writeAudioBuffer( ev.track, ev.scene, ev.ab );
|
||||
delete ev.ab;
|
||||
} else
|
||||
{
|
||||
gui->getDiskWriter()->writeAudioBuffer(ev.track, ev.scene, ev.ab,
|
||||
gui->saveBufferPath.c_str());
|
||||
gui->saveBufferPath = "";
|
||||
}
|
||||
gui->getDiskWriter()->writeAudioBuffer( ev.track, ev.scene, ev.ab );
|
||||
// de allocate the AudioBuffer only if reqested
|
||||
if(!ev.no_dealloc) {
|
||||
gui->getDiskWriter()->writeAudioBuffer( ev.track, ev.scene, ev.ab );
|
||||
delete ev.ab;
|
||||
} else {
|
||||
gui->getDiskWriter()->writeAudioBuffer(ev.track, ev.scene, ev.ab,
|
||||
gui->saveBufferPath.c_str());
|
||||
gui->saveBufferPath = "";
|
||||
}
|
||||
|
||||
} break; }
|
||||
|
||||
case Event::STATE_SAVE_FINISH: {
|
||||
if ( availableRead >= sizeof(EventStateSaveFinish) ) {
|
||||
EventStateSaveFinish ev;
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventStateSaveFinish) );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Event::STATE_SAVE_FINISH: {
|
||||
if ( availableRead >= sizeof(EventStateSaveFinish) ) {
|
||||
EventStateSaveFinish ev;
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventStateSaveFinish) );
|
||||
#ifdef DEBUG_SAVE
|
||||
cout << "EventSaveFinish!" << endl;
|
||||
cout << "EventSaveFinish!" << endl;
|
||||
#endif
|
||||
gui->getDiskWriter()->writeSession();
|
||||
} break; }
|
||||
|
||||
|
||||
case Event::GRID_STATE: {
|
||||
if ( availableRead >= sizeof(EventGridState) ) {
|
||||
EventGridState ev;
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventGridState) );
|
||||
gui->getTrack(ev.track)->getClipSelector()->setState( ev.scene, ev.state );
|
||||
if ( ev.state == GridLogic::STATE_RECORDING )
|
||||
gui->getTrack(ev.track)->getRadialStatus()->recording( true );
|
||||
else
|
||||
gui->getTrack(ev.track)->getRadialStatus()->recording( false );
|
||||
} break; }
|
||||
case Event::GRID_LAUNCH_SCENE: {
|
||||
if ( availableRead >= sizeof(EventGridLaunchScene) ) {
|
||||
EventGridLaunchScene ev;
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventGridLaunchScene) );
|
||||
for(int i = 0; i < NSCENES; i++)
|
||||
gui->getMasterTrack()->getClipSelector()->setState( i, GridLogic::STATE_EMPTY );
|
||||
gui->getMasterTrack()->getClipSelector()->setState( ev.scene, GridLogic::STATE_PLAYING );
|
||||
} break; }
|
||||
|
||||
case Event::GRID_SELECT_NEW_CHOSEN: {
|
||||
if ( availableRead >= sizeof(EventGridSelectNewChosen) ) {
|
||||
EventGridSelectNewChosen ev;
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventGridSelectNewChosen) );
|
||||
//LUPPP_NOTE("New special, %i, %i", ev.track, ev.scene);
|
||||
for(int i = 0; i < NTRACKS; i++)
|
||||
{
|
||||
gui->getTrack(i)->getClipSelector()->setSpecial( i == ev.track ? ev.scene : -1 );
|
||||
}
|
||||
gui->specialTrack = ev.track;
|
||||
gui->specialScene = ev.scene;
|
||||
} break; }
|
||||
|
||||
|
||||
case Event::TRACK_SEND: {
|
||||
if ( availableRead >= sizeof(EventTrackSend) ) {
|
||||
EventTrackSend ev;
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventTrackSend) );
|
||||
if ( ev.send == SEND_POSTFADER )
|
||||
if ( ev.track < NTRACKS )
|
||||
{
|
||||
gui->getTrack(ev.track)->setSend(ev.value );
|
||||
}
|
||||
if ( ev.send == SEND_XSIDE )
|
||||
if ( ev.track < NTRACKS )
|
||||
{
|
||||
gui->getTrack(ev.track)->setXSide( ev.value );
|
||||
}
|
||||
} break; }
|
||||
gui->getDiskWriter()->writeSession();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Event::TRACK_JACKSEND: {
|
||||
if ( availableRead >= sizeof(EventTrackJackSend) ) {
|
||||
EventTrackJackSend ev;
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventTrackJackSend) );
|
||||
gui->getTrack(ev.track)->setJackSend(ev.value);
|
||||
} break; }
|
||||
|
||||
case Event::TRACK_JACKSEND_ACTIVATE: {
|
||||
if ( availableRead >= sizeof(EventTrackJackSendActivate) ) {
|
||||
EventTrackJackSendActivate ev;
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventTrackJackSendActivate) );
|
||||
gui->getTrack(ev.track)->setJackSendActivate(ev.active);
|
||||
} break; }
|
||||
|
||||
case Event::TRACK_SEND_ACTIVE: {
|
||||
if ( availableRead >= sizeof(EventTrackSendActive) ) {
|
||||
EventTrackSendActive ev;
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventTrackSendActive) );
|
||||
if ( ev.send == SEND_POSTFADER )
|
||||
if ( ev.track < NTRACKS )
|
||||
{
|
||||
gui->getTrack(ev.track)->setSendActive(ev.active );
|
||||
}
|
||||
if ( ev.send == SEND_KEY )
|
||||
{
|
||||
if ( ev.track < NTRACKS )
|
||||
{
|
||||
gui->getTrack(ev.track)->setKeyActive( ev.active );
|
||||
}
|
||||
}
|
||||
} break; }
|
||||
|
||||
case Event::GUI_PRINT: {
|
||||
if ( availableRead >= sizeof(EventGuiPrint) ) {
|
||||
EventGuiPrint ev;
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventGuiPrint) );
|
||||
//cout << "DSP: " << ev.getMessage() << endl;
|
||||
LUPPP_DSP("%s", ev.getMessage() );
|
||||
} break; }
|
||||
case Event::TIME_BAR_BEAT: {
|
||||
if ( availableRead >= sizeof(EventTimeBarBeat) ) {
|
||||
EventTimeBarBeat ev;
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventTimeBarBeat) );
|
||||
gui->getMasterTrack()->setBarBeat( ev.bar, ev.beat);
|
||||
} break; }
|
||||
case Event::TIME_TEMPO_TAP: {
|
||||
if ( availableRead >= sizeof(EventTimeTempoTap) ) {
|
||||
EventTimeTempoTap ev;
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventTimeTempoTap) );
|
||||
gui->getMasterTrack()->setTapTempo( ev.pressed );
|
||||
} break; }
|
||||
|
||||
|
||||
case Event::LOOPER_REQUEST_BUFFER: {
|
||||
if ( availableRead >= sizeof(EventLooperClipRequestBuffer) ) {
|
||||
EventLooperClipRequestBuffer ev;
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventLooperClipRequestBuffer) );
|
||||
|
||||
/// allocate a new AudioBuffer with ev.numElements, pass back to DSP
|
||||
AudioBuffer* ab = new AudioBuffer(ev.numElements);
|
||||
EventLooperClipRequestBuffer returnEvent(ev.track, ev.scene, ab);
|
||||
writeToDspRingbuffer( &returnEvent );
|
||||
case Event::GRID_STATE: {
|
||||
if ( availableRead >= sizeof(EventGridState) ) {
|
||||
EventGridState ev;
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventGridState) );
|
||||
gui->getTrack(ev.track)->getClipSelector()->setState( ev.scene, ev.state );
|
||||
if ( ev.state == GridLogic::STATE_RECORDING )
|
||||
gui->getTrack(ev.track)->getRadialStatus()->recording( true );
|
||||
else
|
||||
gui->getTrack(ev.track)->getRadialStatus()->recording( false );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Event::GRID_LAUNCH_SCENE: {
|
||||
if ( availableRead >= sizeof(EventGridLaunchScene) ) {
|
||||
EventGridLaunchScene ev;
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventGridLaunchScene) );
|
||||
for(int i = 0; i < NSCENES; i++)
|
||||
gui->getMasterTrack()->getClipSelector()->setState( i, GridLogic::STATE_EMPTY );
|
||||
gui->getMasterTrack()->getClipSelector()->setState( ev.scene, GridLogic::STATE_PLAYING );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Event::GRID_SELECT_NEW_CHOSEN: {
|
||||
if ( availableRead >= sizeof(EventGridSelectNewChosen) ) {
|
||||
EventGridSelectNewChosen ev;
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventGridSelectNewChosen) );
|
||||
//LUPPP_NOTE("New special, %i, %i", ev.track, ev.scene);
|
||||
for(int i = 0; i < NTRACKS; i++) {
|
||||
gui->getTrack(i)->getClipSelector()->setSpecial( i == ev.track ? ev.scene : -1 );
|
||||
}
|
||||
gui->specialTrack = ev.track;
|
||||
gui->specialScene = ev.scene;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case Event::TRACK_SEND: {
|
||||
if ( availableRead >= sizeof(EventTrackSend) ) {
|
||||
EventTrackSend ev;
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventTrackSend) );
|
||||
if ( ev.send == SEND_POSTFADER )
|
||||
if ( ev.track < NTRACKS ) {
|
||||
gui->getTrack(ev.track)->setSend(ev.value );
|
||||
}
|
||||
if ( ev.send == SEND_XSIDE )
|
||||
if ( ev.track < NTRACKS ) {
|
||||
gui->getTrack(ev.track)->setXSide( ev.value );
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Event::TRACK_JACKSEND: {
|
||||
if ( availableRead >= sizeof(EventTrackJackSend) ) {
|
||||
EventTrackJackSend ev;
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventTrackJackSend) );
|
||||
gui->getTrack(ev.track)->setJackSend(ev.value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Event::TRACK_JACKSEND_ACTIVATE: {
|
||||
if ( availableRead >= sizeof(EventTrackJackSendActivate) ) {
|
||||
EventTrackJackSendActivate ev;
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventTrackJackSendActivate) );
|
||||
gui->getTrack(ev.track)->setJackSendActivate(ev.active);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Event::TRACK_SEND_ACTIVE: {
|
||||
if ( availableRead >= sizeof(EventTrackSendActive) ) {
|
||||
EventTrackSendActive ev;
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventTrackSendActive) );
|
||||
if ( ev.send == SEND_POSTFADER )
|
||||
if ( ev.track < NTRACKS ) {
|
||||
gui->getTrack(ev.track)->setSendActive(ev.active );
|
||||
}
|
||||
if ( ev.send == SEND_KEY ) {
|
||||
if ( ev.track < NTRACKS ) {
|
||||
gui->getTrack(ev.track)->setKeyActive( ev.active );
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Event::GUI_PRINT: {
|
||||
if ( availableRead >= sizeof(EventGuiPrint) ) {
|
||||
EventGuiPrint ev;
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventGuiPrint) );
|
||||
//cout << "DSP: " << ev.getMessage() << endl;
|
||||
LUPPP_DSP("%s", ev.getMessage() );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Event::TIME_BAR_BEAT: {
|
||||
if ( availableRead >= sizeof(EventTimeBarBeat) ) {
|
||||
EventTimeBarBeat ev;
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventTimeBarBeat) );
|
||||
gui->getMasterTrack()->setBarBeat( ev.bar, ev.beat);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Event::TIME_TEMPO_TAP: {
|
||||
if ( availableRead >= sizeof(EventTimeTempoTap) ) {
|
||||
EventTimeTempoTap ev;
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventTimeTempoTap) );
|
||||
gui->getMasterTrack()->setTapTempo( ev.pressed );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case Event::LOOPER_REQUEST_BUFFER: {
|
||||
if ( availableRead >= sizeof(EventLooperClipRequestBuffer) ) {
|
||||
EventLooperClipRequestBuffer ev;
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventLooperClipRequestBuffer) );
|
||||
|
||||
/// allocate a new AudioBuffer with ev.numElements, pass back to DSP
|
||||
AudioBuffer* ab = new AudioBuffer(ev.numElements);
|
||||
EventLooperClipRequestBuffer returnEvent(ev.track, ev.scene, ab);
|
||||
writeToDspRingbuffer( &returnEvent );
|
||||
#ifdef DEBUG_BUFFER
|
||||
printf("new buffer going to track %i, scene %i\n",ev.track, ev.scene);
|
||||
printf("new buffer going to track %i, scene %i\n",ev.track, ev.scene);
|
||||
#endif
|
||||
} break; }
|
||||
|
||||
case Event::REQUEST_SAVE_BUFFER: {
|
||||
if ( availableRead >= sizeof(EventRequestSaveBuffer) ) {
|
||||
EventRequestSaveBuffer ev;
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventRequestSaveBuffer) );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Event::REQUEST_SAVE_BUFFER: {
|
||||
if ( availableRead >= sizeof(EventRequestSaveBuffer) ) {
|
||||
EventRequestSaveBuffer ev;
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventRequestSaveBuffer) );
|
||||
#ifdef DEBUG_BUFFER
|
||||
printf("Save buffer to track %i, scene %i\n",ev.track, ev.scene);
|
||||
printf("Save buffer to track %i, scene %i\n",ev.track, ev.scene);
|
||||
#endif
|
||||
/// allocate a new AudioBuffer with ev.numElements, pass back to DSP
|
||||
AudioBuffer* ab = new AudioBuffer(ev.bufferSize);
|
||||
|
||||
if ( ab )
|
||||
{
|
||||
//LUPPP_NOTE("Save buffer sent with t %i, s %i, ab* %i", ev.track, ev.scene, ab );
|
||||
EventRequestSaveBuffer returnEvent( ev.track, ev.scene, ab);
|
||||
writeToDspRingbuffer( &returnEvent );
|
||||
}
|
||||
else
|
||||
{
|
||||
cout << "error allocating save buffer!" << endl;
|
||||
}
|
||||
} break; }
|
||||
|
||||
case Event::DEALLOCATE_BUFFER: {
|
||||
if ( availableRead >= sizeof(EventDeallocateBuffer) ) {
|
||||
EventDeallocateBuffer ev;
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventDeallocateBuffer) );
|
||||
delete ev.ab;
|
||||
} break; }
|
||||
|
||||
case Event::CONTROLLER_BINDING_ENABLE: {
|
||||
if ( availableRead >= sizeof(EventControllerBindingEnable) ) {
|
||||
EventControllerBindingEnable ev;
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventControllerBindingEnable) );
|
||||
ControllerUI* c = gui->getOptionsWindow()->getControllerUI( ev.controllerID );
|
||||
if ( c )
|
||||
c->setBindEnable( ev.enable );
|
||||
else
|
||||
LUPPP_WARN("ControllerUI %i doesn't exist in the UI", ev.controllerID );
|
||||
} break; }
|
||||
|
||||
case Event::CONTROLLER_BINDING_TARGET: {
|
||||
if ( availableRead >= sizeof(EventControllerBindingTarget) ) {
|
||||
EventControllerBindingTarget ev;
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventControllerBindingTarget) );
|
||||
gui->getOptionsWindow()->setTarget( ev.target );
|
||||
} break; }
|
||||
|
||||
case Event::CONTROLLER_BINDING_MADE: {
|
||||
if ( availableRead >= sizeof(EventControllerBindingMade) ) {
|
||||
EventControllerBindingMade ev;
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventControllerBindingMade) );
|
||||
ControllerUI* c = gui->getOptionsWindow()->getControllerUI( ev.controllerID );
|
||||
if ( c )
|
||||
c->addBinding( (Binding*)ev.binding );
|
||||
else
|
||||
LUPPP_WARN("ControllerUI %i doesn't exist in the UI", ev.controllerID );
|
||||
} break; }
|
||||
|
||||
case Event::CONTROLLER_INSTANCE_GET_TO_WRITE: {
|
||||
if ( availableRead >= sizeof(EventControllerInstanceGetToWrite) ) {
|
||||
EventControllerInstanceGetToWrite ev;
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventControllerInstanceGetToWrite) );
|
||||
// write the contents of the GenericMIDI controller to .ctlr file
|
||||
gui->getDiskWriter()->writeControllerFile( (Controller*)ev.controller );
|
||||
} break; }
|
||||
|
||||
case Event::CONTROLLER_INSTANCE: {
|
||||
if ( availableRead >= sizeof(EventControllerInstance) ) {
|
||||
EventControllerInstance ev;
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventControllerInstance) );
|
||||
// remove this controller from use:
|
||||
Controller* c = (Controller*)ev.controller;
|
||||
LUPPP_NOTE("Deleting controller %s", c->getName().c_str() );
|
||||
// delete will call the destructor for the Controller: this should
|
||||
// clean up ports etc, all from the GUI thread as appropriate
|
||||
delete c;
|
||||
} break; }
|
||||
|
||||
|
||||
|
||||
default:
|
||||
{
|
||||
cout << "GUI: Unkown message!! Will clog ringbuffer" << endl;
|
||||
// just do nothing
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// next call will get the half-written event
|
||||
return;
|
||||
}
|
||||
|
||||
// update available read, and loop over events
|
||||
availableRead = jack_ringbuffer_read_space( rbToGui );
|
||||
}
|
||||
/// allocate a new AudioBuffer with ev.numElements, pass back to DSP
|
||||
AudioBuffer* ab = new AudioBuffer(ev.bufferSize);
|
||||
|
||||
if ( ab ) {
|
||||
//LUPPP_NOTE("Save buffer sent with t %i, s %i, ab* %i", ev.track, ev.scene, ab );
|
||||
EventRequestSaveBuffer returnEvent( ev.track, ev.scene, ab);
|
||||
writeToDspRingbuffer( &returnEvent );
|
||||
} else {
|
||||
cout << "error allocating save buffer!" << endl;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Event::DEALLOCATE_BUFFER: {
|
||||
if ( availableRead >= sizeof(EventDeallocateBuffer) ) {
|
||||
EventDeallocateBuffer ev;
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventDeallocateBuffer) );
|
||||
delete ev.ab;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Event::CONTROLLER_BINDING_ENABLE: {
|
||||
if ( availableRead >= sizeof(EventControllerBindingEnable) ) {
|
||||
EventControllerBindingEnable ev;
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventControllerBindingEnable) );
|
||||
ControllerUI* c = gui->getOptionsWindow()->getControllerUI( ev.controllerID );
|
||||
if ( c )
|
||||
c->setBindEnable( ev.enable );
|
||||
else
|
||||
LUPPP_WARN("ControllerUI %i doesn't exist in the UI", ev.controllerID );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Event::CONTROLLER_BINDING_TARGET: {
|
||||
if ( availableRead >= sizeof(EventControllerBindingTarget) ) {
|
||||
EventControllerBindingTarget ev;
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventControllerBindingTarget) );
|
||||
gui->getOptionsWindow()->setTarget( ev.target );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Event::CONTROLLER_BINDING_MADE: {
|
||||
if ( availableRead >= sizeof(EventControllerBindingMade) ) {
|
||||
EventControllerBindingMade ev;
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventControllerBindingMade) );
|
||||
ControllerUI* c = gui->getOptionsWindow()->getControllerUI( ev.controllerID );
|
||||
if ( c )
|
||||
c->addBinding( (Binding*)ev.binding );
|
||||
else
|
||||
LUPPP_WARN("ControllerUI %i doesn't exist in the UI", ev.controllerID );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Event::CONTROLLER_INSTANCE_GET_TO_WRITE: {
|
||||
if ( availableRead >= sizeof(EventControllerInstanceGetToWrite) ) {
|
||||
EventControllerInstanceGetToWrite ev;
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventControllerInstanceGetToWrite) );
|
||||
// write the contents of the GenericMIDI controller to .ctlr file
|
||||
gui->getDiskWriter()->writeControllerFile( (Controller*)ev.controller );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Event::CONTROLLER_INSTANCE: {
|
||||
if ( availableRead >= sizeof(EventControllerInstance) ) {
|
||||
EventControllerInstance ev;
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventControllerInstance) );
|
||||
// remove this controller from use:
|
||||
Controller* c = (Controller*)ev.controller;
|
||||
LUPPP_NOTE("Deleting controller %s", c->getName().c_str() );
|
||||
// delete will call the destructor for the Controller: this should
|
||||
// clean up ports etc, all from the GUI thread as appropriate
|
||||
delete c;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
|
||||
default: {
|
||||
cout << "GUI: Unkown message!! Will clog ringbuffer" << endl;
|
||||
// just do nothing
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// next call will get the half-written event
|
||||
return;
|
||||
}
|
||||
|
||||
// update available read, and loop over events
|
||||
availableRead = jack_ringbuffer_read_space( rbToGui );
|
||||
}
|
||||
}
|
||||
|
||||
void writeToGuiRingbuffer(EventBase* e)
|
||||
{
|
||||
if ( jack_ringbuffer_write_space(rbToGui) >= e->size() )
|
||||
{
|
||||
jack_ringbuffer_write( rbToGui, (const char*)e, e->size() );
|
||||
}
|
||||
else
|
||||
{
|
||||
cout << "->GUI ringbuffer full!" << endl;
|
||||
}
|
||||
if ( jack_ringbuffer_write_space(rbToGui) >= e->size() ) {
|
||||
jack_ringbuffer_write( rbToGui, (const char*)e, e->size() );
|
||||
} else {
|
||||
cout << "->GUI ringbuffer full!" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // LUPPP_EVENT_HANDLER_DSP_H
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -31,154 +31,157 @@ extern Gui* gui;
|
|||
#include "avtk/avtk_button.h"
|
||||
|
||||
|
||||
void oneCB (Fl_Widget*,void* data) { ((AudioEditor*)data)->setBeatsAndQuit( 1 ); }
|
||||
void twoCB (Fl_Widget*,void* data) { ((AudioEditor*)data)->setBeatsAndQuit( 2 ); }
|
||||
void fourCB (Fl_Widget*,void* data) { ((AudioEditor*)data)->setBeatsAndQuit( 4 ); }
|
||||
void eightCB (Fl_Widget*,void* data) { ((AudioEditor*)data)->setBeatsAndQuit( 8 ); }
|
||||
void sixteenCB (Fl_Widget*,void* data) { ((AudioEditor*)data)->setBeatsAndQuit( 16); }
|
||||
void thirtyTwoCB(Fl_Widget*,void* data) { ((AudioEditor*)data)->setBeatsAndQuit( 32); }
|
||||
void sixtyfourCB(Fl_Widget*,void* data) { ((AudioEditor*)data)->setBeatsAndQuit( 64); }
|
||||
void oneCB (Fl_Widget*,void* data)
|
||||
{
|
||||
((AudioEditor*)data)->setBeatsAndQuit( 1 );
|
||||
}
|
||||
void twoCB (Fl_Widget*,void* data)
|
||||
{
|
||||
((AudioEditor*)data)->setBeatsAndQuit( 2 );
|
||||
}
|
||||
void fourCB (Fl_Widget*,void* data)
|
||||
{
|
||||
((AudioEditor*)data)->setBeatsAndQuit( 4 );
|
||||
}
|
||||
void eightCB (Fl_Widget*,void* data)
|
||||
{
|
||||
((AudioEditor*)data)->setBeatsAndQuit( 8 );
|
||||
}
|
||||
void sixteenCB (Fl_Widget*,void* data)
|
||||
{
|
||||
((AudioEditor*)data)->setBeatsAndQuit( 16);
|
||||
}
|
||||
void thirtyTwoCB(Fl_Widget*,void* data)
|
||||
{
|
||||
((AudioEditor*)data)->setBeatsAndQuit( 32);
|
||||
}
|
||||
void sixtyfourCB(Fl_Widget*,void* data)
|
||||
{
|
||||
((AudioEditor*)data)->setBeatsAndQuit( 64);
|
||||
}
|
||||
|
||||
void cancelCB(Fl_Widget*,void* data)
|
||||
{
|
||||
printf("button, beats = 4\n");
|
||||
AudioEditor* ae = (AudioEditor*) data;
|
||||
ae->setBeatsAndQuit( -1 );
|
||||
printf("button, beats = 4\n");
|
||||
AudioEditor* ae = (AudioEditor*) data;
|
||||
ae->setBeatsAndQuit( -1 );
|
||||
}
|
||||
|
||||
AudioEditor::AudioEditor()
|
||||
{
|
||||
window = new Fl_Double_Window(460,200,"Audio Editor : Beats?");
|
||||
waveform = new Avtk::Waveform(5, 5, 450, 150, "Waveform");
|
||||
cancel = new Avtk::Button(360, 160, 80,30, "Cancel");
|
||||
|
||||
const char* names[] = {
|
||||
"1","2","4","8","16","32","64"
|
||||
};
|
||||
|
||||
for(int i = 0; i < 7; i++)
|
||||
{
|
||||
stringstream s;
|
||||
s << i;
|
||||
beatButtons[i] = new Avtk::Button(5 + i * 50, 160, 40,30, strdup(names[i]) );
|
||||
}
|
||||
window->end();
|
||||
|
||||
beatButtons[0]->callback( oneCB , this);
|
||||
beatButtons[1]->callback( twoCB , this);
|
||||
beatButtons[2]->callback( fourCB , this);
|
||||
beatButtons[3]->callback( eightCB , this);
|
||||
beatButtons[4]->callback( sixteenCB , this);
|
||||
beatButtons[5]->callback( thirtyTwoCB, this);
|
||||
beatButtons[6]->callback( sixtyfourCB, this);
|
||||
|
||||
cancel->callback( cancelCB, this );
|
||||
window = new Fl_Double_Window(460,200,"Audio Editor : Beats?");
|
||||
waveform = new Avtk::Waveform(5, 5, 450, 150, "Waveform");
|
||||
cancel = new Avtk::Button(360, 160, 80,30, "Cancel");
|
||||
|
||||
const char* names[] = {
|
||||
"1","2","4","8","16","32","64"
|
||||
};
|
||||
|
||||
for(int i = 0; i < 7; i++) {
|
||||
stringstream s;
|
||||
s << i;
|
||||
beatButtons[i] = new Avtk::Button(5 + i * 50, 160, 40,30, strdup(names[i]) );
|
||||
}
|
||||
window->end();
|
||||
|
||||
beatButtons[0]->callback( oneCB , this);
|
||||
beatButtons[1]->callback( twoCB , this);
|
||||
beatButtons[2]->callback( fourCB , this);
|
||||
beatButtons[3]->callback( eightCB , this);
|
||||
beatButtons[4]->callback( sixteenCB , this);
|
||||
beatButtons[5]->callback( thirtyTwoCB, this);
|
||||
beatButtons[6]->callback( sixtyfourCB, this);
|
||||
|
||||
cancel->callback( cancelCB, this );
|
||||
}
|
||||
|
||||
void AudioEditor::show( AudioBuffer* buf, bool modal )
|
||||
{
|
||||
ab = buf;
|
||||
|
||||
if ( !ab )
|
||||
{
|
||||
LUPPP_WARN("called with ab == 0");
|
||||
}
|
||||
else
|
||||
{
|
||||
std::vector<float>& tmp = ab->getData();
|
||||
int size = tmp.size();
|
||||
waveform->setData( &tmp[0], size );
|
||||
|
||||
const int beats[]={1,2,4,8,16,32,64};
|
||||
|
||||
int iBeatOne = -1;
|
||||
int iBeatTwo = -1;
|
||||
|
||||
// figure out BPM values from size
|
||||
for( int i = 0; i < 7; i++ )
|
||||
{
|
||||
int beat = beats[i];
|
||||
|
||||
int fpb = size / beat;
|
||||
|
||||
int bpm = (gui->samplerate / fpb) * 60;
|
||||
|
||||
|
||||
if ( bpm < 60 || bpm > 220 )
|
||||
{
|
||||
// disable option: not valid
|
||||
beatButtons[i]->setGreyOut( true );
|
||||
beatButtons[i]->setColor( 0.4, 0.4, 0.4 );
|
||||
}
|
||||
else
|
||||
{
|
||||
//printf("%i, fpb = %i, bpm= = %i\n", beat, fpb, bpm );
|
||||
// enable option ( may be disabled previously! )
|
||||
beatButtons[i]->setGreyOut( false );
|
||||
|
||||
// remember this beat was a valid one, to check for best match
|
||||
if ( iBeatOne == -1 )
|
||||
iBeatOne = i;
|
||||
else
|
||||
iBeatTwo = i;
|
||||
}
|
||||
}
|
||||
|
||||
// both valid: compare, and adjust color
|
||||
if ( iBeatOne != -1 && iBeatTwo != -1 )
|
||||
{
|
||||
int masterFpb = (gui->samplerate * 60) / gui->getMasterTrack()->getBpm();
|
||||
int oneFpb = size / beats[iBeatOne];
|
||||
int twoFpb = size / beats[iBeatTwo];
|
||||
|
||||
int oneDelta = masterFpb - oneFpb;
|
||||
int twoDelta = masterFpb - twoFpb;
|
||||
|
||||
if ( oneDelta < 0 ) oneDelta = -oneDelta;
|
||||
if ( twoDelta < 0 ) twoDelta = -twoDelta;
|
||||
|
||||
if ( oneDelta == twoDelta )
|
||||
{
|
||||
beatButtons[iBeatOne]->setColor( 0.0, 1.0, 0.0 );
|
||||
beatButtons[iBeatTwo]->setColor( 0.0, 1.0, 0.0 );
|
||||
}
|
||||
else if ( oneDelta <= twoDelta )
|
||||
{
|
||||
// one is the better match
|
||||
beatButtons[iBeatOne]->setColor( 0.0, 1.0, 0.0 );
|
||||
beatButtons[iBeatTwo]->setColor( 1.0, 0.0, 0.0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
beatButtons[iBeatTwo]->setColor( 0.0, 1.0, 0.0 );
|
||||
beatButtons[iBeatOne]->setColor( 1.0, 0.0, 0.0 );
|
||||
}
|
||||
}
|
||||
else if( iBeatOne != -1 && iBeatTwo == -1) // only one valid
|
||||
{
|
||||
beatButtons[iBeatOne]->setColor( 0.0, 1.0, 0.0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
// no valid BPM range..?
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
window->set_modal();
|
||||
window->show();
|
||||
ab = buf;
|
||||
|
||||
if ( !ab ) {
|
||||
LUPPP_WARN("called with ab == 0");
|
||||
} else {
|
||||
std::vector<float>& tmp = ab->getData();
|
||||
int size = tmp.size();
|
||||
waveform->setData( &tmp[0], size );
|
||||
|
||||
const int beats[]= {1,2,4,8,16,32,64};
|
||||
|
||||
int iBeatOne = -1;
|
||||
int iBeatTwo = -1;
|
||||
|
||||
// figure out BPM values from size
|
||||
for( int i = 0; i < 7; i++ ) {
|
||||
int beat = beats[i];
|
||||
|
||||
int fpb = size / beat;
|
||||
|
||||
int bpm = (gui->samplerate / fpb) * 60;
|
||||
|
||||
|
||||
if ( bpm < 60 || bpm > 220 ) {
|
||||
// disable option: not valid
|
||||
beatButtons[i]->setGreyOut( true );
|
||||
beatButtons[i]->setColor( 0.4, 0.4, 0.4 );
|
||||
} else {
|
||||
//printf("%i, fpb = %i, bpm= = %i\n", beat, fpb, bpm );
|
||||
// enable option ( may be disabled previously! )
|
||||
beatButtons[i]->setGreyOut( false );
|
||||
|
||||
// remember this beat was a valid one, to check for best match
|
||||
if ( iBeatOne == -1 )
|
||||
iBeatOne = i;
|
||||
else
|
||||
iBeatTwo = i;
|
||||
}
|
||||
}
|
||||
|
||||
// both valid: compare, and adjust color
|
||||
if ( iBeatOne != -1 && iBeatTwo != -1 ) {
|
||||
int masterFpb = (gui->samplerate * 60) / gui->getMasterTrack()->getBpm();
|
||||
int oneFpb = size / beats[iBeatOne];
|
||||
int twoFpb = size / beats[iBeatTwo];
|
||||
|
||||
int oneDelta = masterFpb - oneFpb;
|
||||
int twoDelta = masterFpb - twoFpb;
|
||||
|
||||
if ( oneDelta < 0 ) oneDelta = -oneDelta;
|
||||
if ( twoDelta < 0 ) twoDelta = -twoDelta;
|
||||
|
||||
if ( oneDelta == twoDelta ) {
|
||||
beatButtons[iBeatOne]->setColor( 0.0, 1.0, 0.0 );
|
||||
beatButtons[iBeatTwo]->setColor( 0.0, 1.0, 0.0 );
|
||||
} else if ( oneDelta <= twoDelta ) {
|
||||
// one is the better match
|
||||
beatButtons[iBeatOne]->setColor( 0.0, 1.0, 0.0 );
|
||||
beatButtons[iBeatTwo]->setColor( 1.0, 0.0, 0.0 );
|
||||
} else {
|
||||
beatButtons[iBeatTwo]->setColor( 0.0, 1.0, 0.0 );
|
||||
beatButtons[iBeatOne]->setColor( 1.0, 0.0, 0.0 );
|
||||
}
|
||||
} else if( iBeatOne != -1 && iBeatTwo == -1) { // only one valid
|
||||
beatButtons[iBeatOne]->setColor( 0.0, 1.0, 0.0 );
|
||||
} else {
|
||||
// no valid BPM range..?
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
window->set_modal();
|
||||
window->show();
|
||||
}
|
||||
|
||||
void AudioEditor::hide()
|
||||
{
|
||||
window->hide();
|
||||
window->hide();
|
||||
}
|
||||
|
||||
|
||||
void AudioEditor::setBeatsAndQuit(int beats)
|
||||
{
|
||||
ab->setBeats(beats);
|
||||
window->hide();
|
||||
ab->setBeats(beats);
|
||||
window->hide();
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -190,10 +193,10 @@ AudioBuffer* AudioEditor::getAudioBuffer()
|
|||
|
||||
bool AudioEditor::shown()
|
||||
{
|
||||
return window->shown();
|
||||
return window->shown();
|
||||
}
|
||||
|
||||
AudioEditor::~AudioEditor()
|
||||
{
|
||||
delete window;
|
||||
delete window;
|
||||
}
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -24,38 +24,39 @@
|
|||
#include <FL/Fl_Double_Window.H>
|
||||
|
||||
class AudioBuffer;
|
||||
namespace Avtk {
|
||||
namespace Avtk
|
||||
{
|
||||
class Waveform;
|
||||
class Button;
|
||||
}
|
||||
|
||||
class AudioEditor
|
||||
{
|
||||
public:
|
||||
AudioEditor();
|
||||
~AudioEditor();
|
||||
|
||||
/// shows the window, and loads the audio buffer into the display
|
||||
void show( AudioBuffer* ab, bool modal = false );
|
||||
|
||||
void hide();
|
||||
|
||||
/// returns true if the editor window is shown
|
||||
bool shown();
|
||||
|
||||
void setBeatsAndQuit( int beats );
|
||||
|
||||
//AudioBuffer* getAudioBuffer();
|
||||
|
||||
private:
|
||||
// GUI elements
|
||||
Fl_Double_Window* window;
|
||||
Avtk::Waveform* waveform;
|
||||
Avtk::Button* cancel;
|
||||
Avtk::Button* beatButtons[7];
|
||||
|
||||
// Contents
|
||||
AudioBuffer* ab;
|
||||
public:
|
||||
AudioEditor();
|
||||
~AudioEditor();
|
||||
|
||||
/// shows the window, and loads the audio buffer into the display
|
||||
void show( AudioBuffer* ab, bool modal = false );
|
||||
|
||||
void hide();
|
||||
|
||||
/// returns true if the editor window is shown
|
||||
bool shown();
|
||||
|
||||
void setBeatsAndQuit( int beats );
|
||||
|
||||
//AudioBuffer* getAudioBuffer();
|
||||
|
||||
private:
|
||||
// GUI elements
|
||||
Fl_Double_Window* window;
|
||||
Avtk::Waveform* waveform;
|
||||
Avtk::Button* cancel;
|
||||
Avtk::Button* beatButtons[7];
|
||||
|
||||
// Contents
|
||||
AudioBuffer* ab;
|
||||
};
|
||||
|
||||
#endif // LUPPP_AUDIO_EDITOR_H
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -22,378 +22,358 @@
|
|||
|
||||
static void gmastertrack_tempoDial_callback(Fl_Widget *w, void *data)
|
||||
{
|
||||
Avtk::Dial* b = (Avtk::Dial*)w;
|
||||
float bpm = (int)(b->value() * 160.f + 60);
|
||||
if(std::fabs(bpm-round(bpm)))
|
||||
{
|
||||
LUPPP_WARN("%f",bpm);
|
||||
}
|
||||
EventTimeBPM e = EventTimeBPM( bpm );
|
||||
writeToDspRingbuffer( &e );
|
||||
Avtk::Dial* b = (Avtk::Dial*)w;
|
||||
float bpm = (int)(b->value() * 160.f + 60);
|
||||
if(std::fabs(bpm-round(bpm))) {
|
||||
LUPPP_WARN("%f",bpm);
|
||||
}
|
||||
EventTimeBPM e = EventTimeBPM( bpm );
|
||||
writeToDspRingbuffer( &e );
|
||||
}
|
||||
|
||||
static void gmastertrack_volume_callback(Fl_Widget *w, void *data)
|
||||
{
|
||||
Avtk::Volume* b = (Avtk::Volume*)w;
|
||||
float v = b->value();
|
||||
EventMasterVol e( v );
|
||||
writeToDspRingbuffer( &e );
|
||||
Avtk::Volume* b = (Avtk::Volume*)w;
|
||||
float v = b->value();
|
||||
EventMasterVol e( v );
|
||||
writeToDspRingbuffer( &e );
|
||||
}
|
||||
|
||||
static void gmastertrack_inputVolume_callback(Fl_Widget *w, void *data)
|
||||
{
|
||||
Avtk::Volume* b = (Avtk::Volume*)w;
|
||||
float v = b->value();
|
||||
EventMasterInputVol e( v );
|
||||
writeToDspRingbuffer( &e );
|
||||
Avtk::Volume* b = (Avtk::Volume*)w;
|
||||
float v = b->value();
|
||||
EventMasterInputVol e( v );
|
||||
writeToDspRingbuffer( &e );
|
||||
}
|
||||
|
||||
static void gmastertrack_sidchainKeyButton_callback(Fl_Widget *w, void *data)
|
||||
{
|
||||
Avtk::LightButton* b = (Avtk::LightButton*)w;
|
||||
b->value( !b->value() );
|
||||
EventMasterInputToActive e( INPUT_TO_SIDE_KEY, b->value() );
|
||||
writeToDspRingbuffer( &e );
|
||||
//printf("Key button\n");
|
||||
Avtk::LightButton* b = (Avtk::LightButton*)w;
|
||||
b->value( !b->value() );
|
||||
EventMasterInputToActive e( INPUT_TO_SIDE_KEY, b->value() );
|
||||
writeToDspRingbuffer( &e );
|
||||
//printf("Key button\n");
|
||||
}
|
||||
|
||||
static void gmastertrack_mixButton_callback(Fl_Widget *w, void *data)
|
||||
{
|
||||
Avtk::LightButton* b = (Avtk::LightButton*)w;
|
||||
b->value( !b->value() );
|
||||
EventMasterInputToActive e( INPUT_TO_MIX, b->value() );
|
||||
writeToDspRingbuffer( &e );
|
||||
//printf("Mix button\n");
|
||||
Avtk::LightButton* b = (Avtk::LightButton*)w;
|
||||
b->value( !b->value() );
|
||||
EventMasterInputToActive e( INPUT_TO_MIX, b->value() );
|
||||
writeToDspRingbuffer( &e );
|
||||
//printf("Mix button\n");
|
||||
}
|
||||
|
||||
static void gmastertrack_sendButton_callback(Fl_Widget *w, void *data)
|
||||
{
|
||||
Avtk::LightButton* b = (Avtk::LightButton*)w;
|
||||
b->value( !b->value() );
|
||||
EventMasterInputToActive e( INPUT_TO_SEND, b->value() );
|
||||
writeToDspRingbuffer( &e );
|
||||
//printf("Send button\n");
|
||||
Avtk::LightButton* b = (Avtk::LightButton*)w;
|
||||
b->value( !b->value() );
|
||||
EventMasterInputToActive e( INPUT_TO_SEND, b->value() );
|
||||
writeToDspRingbuffer( &e );
|
||||
//printf("Send button\n");
|
||||
|
||||
}
|
||||
|
||||
static void gmastertrack_sendVol_callback(Fl_Widget *w, void *data)
|
||||
{
|
||||
Avtk::Dial* b = (Avtk::Dial*)w;
|
||||
float v = b->value();
|
||||
EventMasterInputTo e = EventMasterInputTo( INPUT_TO_SEND, v );
|
||||
writeToDspRingbuffer( &e );
|
||||
///printf("Send dial\n");
|
||||
Avtk::Dial* b = (Avtk::Dial*)w;
|
||||
float v = b->value();
|
||||
EventMasterInputTo e = EventMasterInputTo( INPUT_TO_SEND, v );
|
||||
writeToDspRingbuffer( &e );
|
||||
///printf("Send dial\n");
|
||||
}
|
||||
|
||||
static void gmastertrack_xSideVol_callback(Fl_Widget *w, void *data)
|
||||
{
|
||||
Avtk::Dial* b = (Avtk::Dial*)w;
|
||||
float v = b->value();
|
||||
EventMasterInputTo e = EventMasterInputTo( INPUT_TO_XSIDE, v );
|
||||
writeToDspRingbuffer( &e );
|
||||
//printf("XSide dial\n");
|
||||
Avtk::Dial* b = (Avtk::Dial*)w;
|
||||
float v = b->value();
|
||||
EventMasterInputTo e = EventMasterInputTo( INPUT_TO_XSIDE, v );
|
||||
writeToDspRingbuffer( &e );
|
||||
//printf("XSide dial\n");
|
||||
}
|
||||
|
||||
/// return volume
|
||||
static void gmastertrack_returnVol_callback(Fl_Widget *w, void *data)
|
||||
{
|
||||
Avtk::Dial* b = (Avtk::Dial*)w;
|
||||
float v = b->value();
|
||||
EventMasterReturn e( RETURN_MAIN, v );
|
||||
writeToDspRingbuffer( &e );
|
||||
//printf("Return dial\n");
|
||||
Avtk::Dial* b = (Avtk::Dial*)w;
|
||||
float v = b->value();
|
||||
EventMasterReturn e( RETURN_MAIN, v );
|
||||
writeToDspRingbuffer( &e );
|
||||
//printf("Return dial\n");
|
||||
}
|
||||
|
||||
static void gmastertrack_mixVol_callback(Fl_Widget *w, void *data)
|
||||
{
|
||||
Avtk::Dial* b = (Avtk::Dial*)w;
|
||||
float v = b->value();
|
||||
EventMasterInputTo e = EventMasterInputTo( INPUT_TO_MIX, v );
|
||||
writeToDspRingbuffer( &e );
|
||||
Avtk::Dial* b = (Avtk::Dial*)w;
|
||||
float v = b->value();
|
||||
EventMasterInputTo e = EventMasterInputTo( INPUT_TO_MIX, v );
|
||||
writeToDspRingbuffer( &e );
|
||||
}
|
||||
|
||||
static void gmastertrack_transport_callback(Fl_Widget *w, void *data)
|
||||
{
|
||||
Avtk::LightButton* b = (Avtk::LightButton*)w;
|
||||
if( b->value() )
|
||||
{
|
||||
EventTransportState e = EventTransportState( TRANSPORT_ROLLING );
|
||||
writeToDspRingbuffer( &e );
|
||||
w->label( "Stop" );
|
||||
b->value( 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
EventTransportState e = EventTransportState( TRANSPORT_STOPPED );
|
||||
writeToDspRingbuffer( &e );
|
||||
w->label( "Play" );
|
||||
b->value( 1 );
|
||||
}
|
||||
|
||||
Avtk::LightButton* b = (Avtk::LightButton*)w;
|
||||
if( b->value() ) {
|
||||
EventTransportState e = EventTransportState( TRANSPORT_ROLLING );
|
||||
writeToDspRingbuffer( &e );
|
||||
w->label( "Stop" );
|
||||
b->value( 0 );
|
||||
} else {
|
||||
EventTransportState e = EventTransportState( TRANSPORT_STOPPED );
|
||||
writeToDspRingbuffer( &e );
|
||||
w->label( "Play" );
|
||||
b->value( 1 );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void gmastertrack_button_callback(Fl_Widget *w, void *data)
|
||||
{
|
||||
if ( strcmp( w->label(), "Metro" ) == 0 )
|
||||
{
|
||||
if ( Fl::event_button() == FL_RIGHT_MOUSE )
|
||||
{
|
||||
// popup volume menu: 10 "steps of volume"
|
||||
Fl_Menu_Item rclick_menu[] =
|
||||
{
|
||||
{ "Vol 100%" },
|
||||
{ "Vol 75%" },
|
||||
{ "Vol 50%" },
|
||||
{ "Vol 25%"},
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
Fl_Menu_Item *m = (Fl_Menu_Item*) rclick_menu->popup( Fl::event_x(), Fl::event_y(), 0, 0, 0);
|
||||
|
||||
float v = 0.f;
|
||||
if ( !m )
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if ( strcmp(m->label(), "Vol 100%") == 0 ) {
|
||||
v = 1;
|
||||
}
|
||||
else if ( strcmp(m->label(), "Vol 75%") == 0 ) {
|
||||
v = 0.75;
|
||||
}
|
||||
else if ( strcmp(m->label(), "Vol 50%") == 0 ) {
|
||||
v = 0.5;
|
||||
}
|
||||
else
|
||||
v = 0.25;
|
||||
|
||||
LUPPP_NOTE("metro vol = %f", v );
|
||||
|
||||
EventMetronomeVolume e( v );
|
||||
writeToDspRingbuffer( &e );
|
||||
}
|
||||
else
|
||||
{
|
||||
Avtk::LightButton* b = (Avtk::LightButton*)w;
|
||||
b->value( !b->value() );
|
||||
EventMetronomeActive e = EventMetronomeActive( b->value() );
|
||||
writeToDspRingbuffer( &e );
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
else if ( strcmp( w->label(), "Tap" ) == 0 )
|
||||
{
|
||||
EventTimeTempoTap e;
|
||||
writeToDspRingbuffer( &e );
|
||||
}
|
||||
else
|
||||
{
|
||||
LUPPP_WARN("Error: unknown command string");
|
||||
}
|
||||
if ( strcmp( w->label(), "Metro" ) == 0 ) {
|
||||
if ( Fl::event_button() == FL_RIGHT_MOUSE ) {
|
||||
// popup volume menu: 10 "steps of volume"
|
||||
Fl_Menu_Item rclick_menu[] = {
|
||||
{ "Vol 100%" },
|
||||
{ "Vol 75%" },
|
||||
{ "Vol 50%" },
|
||||
{ "Vol 25%"},
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
Fl_Menu_Item *m = (Fl_Menu_Item*) rclick_menu->popup( Fl::event_x(), Fl::event_y(), 0, 0, 0);
|
||||
|
||||
float v = 0.f;
|
||||
if ( !m ) {
|
||||
return;
|
||||
} else if ( strcmp(m->label(), "Vol 100%") == 0 ) {
|
||||
v = 1;
|
||||
} else if ( strcmp(m->label(), "Vol 75%") == 0 ) {
|
||||
v = 0.75;
|
||||
} else if ( strcmp(m->label(), "Vol 50%") == 0 ) {
|
||||
v = 0.5;
|
||||
} else
|
||||
v = 0.25;
|
||||
|
||||
LUPPP_NOTE("metro vol = %f", v );
|
||||
|
||||
EventMetronomeVolume e( v );
|
||||
writeToDspRingbuffer( &e );
|
||||
} else {
|
||||
Avtk::LightButton* b = (Avtk::LightButton*)w;
|
||||
b->value( !b->value() );
|
||||
EventMetronomeActive e = EventMetronomeActive( b->value() );
|
||||
writeToDspRingbuffer( &e );
|
||||
}
|
||||
|
||||
|
||||
|
||||
} else if ( strcmp( w->label(), "Tap" ) == 0 ) {
|
||||
EventTimeTempoTap e;
|
||||
writeToDspRingbuffer( &e );
|
||||
} else {
|
||||
LUPPP_WARN("Error: unknown command string");
|
||||
}
|
||||
}
|
||||
|
||||
#define OFST 33
|
||||
GMasterTrack::GMasterTrack(int x, int y, int w, int h, const char* l ) :
|
||||
Fl_Group(x, y, w, h),
|
||||
title( strdup(l) ),
|
||||
bg( x, y , w, h, title ),
|
||||
|
||||
// with "true" master flag: launches scenes instead of clips on tracks
|
||||
clipSel(x + 5, y + 26 + 102, 140, 294,"", true),
|
||||
|
||||
source(x+5, y+26, 140, 100, ""),
|
||||
volBox(x+5, y+422, 140, 232, ""),
|
||||
|
||||
transport ( x + w * 2/4.f - 18, y + 436 + OFST * 0, 44,28, "Stop" ),
|
||||
tapTempo ( x + w * 2/4.f - 18, y + 436 + OFST * 1, 44,28, "Tap" ),
|
||||
metronomeButton( x + w * 2/4.f - 18, y + 436 + OFST * 2, 44,28,"Metro"),
|
||||
|
||||
tempoDial ( x + w * 2/4.f - 18, y + 436 + OFST * 3.5, 45, 38,"BPM"),
|
||||
returnVol ( x + w * 2/4.f - 18, y + 436 + OFST * 5, 45, 38,"Return"),
|
||||
|
||||
inputVolume(x + 9,y + 26 + 4, w - 18, 30,""),
|
||||
|
||||
inputToSend (x + 10,y + 28 + 68, 40, 26,"Snd"),
|
||||
inputToSendVol(x + w*0.2-15,y + 28 + 36, 30, 30,""),
|
||||
|
||||
inputToSidechainKey (x + w*0.5-20,y + 28 + 68, 40, 26,"Key"),
|
||||
inputToSidechainSignalVol(x + w*0.5-15,y + 28 + 36, 30, 30,""),
|
||||
|
||||
inputToMix (x + w*0.8-20,y + 28 + 68, 40, 26,"Mix"),
|
||||
inputToMixVol(x + w*0.8-15,y + 28 + 36, 30, 30,""),
|
||||
|
||||
volume(x+106, y +425, 36, 216, "")
|
||||
Fl_Group(x, y, w, h),
|
||||
title( strdup(l) ),
|
||||
bg( x, y , w, h, title ),
|
||||
|
||||
// with "true" master flag: launches scenes instead of clips on tracks
|
||||
clipSel(x + 5, y + 26 + 102, 140, 294,"", true),
|
||||
|
||||
source(x+5, y+26, 140, 100, ""),
|
||||
volBox(x+5, y+422, 140, 232, ""),
|
||||
|
||||
transport ( x + w * 2/4.f - 18, y + 436 + OFST * 0, 44,28, "Stop" ),
|
||||
tapTempo ( x + w * 2/4.f - 18, y + 436 + OFST * 1, 44,28, "Tap" ),
|
||||
metronomeButton( x + w * 2/4.f - 18, y + 436 + OFST * 2, 44,28,"Metro"),
|
||||
|
||||
tempoDial ( x + w * 2/4.f - 18, y + 436 + OFST * 3.5, 45, 38,"BPM"),
|
||||
returnVol ( x + w * 2/4.f - 18, y + 436 + OFST * 5, 45, 38,"Return"),
|
||||
|
||||
inputVolume(x + 9,y + 26 + 4, w - 18, 30,""),
|
||||
|
||||
inputToSend (x + 10,y + 28 + 68, 40, 26,"Snd"),
|
||||
inputToSendVol(x + w*0.2-15,y + 28 + 36, 30, 30,""),
|
||||
|
||||
inputToSidechainKey (x + w*0.5-20,y + 28 + 68, 40, 26,"Key"),
|
||||
inputToSidechainSignalVol(x + w*0.5-15,y + 28 + 36, 30, 30,""),
|
||||
|
||||
inputToMix (x + w*0.8-20,y + 28 + 68, 40, 26,"Mix"),
|
||||
inputToMixVol(x + w*0.8-15,y + 28 + 36, 30, 30,""),
|
||||
|
||||
volume(x+106, y +425, 36, 216, "")
|
||||
{
|
||||
ID = privateID++;
|
||||
|
||||
bar = 0;
|
||||
|
||||
inputVolume.value(0.5);
|
||||
inputVolume.setOrientationHorizontal();
|
||||
|
||||
inputVolume.callback( gmastertrack_inputVolume_callback, 0 );
|
||||
|
||||
transport.callback( gmastertrack_transport_callback, &ID );
|
||||
|
||||
tapTempo.callback( gmastertrack_button_callback, &ID );
|
||||
|
||||
metronomeButton.callback( gmastertrack_button_callback, 0 );
|
||||
|
||||
tempoDial.callback( gmastertrack_tempoDial_callback, 0 );
|
||||
|
||||
inputToSend.setColor( 0, 1.0, 0 );
|
||||
inputToSend.callback( gmastertrack_sendButton_callback, 0 );
|
||||
inputToSendVol.callback( gmastertrack_sendVol_callback, 0 );
|
||||
|
||||
inputToSidechainKey.setColor( 0, 0.6, 1 );
|
||||
inputToSidechainKey.callback( gmastertrack_sidchainKeyButton_callback, 0 );
|
||||
inputToSidechainSignalVol.value( 0 );
|
||||
inputToSidechainSignalVol.callback( gmastertrack_xSideVol_callback, 0 );
|
||||
|
||||
inputToMix.callback ( gmastertrack_mixButton_callback, 0 );
|
||||
inputToMixVol.callback ( gmastertrack_mixVol_callback, 0 );
|
||||
|
||||
tempoDial.align( FL_ALIGN_CENTER );
|
||||
|
||||
returnVol.value( 1.f );
|
||||
returnVol.align( FL_ALIGN_CENTER );
|
||||
returnVol.callback( gmastertrack_returnVol_callback, 0 );
|
||||
|
||||
for(int i = 0; i < 4; i++)
|
||||
{
|
||||
beatLights[i] = new Avtk::LightButton( x + 10, y + 437 + 54 * i, 40, 42, "" );
|
||||
}
|
||||
beatLights[0]->setColor( 1.0, 0.0 , 0.0 );
|
||||
beatLights[1]->setColor( 1.0, 0.48, 0.0 );
|
||||
beatLights[2]->setColor( 1.0, 1.0 , 0.0 );
|
||||
beatLights[3]->setColor( 0.0, 1.0 , 0.0 );
|
||||
|
||||
volume.amplitude( 0.0, 0.0 );
|
||||
volume.callback( gmastertrack_volume_callback, 0 );
|
||||
|
||||
end(); // close the group
|
||||
ID = privateID++;
|
||||
|
||||
bar = 0;
|
||||
|
||||
inputVolume.value(0.5);
|
||||
inputVolume.setOrientationHorizontal();
|
||||
|
||||
inputVolume.callback( gmastertrack_inputVolume_callback, 0 );
|
||||
|
||||
transport.callback( gmastertrack_transport_callback, &ID );
|
||||
|
||||
tapTempo.callback( gmastertrack_button_callback, &ID );
|
||||
|
||||
metronomeButton.callback( gmastertrack_button_callback, 0 );
|
||||
|
||||
tempoDial.callback( gmastertrack_tempoDial_callback, 0 );
|
||||
|
||||
inputToSend.setColor( 0, 1.0, 0 );
|
||||
inputToSend.callback( gmastertrack_sendButton_callback, 0 );
|
||||
inputToSendVol.callback( gmastertrack_sendVol_callback, 0 );
|
||||
|
||||
inputToSidechainKey.setColor( 0, 0.6, 1 );
|
||||
inputToSidechainKey.callback( gmastertrack_sidchainKeyButton_callback, 0 );
|
||||
inputToSidechainSignalVol.value( 0 );
|
||||
inputToSidechainSignalVol.callback( gmastertrack_xSideVol_callback, 0 );
|
||||
|
||||
inputToMix.callback ( gmastertrack_mixButton_callback, 0 );
|
||||
inputToMixVol.callback ( gmastertrack_mixVol_callback, 0 );
|
||||
|
||||
tempoDial.align( FL_ALIGN_CENTER );
|
||||
|
||||
returnVol.value( 1.f );
|
||||
returnVol.align( FL_ALIGN_CENTER );
|
||||
returnVol.callback( gmastertrack_returnVol_callback, 0 );
|
||||
|
||||
for(int i = 0; i < 4; i++) {
|
||||
beatLights[i] = new Avtk::LightButton( x + 10, y + 437 + 54 * i, 40, 42, "" );
|
||||
}
|
||||
beatLights[0]->setColor( 1.0, 0.0 , 0.0 );
|
||||
beatLights[1]->setColor( 1.0, 0.48, 0.0 );
|
||||
beatLights[2]->setColor( 1.0, 1.0 , 0.0 );
|
||||
beatLights[3]->setColor( 0.0, 1.0 , 0.0 );
|
||||
|
||||
volume.amplitude( 0.0, 0.0 );
|
||||
volume.callback( gmastertrack_volume_callback, 0 );
|
||||
|
||||
end(); // close the group
|
||||
}
|
||||
|
||||
void GMasterTrack::setBpm( int b )
|
||||
{
|
||||
bpm = b;
|
||||
tempoDial.value( ( bpm - 60 ) / 160.f );
|
||||
std::stringstream s;
|
||||
s << bpm;
|
||||
tempoDial.setLabel( s.str().c_str() );
|
||||
bpm = b;
|
||||
tempoDial.value( ( bpm - 60 ) / 160.f );
|
||||
std::stringstream s;
|
||||
s << bpm;
|
||||
tempoDial.setLabel( s.str().c_str() );
|
||||
}
|
||||
|
||||
void GMasterTrack::setInputVol(float f)
|
||||
{
|
||||
//LUPPP_NOTE(" gmtrck, inputVol %f", f );
|
||||
inputVolume.value( f );
|
||||
//LUPPP_NOTE(" gmtrck, inputVol %f", f );
|
||||
inputVolume.value( f );
|
||||
}
|
||||
|
||||
void GMasterTrack::setReturnVol(float f)
|
||||
{
|
||||
LUPPP_NOTE(" gmtrck, returnVol %f", f );
|
||||
returnVol.value( f );
|
||||
LUPPP_NOTE(" gmtrck, returnVol %f", f );
|
||||
returnVol.value( f );
|
||||
}
|
||||
|
||||
void GMasterTrack::setInputTo(int to, float f)
|
||||
{
|
||||
//LUPPP_NOTE(" gmtrck, inputTO %i, %f", to, f );
|
||||
if ( to == Event::INPUT_TO_MIX )
|
||||
inputToMixVol.value( f );
|
||||
else if ( to == Event::INPUT_TO_SEND )
|
||||
inputToSendVol.value( f );
|
||||
else if ( to == Event::INPUT_TO_XSIDE )
|
||||
inputToSidechainSignalVol.value( f );
|
||||
//LUPPP_NOTE(" gmtrck, inputTO %i, %f", to, f );
|
||||
if ( to == Event::INPUT_TO_MIX )
|
||||
inputToMixVol.value( f );
|
||||
else if ( to == Event::INPUT_TO_SEND )
|
||||
inputToSendVol.value( f );
|
||||
else if ( to == Event::INPUT_TO_XSIDE )
|
||||
inputToSidechainSignalVol.value( f );
|
||||
}
|
||||
|
||||
void GMasterTrack::setInputToActive(int to, bool f)
|
||||
{
|
||||
//LUPPP_NOTE(" gmtrck, inputToActive %i, %i", to, int(f) );
|
||||
|
||||
if ( to == Event::INPUT_TO_MIX )
|
||||
inputToMix.value( f );
|
||||
else if ( to == Event::INPUT_TO_SEND )
|
||||
inputToSend.value( f );
|
||||
else if ( to == Event::INPUT_TO_SIDE_KEY )
|
||||
inputToSidechainKey.value( f );
|
||||
//LUPPP_NOTE(" gmtrck, inputToActive %i, %i", to, int(f) );
|
||||
|
||||
if ( to == Event::INPUT_TO_MIX )
|
||||
inputToMix.value( f );
|
||||
else if ( to == Event::INPUT_TO_SEND )
|
||||
inputToSend.value( f );
|
||||
else if ( to == Event::INPUT_TO_SIDE_KEY )
|
||||
inputToSidechainKey.value( f );
|
||||
}
|
||||
|
||||
void GMasterTrack::metronomeEnable( bool b )
|
||||
{
|
||||
metronomeButton.value( b );
|
||||
metronomeButton.value( b );
|
||||
}
|
||||
|
||||
int GMasterTrack::getBpm()
|
||||
{
|
||||
return bpm;
|
||||
return bpm;
|
||||
}
|
||||
|
||||
void GMasterTrack::setTapTempo( bool b )
|
||||
{
|
||||
tapTempo.setHighlight( b );
|
||||
tapTempo.setHighlight( b );
|
||||
}
|
||||
|
||||
void GMasterTrack::setBarBeat(int b, int beat)
|
||||
{
|
||||
// FIXME: hard coded 4/4 time here
|
||||
if ( beat % 4 == 0 )
|
||||
{
|
||||
bar = bar % 4 + 1;
|
||||
}
|
||||
|
||||
// turn all off
|
||||
for( int i = 0; i < 4; i++)
|
||||
beatLights[i]->value( 0 );
|
||||
|
||||
// beat starts at 4
|
||||
// FIXME: hard coded 4/4 time
|
||||
beatLights[ 3 - beat%4 ]->value( 1 );
|
||||
// FIXME: hard coded 4/4 time here
|
||||
if ( beat % 4 == 0 ) {
|
||||
bar = bar % 4 + 1;
|
||||
}
|
||||
|
||||
// turn all off
|
||||
for( int i = 0; i < 4; i++)
|
||||
beatLights[i]->value( 0 );
|
||||
|
||||
// beat starts at 4
|
||||
// FIXME: hard coded 4/4 time
|
||||
beatLights[ 3 - beat%4 ]->value( 1 );
|
||||
}
|
||||
|
||||
Avtk::Volume* GMasterTrack::getInputVolume()
|
||||
{
|
||||
return &inputVolume;
|
||||
return &inputVolume;
|
||||
}
|
||||
Avtk::Volume* GMasterTrack::getVolume()
|
||||
{
|
||||
return &volume;
|
||||
return &volume;
|
||||
}
|
||||
|
||||
Avtk::LightButton* GMasterTrack::getInputToSend()
|
||||
{
|
||||
return &inputToSend;
|
||||
return &inputToSend;
|
||||
}
|
||||
Avtk::LightButton* GMasterTrack::getInputToSidechainKey()
|
||||
{
|
||||
return &inputToSidechainKey;
|
||||
return &inputToSidechainKey;
|
||||
}
|
||||
Avtk::LightButton* GMasterTrack::getInputToMix()
|
||||
{
|
||||
return &inputToMix;
|
||||
return &inputToMix;
|
||||
}
|
||||
|
||||
Avtk::Dial* GMasterTrack::getInputToSendVol()
|
||||
{
|
||||
return &inputToSendVol;
|
||||
return &inputToSendVol;
|
||||
}
|
||||
Avtk::Dial* GMasterTrack::getInputToXSide()
|
||||
{
|
||||
return &inputToSidechainSignalVol;
|
||||
return &inputToSidechainSignalVol;
|
||||
}
|
||||
Avtk::Dial* GMasterTrack::getInputToMixVol()
|
||||
{
|
||||
return &inputToMixVol;
|
||||
return &inputToMixVol;
|
||||
}
|
||||
|
||||
|
||||
Avtk::ClipSelector* GMasterTrack::getClipSelector()
|
||||
{
|
||||
return &clipSel;
|
||||
return &clipSel;
|
||||
}
|
||||
|
||||
GMasterTrack::~GMasterTrack()
|
||||
{
|
||||
free(title);
|
||||
free(title);
|
||||
}
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -45,72 +45,72 @@ using namespace std;
|
|||
|
||||
class GMasterTrack : public Fl_Group
|
||||
{
|
||||
public:
|
||||
GMasterTrack(int x, int y, int w, int h, const char* l = 0 );
|
||||
|
||||
int getBpm();
|
||||
void setBpm( int bpm );
|
||||
void setTapTempo( bool b );
|
||||
void setBarBeat(int b, int beat);
|
||||
|
||||
void setReturnVol(float f);
|
||||
void setInputVol(float f);
|
||||
void setInputTo(int to, float f);
|
||||
void setInputToActive(int to, bool f);
|
||||
|
||||
void metronomeEnable( bool b );
|
||||
|
||||
Avtk::Volume* getInputVolume();
|
||||
Avtk::Volume* getVolume();
|
||||
Avtk::ClipSelector* getClipSelector();
|
||||
|
||||
Avtk::LightButton* getInputToSend();
|
||||
Avtk::LightButton* getInputToSidechainKey();
|
||||
Avtk::LightButton* getInputToMix();
|
||||
|
||||
Avtk::Dial* getInputToSendVol();
|
||||
Avtk::Dial* getInputToXSide();
|
||||
Avtk::Dial* getInputToMixVol();
|
||||
|
||||
~GMasterTrack();
|
||||
|
||||
private:
|
||||
int ID;
|
||||
char* title;
|
||||
|
||||
int bar;
|
||||
int bpm;
|
||||
|
||||
Avtk::Background bg;
|
||||
|
||||
Avtk::ClipSelector clipSel;
|
||||
|
||||
Avtk::Box source;
|
||||
Avtk::Box volBox;
|
||||
|
||||
Avtk::Button transport;
|
||||
Avtk::Button tapTempo;
|
||||
Avtk::LightButton metronomeButton;
|
||||
Avtk::Dial tempoDial;
|
||||
|
||||
Avtk::Dial returnVol;
|
||||
|
||||
Avtk::LightButton* beatLights[4];
|
||||
|
||||
Avtk::Volume inputVolume;
|
||||
|
||||
Avtk::LightButton inputToSend;
|
||||
Avtk::Dial inputToSendVol;
|
||||
|
||||
Avtk::LightButton inputToSidechainKey;
|
||||
Avtk::Dial inputToSidechainSignalVol;
|
||||
|
||||
Avtk::LightButton inputToMix;
|
||||
Avtk::Dial inputToMixVol;
|
||||
|
||||
Avtk::Volume volume;
|
||||
|
||||
static int privateID;
|
||||
public:
|
||||
GMasterTrack(int x, int y, int w, int h, const char* l = 0 );
|
||||
|
||||
int getBpm();
|
||||
void setBpm( int bpm );
|
||||
void setTapTempo( bool b );
|
||||
void setBarBeat(int b, int beat);
|
||||
|
||||
void setReturnVol(float f);
|
||||
void setInputVol(float f);
|
||||
void setInputTo(int to, float f);
|
||||
void setInputToActive(int to, bool f);
|
||||
|
||||
void metronomeEnable( bool b );
|
||||
|
||||
Avtk::Volume* getInputVolume();
|
||||
Avtk::Volume* getVolume();
|
||||
Avtk::ClipSelector* getClipSelector();
|
||||
|
||||
Avtk::LightButton* getInputToSend();
|
||||
Avtk::LightButton* getInputToSidechainKey();
|
||||
Avtk::LightButton* getInputToMix();
|
||||
|
||||
Avtk::Dial* getInputToSendVol();
|
||||
Avtk::Dial* getInputToXSide();
|
||||
Avtk::Dial* getInputToMixVol();
|
||||
|
||||
~GMasterTrack();
|
||||
|
||||
private:
|
||||
int ID;
|
||||
char* title;
|
||||
|
||||
int bar;
|
||||
int bpm;
|
||||
|
||||
Avtk::Background bg;
|
||||
|
||||
Avtk::ClipSelector clipSel;
|
||||
|
||||
Avtk::Box source;
|
||||
Avtk::Box volBox;
|
||||
|
||||
Avtk::Button transport;
|
||||
Avtk::Button tapTempo;
|
||||
Avtk::LightButton metronomeButton;
|
||||
Avtk::Dial tempoDial;
|
||||
|
||||
Avtk::Dial returnVol;
|
||||
|
||||
Avtk::LightButton* beatLights[4];
|
||||
|
||||
Avtk::Volume inputVolume;
|
||||
|
||||
Avtk::LightButton inputToSend;
|
||||
Avtk::Dial inputToSendVol;
|
||||
|
||||
Avtk::LightButton inputToSidechainKey;
|
||||
Avtk::Dial inputToSidechainSignalVol;
|
||||
|
||||
Avtk::LightButton inputToMix;
|
||||
Avtk::Dial inputToMixVol;
|
||||
|
||||
Avtk::Volume volume;
|
||||
|
||||
static int privateID;
|
||||
};
|
||||
|
||||
#endif // LUPPP_G_MASTER_TRACK_H
|
||||
|
|
685
src/goptions.cxx
685
src/goptions.cxx
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -33,449 +33,432 @@ extern Gui* gui;
|
|||
|
||||
static void addControllerUiDsp(OptionsWindow* self, GenericMIDI* c)
|
||||
{
|
||||
// add the controller to the UI
|
||||
int x, y, w, h;
|
||||
self->tabs->client_area( x, y, w, h, 25 );
|
||||
self->controllers.push_back( new ControllerUI( x, y, w, h, c->getName().c_str(), c->getID() ) );
|
||||
|
||||
// store the pointer to the options window: needed to make remove button work
|
||||
self->controllers.back()->optionsWindow = self;
|
||||
|
||||
LUPPP_NOTE("Added controller %s, ID %i", c->getName().c_str(), c->getID() );
|
||||
// add the controller to the UI
|
||||
int x, y, w, h;
|
||||
self->tabs->client_area( x, y, w, h, 25 );
|
||||
self->controllers.push_back( new ControllerUI( x, y, w, h, c->getName().c_str(), c->getID() ) );
|
||||
|
||||
// add widget before "add" button
|
||||
self->tabs->insert( *self->controllers.back()->widget, self->addGroup );
|
||||
|
||||
// tell the ControllerUI to add the bindings from this Controller*
|
||||
self->controllers.back()->setAuthor( c->getAuthor() );
|
||||
self->controllers.back()->setLink( c->getEmail() );
|
||||
self->controllers.back()->addBindings( c );
|
||||
|
||||
self->tabs->redraw();
|
||||
|
||||
// send to DSP side
|
||||
EventControllerInstance e(c);
|
||||
writeToDspRingbuffer( &e );
|
||||
// store the pointer to the options window: needed to make remove button work
|
||||
self->controllers.back()->optionsWindow = self;
|
||||
|
||||
LUPPP_NOTE("Added controller %s, ID %i", c->getName().c_str(), c->getID() );
|
||||
|
||||
// add widget before "add" button
|
||||
self->tabs->insert( *self->controllers.back()->widget, self->addGroup );
|
||||
|
||||
// tell the ControllerUI to add the bindings from this Controller*
|
||||
self->controllers.back()->setAuthor( c->getAuthor() );
|
||||
self->controllers.back()->setLink( c->getEmail() );
|
||||
self->controllers.back()->addBindings( c );
|
||||
|
||||
self->tabs->redraw();
|
||||
|
||||
// send to DSP side
|
||||
EventControllerInstance e(c);
|
||||
writeToDspRingbuffer( &e );
|
||||
}
|
||||
|
||||
static void updateAuthorCB(Fl_Widget* w, void* data)
|
||||
{
|
||||
ControllerUI* c = (ControllerUI*)data;
|
||||
const char* s = fl_input( "Author: ", "" );
|
||||
if ( s )
|
||||
{
|
||||
c->setAuthor( s );
|
||||
}
|
||||
ControllerUI* c = (ControllerUI*)data;
|
||||
const char* s = fl_input( "Author: ", "" );
|
||||
if ( s ) {
|
||||
c->setAuthor( s );
|
||||
}
|
||||
}
|
||||
|
||||
static void updateLinkCB(Fl_Widget* w, void* data)
|
||||
{
|
||||
ControllerUI* c = (ControllerUI*)data;
|
||||
|
||||
stringstream str;
|
||||
str << "xdg-open ";
|
||||
|
||||
// add http:// if its not in the string
|
||||
std::string l = c->getLink();
|
||||
if ( ( l.find("http") ) == std::string::npos )
|
||||
str << " http://";
|
||||
|
||||
str << l;
|
||||
|
||||
system( str.str().c_str() );
|
||||
ControllerUI* c = (ControllerUI*)data;
|
||||
|
||||
stringstream str;
|
||||
str << "xdg-open ";
|
||||
|
||||
// add http:// if its not in the string
|
||||
std::string l = c->getLink();
|
||||
if ( ( l.find("http") ) == std::string::npos )
|
||||
str << " http://";
|
||||
|
||||
str << l;
|
||||
|
||||
system( str.str().c_str() );
|
||||
}
|
||||
|
||||
static void writeBindEnable(Fl_Widget* w, void* data)
|
||||
{
|
||||
OptionsWindow* o = (OptionsWindow*) data;
|
||||
//LUPPP_NOTE("MIDI bind mode");
|
||||
|
||||
Avtk::LightButton* l = (Avtk::LightButton*)w;
|
||||
l->value( !l->value() );
|
||||
|
||||
int controllerID = -1; // waste?
|
||||
EventControllerBindingEnable e( controllerID, l->value() );
|
||||
writeToDspRingbuffer( &e );
|
||||
OptionsWindow* o = (OptionsWindow*) data;
|
||||
//LUPPP_NOTE("MIDI bind mode");
|
||||
|
||||
Avtk::LightButton* l = (Avtk::LightButton*)w;
|
||||
l->value( !l->value() );
|
||||
|
||||
int controllerID = -1; // waste?
|
||||
EventControllerBindingEnable e( controllerID, l->value() );
|
||||
writeToDspRingbuffer( &e );
|
||||
}
|
||||
|
||||
static void removeControllerCB(Fl_Widget* w, void* data)
|
||||
{
|
||||
ControllerUI* self = (ControllerUI*)data;
|
||||
|
||||
// Remove UI tab for that controller
|
||||
// should return "tabs" from OptionsWindow
|
||||
self->optionsWindow->tabs->remove( self->widget );
|
||||
self->optionsWindow->tabs->redraw();
|
||||
|
||||
// FIXME: confirm action here?
|
||||
|
||||
//LUPPP_NOTE("Removing controllerID %i", self->controllerID );
|
||||
EventControllerInstanceRemove e( self->controllerID );
|
||||
writeToDspRingbuffer( &e );
|
||||
|
||||
delete self;
|
||||
ControllerUI* self = (ControllerUI*)data;
|
||||
|
||||
// Remove UI tab for that controller
|
||||
// should return "tabs" from OptionsWindow
|
||||
self->optionsWindow->tabs->remove( self->widget );
|
||||
self->optionsWindow->tabs->redraw();
|
||||
|
||||
// FIXME: confirm action here?
|
||||
|
||||
//LUPPP_NOTE("Removing controllerID %i", self->controllerID );
|
||||
EventControllerInstanceRemove e( self->controllerID );
|
||||
writeToDspRingbuffer( &e );
|
||||
|
||||
delete self;
|
||||
}
|
||||
|
||||
static void addNewController(Fl_Widget* w, void* ud)
|
||||
{
|
||||
OptionsWindow* self = (OptionsWindow*)ud;
|
||||
LUPPP_NOTE("%s","ADD Controller cb");
|
||||
|
||||
GenericMIDI* c = 0;
|
||||
|
||||
const char* name = fl_input( "Controller name: ", "" );
|
||||
if ( name )
|
||||
{
|
||||
c = new GenericMIDI( 0, name);
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if ( c->status() == Controller::CONTROLLER_OK )
|
||||
{
|
||||
addControllerUiDsp( self, c );
|
||||
}
|
||||
else
|
||||
{
|
||||
LUPPP_ERROR("Controller initialization failed!");
|
||||
}
|
||||
OptionsWindow* self = (OptionsWindow*)ud;
|
||||
LUPPP_NOTE("%s","ADD Controller cb");
|
||||
|
||||
GenericMIDI* c = 0;
|
||||
|
||||
const char* name = fl_input( "Controller name: ", "" );
|
||||
if ( name ) {
|
||||
c = new GenericMIDI( 0, name);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if ( c->status() == Controller::CONTROLLER_OK ) {
|
||||
addControllerUiDsp( self, c );
|
||||
} else {
|
||||
LUPPP_ERROR("Controller initialization failed!");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void selectLoadController(Fl_Widget* w, void* data)
|
||||
{
|
||||
OptionsWindow* self = (OptionsWindow*)data;
|
||||
|
||||
// FIXME: refactor
|
||||
string path;
|
||||
Fl_Native_File_Chooser fnfc;
|
||||
fnfc.title("Pick a controller definition");
|
||||
fnfc.type(Fl_Native_File_Chooser::BROWSE_FILE);
|
||||
fnfc.filter("Controllers\t*.ctlr");
|
||||
|
||||
stringstream s;
|
||||
s << getenv("HOME") << "/.config/openAV/luppp/controllers/";
|
||||
fnfc.directory( s.str().c_str() ); // default directory to use
|
||||
// Show native chooser
|
||||
switch ( fnfc.show() ) {
|
||||
case -1: /*printf("ERROR: %s\n", fnfc.errmsg());*/ break; // ERROR
|
||||
case 1: /*printf("CANCEL\n"); */ break; // CANCEL
|
||||
default:
|
||||
//printf("Loading controller at %s\n", fnfc.filename());
|
||||
path = fnfc.filename();
|
||||
break;
|
||||
}
|
||||
|
||||
if ( strcmp( path.c_str(), "" ) == 0 )
|
||||
return;
|
||||
|
||||
//LUPPP_NOTE("%s","ADD Controller cb");
|
||||
GenericMIDI* c = new GenericMIDI( path );
|
||||
|
||||
if ( c->status() == Controller::CONTROLLER_OK )
|
||||
{
|
||||
addControllerUiDsp( self, c );
|
||||
}
|
||||
else
|
||||
{
|
||||
LUPPP_ERROR("Controller initialization failed!");
|
||||
}
|
||||
OptionsWindow* self = (OptionsWindow*)data;
|
||||
|
||||
// FIXME: refactor
|
||||
string path;
|
||||
Fl_Native_File_Chooser fnfc;
|
||||
fnfc.title("Pick a controller definition");
|
||||
fnfc.type(Fl_Native_File_Chooser::BROWSE_FILE);
|
||||
fnfc.filter("Controllers\t*.ctlr");
|
||||
|
||||
stringstream s;
|
||||
s << getenv("HOME") << "/.config/openAV/luppp/controllers/";
|
||||
fnfc.directory( s.str().c_str() ); // default directory to use
|
||||
// Show native chooser
|
||||
switch ( fnfc.show() ) {
|
||||
case -1: /*printf("ERROR: %s\n", fnfc.errmsg());*/
|
||||
break; // ERROR
|
||||
case 1: /*printf("CANCEL\n"); */
|
||||
break; // CANCEL
|
||||
default:
|
||||
//printf("Loading controller at %s\n", fnfc.filename());
|
||||
path = fnfc.filename();
|
||||
break;
|
||||
}
|
||||
|
||||
if ( strcmp( path.c_str(), "" ) == 0 )
|
||||
return;
|
||||
|
||||
//LUPPP_NOTE("%s","ADD Controller cb");
|
||||
GenericMIDI* c = new GenericMIDI( path );
|
||||
|
||||
if ( c->status() == Controller::CONTROLLER_OK ) {
|
||||
addControllerUiDsp( self, c );
|
||||
} else {
|
||||
LUPPP_ERROR("Controller initialization failed!");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void writeControllerFile(Fl_Widget* w, void* data)
|
||||
{
|
||||
ControllerUI* c = (ControllerUI*)data;
|
||||
|
||||
LUPPP_NOTE("Writing controller %li, %s ID %i .ctlr to disk", c, c->name.c_str(), c->controllerID );
|
||||
|
||||
// Set the Controller details in diskWriter, so it write it pretty
|
||||
gui->getDiskWriter()->writeControllerInfo( CONTROLLER_NAME , c->name );
|
||||
gui->getDiskWriter()->writeControllerInfo( CONTROLLER_AUTHOR, c->getAuthor());
|
||||
gui->getDiskWriter()->writeControllerInfo( CONTROLLER_LINK , c->getLink() );
|
||||
|
||||
EventControllerInstanceGetToWrite e( c->controllerID );
|
||||
writeToDspRingbuffer( &e );
|
||||
ControllerUI* c = (ControllerUI*)data;
|
||||
|
||||
LUPPP_NOTE("Writing controller %li, %s ID %i .ctlr to disk", c, c->name.c_str(), c->controllerID );
|
||||
|
||||
// Set the Controller details in diskWriter, so it write it pretty
|
||||
gui->getDiskWriter()->writeControllerInfo( CONTROLLER_NAME , c->name );
|
||||
gui->getDiskWriter()->writeControllerInfo( CONTROLLER_AUTHOR, c->getAuthor());
|
||||
gui->getDiskWriter()->writeControllerInfo( CONTROLLER_LINK , c->getLink() );
|
||||
|
||||
EventControllerInstanceGetToWrite e( c->controllerID );
|
||||
writeToDspRingbuffer( &e );
|
||||
}
|
||||
|
||||
|
||||
static void deleteBindingFromController(Fl_Widget* w, void* ud)
|
||||
{
|
||||
ControllerUI* self = (ControllerUI*)ud;
|
||||
stringstream s;
|
||||
s << w->label();
|
||||
int tmp;
|
||||
s >> tmp;
|
||||
LUPPP_NOTE("CtlrID %i: Deleting binding with ID %i", self->controllerID, tmp );
|
||||
|
||||
EventControllerBindingRemove e( self->controllerID, tmp );
|
||||
writeToDspRingbuffer( &e );
|
||||
|
||||
// remove "this" widget (and its parent Pack) from the list of MIDI bindings:
|
||||
self->bindingsPack->remove( w->parent() );
|
||||
self->bindingsPack->redraw();
|
||||
self->scroll->redraw();
|
||||
ControllerUI* self = (ControllerUI*)ud;
|
||||
stringstream s;
|
||||
s << w->label();
|
||||
int tmp;
|
||||
s >> tmp;
|
||||
LUPPP_NOTE("CtlrID %i: Deleting binding with ID %i", self->controllerID, tmp );
|
||||
|
||||
EventControllerBindingRemove e( self->controllerID, tmp );
|
||||
writeToDspRingbuffer( &e );
|
||||
|
||||
// remove "this" widget (and its parent Pack) from the list of MIDI bindings:
|
||||
self->bindingsPack->remove( w->parent() );
|
||||
self->bindingsPack->redraw();
|
||||
self->scroll->redraw();
|
||||
}
|
||||
|
||||
|
||||
ControllerUI::ControllerUI(int x, int y, int w, int h, std::string n, int ID)
|
||||
{
|
||||
name = n;
|
||||
|
||||
widget = new Fl_Group( x, y, w, h, name.c_str());
|
||||
{
|
||||
// author / link
|
||||
authorLabel = new Avtk::Button( x + 5, y + 5, 190, 25, "Author?" );
|
||||
linkLabel = new Avtk::Button( x + 7+ w/2, y + 5, 190, 25, "Link?" );
|
||||
|
||||
authorLabel->label("Author?");
|
||||
authorLabel->label("Link?");
|
||||
|
||||
authorLabel->callback( updateAuthorCB, this );
|
||||
linkLabel->callback( updateLinkCB, this );
|
||||
|
||||
// binding / target
|
||||
targetLabelStat = new Fl_Box(x + 100,y + 32, 75, 25,"Target: ");
|
||||
targetLabel = new Fl_Box(x + 140,y + 32, 200, 25,"");
|
||||
bindEnable = new Avtk::LightButton(x + 5, y + 32, 100, 25, "Bind Enable");
|
||||
|
||||
writeControllerBtn = new Avtk::Button( x + 5, y + h - 27, 100, 25, "Save" );
|
||||
removeController = new Avtk::Button( x + 110, y + h - 27, 100, 25, "Remove");
|
||||
|
||||
scroll = new Fl_Scroll( x + 5, y + 82, 395, 265 );
|
||||
{
|
||||
bindingsPack = new Fl_Pack( x + 5, y + 82, w - 15, 270-10);
|
||||
bindingsPack->end();
|
||||
bindingsPack->spacing( 2 );
|
||||
bindingsPack->box(FL_DOWN_FRAME);
|
||||
}
|
||||
scroll->resizable( bindingsPack );
|
||||
scroll->box( FL_DOWN_FRAME );
|
||||
scroll->type( Fl_Scroll::VERTICAL_ALWAYS );
|
||||
scroll->end();
|
||||
|
||||
widget->resizable( scroll );
|
||||
}
|
||||
widget->end();
|
||||
|
||||
widget->redraw();
|
||||
|
||||
// save the controller ID this ControllerUI represents
|
||||
controllerID = ID;
|
||||
LUPPP_NOTE("Controller %li ID on create %i", this, controllerID );
|
||||
|
||||
//ctlrButton->callback( selectLoadController );
|
||||
bindEnable->callback( writeBindEnable, this );
|
||||
removeController->callback( removeControllerCB, this );
|
||||
writeControllerBtn->callback( writeControllerFile, this );
|
||||
name = n;
|
||||
|
||||
widget = new Fl_Group( x, y, w, h, name.c_str());
|
||||
{
|
||||
// author / link
|
||||
authorLabel = new Avtk::Button( x + 5, y + 5, 190, 25, "Author?" );
|
||||
linkLabel = new Avtk::Button( x + 7+ w/2, y + 5, 190, 25, "Link?" );
|
||||
|
||||
authorLabel->label("Author?");
|
||||
authorLabel->label("Link?");
|
||||
|
||||
authorLabel->callback( updateAuthorCB, this );
|
||||
linkLabel->callback( updateLinkCB, this );
|
||||
|
||||
// binding / target
|
||||
targetLabelStat = new Fl_Box(x + 100,y + 32, 75, 25,"Target: ");
|
||||
targetLabel = new Fl_Box(x + 140,y + 32, 200, 25,"");
|
||||
bindEnable = new Avtk::LightButton(x + 5, y + 32, 100, 25, "Bind Enable");
|
||||
|
||||
writeControllerBtn = new Avtk::Button( x + 5, y + h - 27, 100, 25, "Save" );
|
||||
removeController = new Avtk::Button( x + 110, y + h - 27, 100, 25, "Remove");
|
||||
|
||||
scroll = new Fl_Scroll( x + 5, y + 82, 395, 265 );
|
||||
{
|
||||
bindingsPack = new Fl_Pack( x + 5, y + 82, w - 15, 270-10);
|
||||
bindingsPack->end();
|
||||
bindingsPack->spacing( 2 );
|
||||
bindingsPack->box(FL_DOWN_FRAME);
|
||||
}
|
||||
scroll->resizable( bindingsPack );
|
||||
scroll->box( FL_DOWN_FRAME );
|
||||
scroll->type( Fl_Scroll::VERTICAL_ALWAYS );
|
||||
scroll->end();
|
||||
|
||||
widget->resizable( scroll );
|
||||
}
|
||||
widget->end();
|
||||
|
||||
widget->redraw();
|
||||
|
||||
// save the controller ID this ControllerUI represents
|
||||
controllerID = ID;
|
||||
LUPPP_NOTE("Controller %li ID on create %i", this, controllerID );
|
||||
|
||||
//ctlrButton->callback( selectLoadController );
|
||||
bindEnable->callback( writeBindEnable, this );
|
||||
removeController->callback( removeControllerCB, this );
|
||||
writeControllerBtn->callback( writeControllerFile, this );
|
||||
}
|
||||
|
||||
void OptionsWindow::setTarget(const char* n)
|
||||
{
|
||||
for(unsigned int i = 0; i < controllers.size(); i++ )
|
||||
{
|
||||
controllers.at(i)->setTarget( n );
|
||||
}
|
||||
for(unsigned int i = 0; i < controllers.size(); i++ ) {
|
||||
controllers.at(i)->setTarget( n );
|
||||
}
|
||||
}
|
||||
|
||||
void ControllerUI::setTarget( const char* n )
|
||||
{
|
||||
target = n;
|
||||
targetLabel->label( target.c_str() );
|
||||
targetLabel->redraw();
|
||||
target = n;
|
||||
targetLabel->label( target.c_str() );
|
||||
targetLabel->redraw();
|
||||
}
|
||||
|
||||
void ControllerUI::setAuthor(std::string a)
|
||||
{
|
||||
author = a;
|
||||
authorLabel->label( author.c_str() );
|
||||
authorLabel->redraw();
|
||||
author = a;
|
||||
authorLabel->label( author.c_str() );
|
||||
authorLabel->redraw();
|
||||
}
|
||||
|
||||
void ControllerUI::setLink(std::string e)
|
||||
{
|
||||
link = e;
|
||||
linkLabel->label( link.c_str() );
|
||||
linkLabel->redraw();
|
||||
link = e;
|
||||
linkLabel->label( link.c_str() );
|
||||
linkLabel->redraw();
|
||||
}
|
||||
|
||||
void ControllerUI::setBindEnable( bool b )
|
||||
{
|
||||
bindEnable->value( b );
|
||||
bindEnable->value( b );
|
||||
}
|
||||
|
||||
void ControllerUI::addBinding( Binding* b )
|
||||
{
|
||||
if ( b->action != EVENT_NULL )
|
||||
{
|
||||
// add individual bindings as they're made
|
||||
const char* tmp = Event::getPrettyName( b->action );
|
||||
if ( !tmp )
|
||||
{
|
||||
if ( b->action != EVENT_NULL ) {
|
||||
// add individual bindings as they're made
|
||||
const char* tmp = Event::getPrettyName( b->action );
|
||||
if ( !tmp ) {
|
||||
#ifdef DEBUG_MIDI
|
||||
LUPPP_NOTE("new binding, action string returned NULL, action number %i ", b->action );
|
||||
LUPPP_NOTE("new binding, action string returned NULL, action number %i ", b->action );
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LUPPP_WARN("new binding, action: == EVENT_NULL" );
|
||||
return;
|
||||
}
|
||||
|
||||
// push the bindingID onto the vector
|
||||
bindingID.push_back( b->ID );
|
||||
|
||||
// create a horizontal pack, add that to the bindingsPack
|
||||
Fl_Pack* tmp = new Fl_Pack( 35, 35, 25, 25);
|
||||
{
|
||||
tmp->type( Fl_Pack::HORIZONTAL );
|
||||
tmp->spacing( 2 );
|
||||
|
||||
stringstream s;
|
||||
|
||||
if ( b->action == MASTER_VOL )
|
||||
s << "Master Volume";
|
||||
else if ( false )
|
||||
s << "stuff";
|
||||
else
|
||||
s << Event::getPrettyName( b->action );
|
||||
|
||||
|
||||
|
||||
if (b->track != -2)
|
||||
s << " Track:" << b->track + 1;
|
||||
|
||||
if (b->scene != -1)
|
||||
s << " Scene:" << b->scene + 1;
|
||||
|
||||
if ( b->send == Event::SEND_POSTFADER )
|
||||
s << " Post-fader Send";
|
||||
if ( b->send == Event::SEND_XSIDE )
|
||||
s << " Sidechain Crossfade";
|
||||
if ( b->send == Event::SEND_KEY )
|
||||
s << " Sidechain Key";
|
||||
|
||||
if ( b->active != -1)
|
||||
{
|
||||
if ( b->active == true )
|
||||
s << " On";
|
||||
if ( b->active == false )
|
||||
s << " Off";
|
||||
}
|
||||
|
||||
// button to remove a binding, uses bindingsID vector to get unique number
|
||||
stringstream id;
|
||||
id << b->ID;
|
||||
Fl_Button* but = new Fl_Button(35, 35, 25, 25, strdup(id.str().c_str() ) );
|
||||
but->callback( deleteBindingFromController, this );
|
||||
but->redraw();
|
||||
|
||||
Fl_Box* b = new Fl_Box(35, 35, 400, 25, strdup(s.str().c_str()) );
|
||||
b->align( FL_ALIGN_LEFT | FL_ALIGN_INSIDE );
|
||||
b->redraw();
|
||||
}
|
||||
tmp->end();
|
||||
|
||||
// push the binding to the UI pack, *and* store its binding ID in the same
|
||||
// array element in the bindingID vector. Used to remove bindings
|
||||
bindingsPack->add( tmp );
|
||||
|
||||
bindingsPack->resize( bindingsPack->x(),bindingsPack->y(),bindingsPack->w(),bindingsPack->children() * 36 );
|
||||
bindingsPack->redraw();
|
||||
scroll->redraw();
|
||||
|
||||
//LUPPP_NOTE("binding size %i %i", bindingsPack->w(), bindingsPack->h() );
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
LUPPP_WARN("new binding, action: == EVENT_NULL" );
|
||||
return;
|
||||
}
|
||||
|
||||
// push the bindingID onto the vector
|
||||
bindingID.push_back( b->ID );
|
||||
|
||||
// create a horizontal pack, add that to the bindingsPack
|
||||
Fl_Pack* tmp = new Fl_Pack( 35, 35, 25, 25);
|
||||
{
|
||||
tmp->type( Fl_Pack::HORIZONTAL );
|
||||
tmp->spacing( 2 );
|
||||
|
||||
stringstream s;
|
||||
|
||||
if ( b->action == MASTER_VOL )
|
||||
s << "Master Volume";
|
||||
else if ( false )
|
||||
s << "stuff";
|
||||
else
|
||||
s << Event::getPrettyName( b->action );
|
||||
|
||||
|
||||
|
||||
if (b->track != -2)
|
||||
s << " Track:" << b->track + 1;
|
||||
|
||||
if (b->scene != -1)
|
||||
s << " Scene:" << b->scene + 1;
|
||||
|
||||
if ( b->send == Event::SEND_POSTFADER )
|
||||
s << " Post-fader Send";
|
||||
if ( b->send == Event::SEND_XSIDE )
|
||||
s << " Sidechain Crossfade";
|
||||
if ( b->send == Event::SEND_KEY )
|
||||
s << " Sidechain Key";
|
||||
|
||||
if ( b->active != -1) {
|
||||
if ( b->active == true )
|
||||
s << " On";
|
||||
if ( b->active == false )
|
||||
s << " Off";
|
||||
}
|
||||
|
||||
// button to remove a binding, uses bindingsID vector to get unique number
|
||||
stringstream id;
|
||||
id << b->ID;
|
||||
Fl_Button* but = new Fl_Button(35, 35, 25, 25, strdup(id.str().c_str() ) );
|
||||
but->callback( deleteBindingFromController, this );
|
||||
but->redraw();
|
||||
|
||||
Fl_Box* b = new Fl_Box(35, 35, 400, 25, strdup(s.str().c_str()) );
|
||||
b->align( FL_ALIGN_LEFT | FL_ALIGN_INSIDE );
|
||||
b->redraw();
|
||||
}
|
||||
tmp->end();
|
||||
|
||||
// push the binding to the UI pack, *and* store its binding ID in the same
|
||||
// array element in the bindingID vector. Used to remove bindings
|
||||
bindingsPack->add( tmp );
|
||||
|
||||
bindingsPack->resize( bindingsPack->x(),bindingsPack->y(),bindingsPack->w(),bindingsPack->children() * 36 );
|
||||
bindingsPack->redraw();
|
||||
scroll->redraw();
|
||||
|
||||
//LUPPP_NOTE("binding size %i %i", bindingsPack->w(), bindingsPack->h() );
|
||||
}
|
||||
|
||||
void ControllerUI::addBindings( GenericMIDI* c )
|
||||
{
|
||||
std::vector<Binding*> bindingVector= c->getMidiToAction();
|
||||
|
||||
for(unsigned int i = 0; i < bindingVector.size(); i++ )
|
||||
{
|
||||
addBinding( bindingVector.at(i) );
|
||||
}
|
||||
std::vector<Binding*> bindingVector= c->getMidiToAction();
|
||||
|
||||
for(unsigned int i = 0; i < bindingVector.size(); i++ ) {
|
||||
addBinding( bindingVector.at(i) );
|
||||
}
|
||||
}
|
||||
|
||||
ControllerUI::~ControllerUI()
|
||||
{
|
||||
|
||||
// free all binding resources here:
|
||||
|
||||
|
||||
delete authorLabel;
|
||||
delete linkLabel;
|
||||
|
||||
delete targetLabel;
|
||||
delete targetLabelStat;
|
||||
delete bindEnable;
|
||||
delete removeController;
|
||||
delete writeControllerBtn;
|
||||
|
||||
// free all binding resources here:
|
||||
|
||||
|
||||
delete authorLabel;
|
||||
delete linkLabel;
|
||||
|
||||
delete targetLabel;
|
||||
delete targetLabelStat;
|
||||
delete bindEnable;
|
||||
delete removeController;
|
||||
delete writeControllerBtn;
|
||||
}
|
||||
|
||||
OptionsWindow::OptionsWindow()
|
||||
{
|
||||
window = new Fl_Double_Window(400,400,"Options");
|
||||
|
||||
window->set_non_modal();
|
||||
|
||||
tabs = new Fl_Tabs(0, 0, 400, 400);
|
||||
|
||||
window->resizable( tabs );
|
||||
|
||||
int x, y, w, h;
|
||||
tabs->client_area( x, y, w, h, 25 );
|
||||
|
||||
addGroup = new Fl_Group(x,y,w,h,"Add");
|
||||
{
|
||||
newButton = new Avtk::Button( x+2, y+2, w-4, 30, "New Generic MIDI");
|
||||
loadButton = new Avtk::Button( x+2, y+2+32, w-4, 30, "Load Generic MIDI");
|
||||
}
|
||||
addGroup->end();
|
||||
tabs->end();
|
||||
|
||||
newButton ->callback( addNewController, this );
|
||||
loadButton->callback( selectLoadController, this );
|
||||
|
||||
window->end();
|
||||
window = new Fl_Double_Window(400,400,"Options");
|
||||
|
||||
window->set_non_modal();
|
||||
|
||||
tabs = new Fl_Tabs(0, 0, 400, 400);
|
||||
|
||||
window->resizable( tabs );
|
||||
|
||||
int x, y, w, h;
|
||||
tabs->client_area( x, y, w, h, 25 );
|
||||
|
||||
addGroup = new Fl_Group(x,y,w,h,"Add");
|
||||
{
|
||||
newButton = new Avtk::Button( x+2, y+2, w-4, 30, "New Generic MIDI");
|
||||
loadButton = new Avtk::Button( x+2, y+2+32, w-4, 30, "Load Generic MIDI");
|
||||
}
|
||||
addGroup->end();
|
||||
tabs->end();
|
||||
|
||||
newButton ->callback( addNewController, this );
|
||||
loadButton->callback( selectLoadController, this );
|
||||
|
||||
window->end();
|
||||
}
|
||||
|
||||
OptionsWindow::~OptionsWindow()
|
||||
{
|
||||
delete newButton;
|
||||
delete loadButton;
|
||||
delete addGroup;
|
||||
delete tabs;
|
||||
delete window;
|
||||
delete newButton;
|
||||
delete loadButton;
|
||||
delete addGroup;
|
||||
delete tabs;
|
||||
delete window;
|
||||
}
|
||||
|
||||
void OptionsWindow::show()
|
||||
{
|
||||
window->show();
|
||||
window->show();
|
||||
}
|
||||
|
||||
void OptionsWindow::hide()
|
||||
{
|
||||
window->hide();
|
||||
window->hide();
|
||||
}
|
||||
|
||||
ControllerUI* OptionsWindow::getControllerUI(int id)
|
||||
{
|
||||
for(unsigned int i = 0; i < controllers.size(); i++ )
|
||||
{
|
||||
if ( controllers.at(i)->controllerID == id )
|
||||
{
|
||||
return controllers.at(i);
|
||||
}
|
||||
}
|
||||
|
||||
// error: controller not found!
|
||||
return 0;
|
||||
for(unsigned int i = 0; i < controllers.size(); i++ ) {
|
||||
if ( controllers.at(i)->controllerID == id ) {
|
||||
return controllers.at(i);
|
||||
}
|
||||
}
|
||||
|
||||
// error: controller not found!
|
||||
return 0;
|
||||
}
|
||||
|
|
144
src/goptions.hxx
144
src/goptions.hxx
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -43,78 +43,84 @@ class OptionsWindow;
|
|||
/// contains UI elements to represent one controller
|
||||
class ControllerUI
|
||||
{
|
||||
public:
|
||||
ControllerUI( int x, int y, int w, int h, std::string name,int id);
|
||||
~ControllerUI();
|
||||
|
||||
void setAuthor(std::string author);
|
||||
void setLink (std::string link );
|
||||
std::string getAuthor(){return author;}
|
||||
std::string getLink(){return link;}
|
||||
|
||||
void setTarget(const char* n);
|
||||
void setBindEnable( bool b );
|
||||
|
||||
void addBinding( Binding* b );
|
||||
void addBindings( GenericMIDI* c );
|
||||
|
||||
// the ControllerID this UI class represents
|
||||
int controllerID;
|
||||
|
||||
// for adding to GOptions tabs
|
||||
Fl_Group* widget;
|
||||
|
||||
std::string name;
|
||||
|
||||
OptionsWindow* optionsWindow;
|
||||
|
||||
// public to redraw when removing from static
|
||||
Fl_Scroll* scroll;
|
||||
Fl_Pack* bindingsPack;
|
||||
|
||||
private:
|
||||
// bindings
|
||||
std::string target;
|
||||
std::string author;
|
||||
std::string link;
|
||||
|
||||
Avtk::Button* authorLabel;
|
||||
Avtk::Button* linkLabel;
|
||||
|
||||
std::vector<int> bindingID;
|
||||
|
||||
Fl_Box* targetLabel;
|
||||
Fl_Box* targetLabelStat;
|
||||
//Avtk::Bindings* bindings;
|
||||
Avtk::LightButton* bindEnable;
|
||||
Avtk::Button* removeController;
|
||||
Avtk::Button* writeControllerBtn;
|
||||
public:
|
||||
ControllerUI( int x, int y, int w, int h, std::string name,int id);
|
||||
~ControllerUI();
|
||||
|
||||
void setAuthor(std::string author);
|
||||
void setLink (std::string link );
|
||||
std::string getAuthor()
|
||||
{
|
||||
return author;
|
||||
}
|
||||
std::string getLink()
|
||||
{
|
||||
return link;
|
||||
}
|
||||
|
||||
void setTarget(const char* n);
|
||||
void setBindEnable( bool b );
|
||||
|
||||
void addBinding( Binding* b );
|
||||
void addBindings( GenericMIDI* c );
|
||||
|
||||
// the ControllerID this UI class represents
|
||||
int controllerID;
|
||||
|
||||
// for adding to GOptions tabs
|
||||
Fl_Group* widget;
|
||||
|
||||
std::string name;
|
||||
|
||||
OptionsWindow* optionsWindow;
|
||||
|
||||
// public to redraw when removing from static
|
||||
Fl_Scroll* scroll;
|
||||
Fl_Pack* bindingsPack;
|
||||
|
||||
private:
|
||||
// bindings
|
||||
std::string target;
|
||||
std::string author;
|
||||
std::string link;
|
||||
|
||||
Avtk::Button* authorLabel;
|
||||
Avtk::Button* linkLabel;
|
||||
|
||||
std::vector<int> bindingID;
|
||||
|
||||
Fl_Box* targetLabel;
|
||||
Fl_Box* targetLabelStat;
|
||||
//Avtk::Bindings* bindings;
|
||||
Avtk::LightButton* bindEnable;
|
||||
Avtk::Button* removeController;
|
||||
Avtk::Button* writeControllerBtn;
|
||||
};
|
||||
|
||||
class OptionsWindow
|
||||
{
|
||||
public:
|
||||
OptionsWindow();
|
||||
~OptionsWindow();
|
||||
|
||||
void show();
|
||||
void hide();
|
||||
|
||||
void setTarget(const char* n);
|
||||
ControllerUI* getControllerUI(int id);
|
||||
|
||||
// public for static methods only
|
||||
Fl_Tabs* tabs;
|
||||
std::vector<ControllerUI*> controllers;
|
||||
Fl_Group* addGroup;
|
||||
public:
|
||||
OptionsWindow();
|
||||
~OptionsWindow();
|
||||
|
||||
void show();
|
||||
void hide();
|
||||
|
||||
void setTarget(const char* n);
|
||||
ControllerUI* getControllerUI(int id);
|
||||
|
||||
// public for static methods only
|
||||
Fl_Tabs* tabs;
|
||||
std::vector<ControllerUI*> controllers;
|
||||
Fl_Group* addGroup;
|
||||
#ifdef BUILD_TESTS
|
||||
int runTests();
|
||||
int runTests();
|
||||
#endif
|
||||
|
||||
private:
|
||||
Fl_Double_Window* window;
|
||||
Avtk::Button* newButton;
|
||||
Avtk::Button* loadButton;
|
||||
|
||||
private:
|
||||
Fl_Double_Window* window;
|
||||
Avtk::Button* newButton;
|
||||
Avtk::Button* loadButton;
|
||||
};
|
||||
|
||||
#endif // LUPPP_OPTIONS_H
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -26,269 +26,245 @@
|
|||
extern Jack* jack;
|
||||
|
||||
const char* GridLogic::StateString[8] = {
|
||||
"Empty",
|
||||
"Playing",
|
||||
"Play queued",
|
||||
"Stopped",
|
||||
"Stop queued",
|
||||
"Recording",
|
||||
"Record queued"
|
||||
"Empty",
|
||||
"Playing",
|
||||
"Play queued",
|
||||
"Stopped",
|
||||
"Stop queued",
|
||||
"Recording",
|
||||
"Record queued"
|
||||
};
|
||||
|
||||
GridLogic::GridLogic()
|
||||
{
|
||||
sceneLaunch = 0;
|
||||
|
||||
sampleTrackScene = false;
|
||||
selectedTrack = 0;
|
||||
selectedScene = 0;
|
||||
sceneLaunch = 0;
|
||||
|
||||
sampleTrackScene = false;
|
||||
selectedTrack = 0;
|
||||
selectedScene = 0;
|
||||
}
|
||||
|
||||
void GridLogic::selectedTrackSceneEvent(bool p)
|
||||
{
|
||||
if ( p )
|
||||
{
|
||||
pressed( selectedTrack, selectedScene );
|
||||
}
|
||||
else
|
||||
{
|
||||
released( selectedTrack, selectedScene );
|
||||
}
|
||||
if ( p ) {
|
||||
pressed( selectedTrack, selectedScene );
|
||||
} else {
|
||||
released( selectedTrack, selectedScene );
|
||||
}
|
||||
}
|
||||
|
||||
void GridLogic::setSelectTrackScene(bool b)
|
||||
{
|
||||
char tmp[40];
|
||||
sprintf( tmp, "Select track enable %i", int(b) );
|
||||
EventGuiPrint e( tmp );
|
||||
writeToGuiRingbuffer( &e );
|
||||
sampleTrackScene = b;
|
||||
char tmp[40];
|
||||
sprintf( tmp, "Select track enable %i", int(b) );
|
||||
EventGuiPrint e( tmp );
|
||||
writeToGuiRingbuffer( &e );
|
||||
sampleTrackScene = b;
|
||||
}
|
||||
|
||||
int GridLogic::getLaunchedScene()
|
||||
{
|
||||
return sceneLaunch;
|
||||
return sceneLaunch;
|
||||
}
|
||||
|
||||
int GridLogic::getSelectedTrack()
|
||||
{
|
||||
return selectedTrack;
|
||||
return selectedTrack;
|
||||
}
|
||||
|
||||
int GridLogic::getSelectedScene()
|
||||
{
|
||||
return selectedScene;
|
||||
return selectedScene;
|
||||
}
|
||||
|
||||
void GridLogic::setSelectedTrack(int t)
|
||||
{
|
||||
selectedTrack = t;
|
||||
selectedTrack = t;
|
||||
}
|
||||
|
||||
void GridLogic::setSelectedScene(int s)
|
||||
{
|
||||
selectedScene = s;
|
||||
selectedScene = s;
|
||||
}
|
||||
|
||||
|
||||
void GridLogic::launchScene( int scene )
|
||||
{
|
||||
for(unsigned int t = 0; t < NTRACKS; t++ )
|
||||
{
|
||||
for(int s = 0; s < NSCENES; s++ )
|
||||
{
|
||||
LooperClip* lc = jack->getLooper( t )->getClip( s );
|
||||
if ( s == scene )
|
||||
{
|
||||
lc->queuePlay();
|
||||
jack->getControllerUpdater()->setSceneState( t, s, lc->getState() );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( lc->playing() )
|
||||
{
|
||||
lc->queueStop();
|
||||
jack->getControllerUpdater()->setSceneState( t, s, lc->getState() );
|
||||
}
|
||||
else if ( lc->somethingQueued() )
|
||||
{
|
||||
lc->neutralize();
|
||||
jack->getControllerUpdater()->setSceneState( t, s, lc->getState() );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sceneLaunch = scene;
|
||||
|
||||
jack->getControllerUpdater()->launchScene( scene );
|
||||
for(unsigned int t = 0; t < NTRACKS; t++ ) {
|
||||
for(int s = 0; s < NSCENES; s++ ) {
|
||||
LooperClip* lc = jack->getLooper( t )->getClip( s );
|
||||
if ( s == scene ) {
|
||||
lc->queuePlay();
|
||||
jack->getControllerUpdater()->setSceneState( t, s, lc->getState() );
|
||||
} else {
|
||||
if ( lc->playing() ) {
|
||||
lc->queueStop();
|
||||
jack->getControllerUpdater()->setSceneState( t, s, lc->getState() );
|
||||
} else if ( lc->somethingQueued() ) {
|
||||
lc->neutralize();
|
||||
jack->getControllerUpdater()->setSceneState( t, s, lc->getState() );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sceneLaunch = scene;
|
||||
|
||||
jack->getControllerUpdater()->launchScene( scene );
|
||||
}
|
||||
|
||||
void GridLogic::specialScene(int t, int s)
|
||||
{
|
||||
if ( t < 0 ) t = 0;
|
||||
if ( t >= NTRACKS ) t = NTRACKS-1;
|
||||
|
||||
if ( s < 0 ) s = 0;
|
||||
if ( s >= NSCENES ) s = NSCENES-1;
|
||||
|
||||
selectedTrack = t;
|
||||
selectedScene = s;
|
||||
|
||||
// update UI's
|
||||
jack->getControllerUpdater()->specialScene( t, s );
|
||||
if ( t < 0 ) t = 0;
|
||||
if ( t >= NTRACKS ) t = NTRACKS-1;
|
||||
|
||||
if ( s < 0 ) s = 0;
|
||||
if ( s >= NSCENES ) s = NSCENES-1;
|
||||
|
||||
selectedTrack = t;
|
||||
selectedScene = s;
|
||||
|
||||
// update UI's
|
||||
jack->getControllerUpdater()->specialScene( t, s );
|
||||
}
|
||||
|
||||
void GridLogic::pressed( int track, int scene )
|
||||
{
|
||||
if ( sampleTrackScene )
|
||||
{
|
||||
specialScene( track, scene );
|
||||
|
||||
// don't act on grid press!
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// get the clip, do the "press" action based on current state.
|
||||
LooperClip* lc = jack->getLooper( track )->getClip( scene );
|
||||
TrackOutput* to = jack->getTrackOutput( track );
|
||||
GridLogic::State s = lc->getState();
|
||||
if ( sampleTrackScene ) {
|
||||
specialScene( track, scene );
|
||||
|
||||
// don't act on grid press!
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// get the clip, do the "press" action based on current state.
|
||||
LooperClip* lc = jack->getLooper( track )->getClip( scene );
|
||||
TrackOutput* to = jack->getTrackOutput( track );
|
||||
GridLogic::State s = lc->getState();
|
||||
|
||||
#ifdef DEBUG_CLIP
|
||||
printf("GridLogic::pressed() before press state = %s\n", StateString[ int(scene) ] );
|
||||
#endif
|
||||
|
||||
if ( to->recordArm() && !lc->recording() )
|
||||
{
|
||||
lc->queueRecord();
|
||||
to->recordArm(false);
|
||||
jack->getControllerUpdater()->recordArm( track, false );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( s == STATE_EMPTY )
|
||||
lc->queueRecord();
|
||||
|
||||
if ( s == STATE_STOPPED )
|
||||
{
|
||||
// hack, stop all scenes, then launch proper one
|
||||
for( int i = 0; i < NTRACKS; i++ )
|
||||
{
|
||||
LooperClip* ilc = jack->getLooper( track )->getClip( i );
|
||||
if ( ilc->playing() )
|
||||
{
|
||||
ilc->queueStop();
|
||||
}
|
||||
}
|
||||
|
||||
lc->queuePlay();
|
||||
}
|
||||
|
||||
if ( s == STATE_PLAYING )
|
||||
lc->queueStop();
|
||||
|
||||
if ( s == STATE_RECORDING )
|
||||
lc->queuePlay();
|
||||
|
||||
if ( s == STATE_PLAY_QUEUED )
|
||||
lc->queueStop();
|
||||
|
||||
if ( s == STATE_STOP_QUEUED )
|
||||
lc->queuePlay();
|
||||
|
||||
// don't re-trigger if already playing!
|
||||
if ( s == STATE_STOP_QUEUED && lc->playing() )
|
||||
lc->neutralize();
|
||||
|
||||
if ( s == STATE_RECORD_QUEUED )
|
||||
lc->neutralize();
|
||||
}
|
||||
|
||||
// check state of new clip, if getQueuePlay() == true, queueStop() all other scenes
|
||||
//if ( lc->getQueuePlay() )
|
||||
{
|
||||
for(int i = 0; i < NSCENES; i++)
|
||||
{
|
||||
// exclude current scene
|
||||
if ( i != scene )
|
||||
{
|
||||
//LUPPP_NOTE("netralizing & qStop on scene %i due to press on %i", i, scene );
|
||||
LooperClip* ilc = jack->getLooper( track )->getClip( i );
|
||||
|
||||
ilc->neutralize();
|
||||
ilc->queueStop();
|
||||
jack->getControllerUpdater()->setSceneState(track, i, ilc->getState() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
s = lc->getState();
|
||||
#ifdef DEBUG_CLIP
|
||||
printf("GridLogic::pressed() after press state = %s\n", StateString[ int(s) ] );
|
||||
printf("GridLogic::pressed() before press state = %s\n", StateString[ int(scene) ] );
|
||||
#endif
|
||||
jack->getControllerUpdater()->setSceneState(track, scene, s );
|
||||
|
||||
if ( to->recordArm() && !lc->recording() ) {
|
||||
lc->queueRecord();
|
||||
to->recordArm(false);
|
||||
jack->getControllerUpdater()->recordArm( track, false );
|
||||
} else {
|
||||
if ( s == STATE_EMPTY )
|
||||
lc->queueRecord();
|
||||
|
||||
if ( s == STATE_STOPPED ) {
|
||||
// hack, stop all scenes, then launch proper one
|
||||
for( int i = 0; i < NTRACKS; i++ ) {
|
||||
LooperClip* ilc = jack->getLooper( track )->getClip( i );
|
||||
if ( ilc->playing() ) {
|
||||
ilc->queueStop();
|
||||
}
|
||||
}
|
||||
|
||||
lc->queuePlay();
|
||||
}
|
||||
|
||||
if ( s == STATE_PLAYING )
|
||||
lc->queueStop();
|
||||
|
||||
if ( s == STATE_RECORDING )
|
||||
lc->queuePlay();
|
||||
|
||||
if ( s == STATE_PLAY_QUEUED )
|
||||
lc->queueStop();
|
||||
|
||||
if ( s == STATE_STOP_QUEUED )
|
||||
lc->queuePlay();
|
||||
|
||||
// don't re-trigger if already playing!
|
||||
if ( s == STATE_STOP_QUEUED && lc->playing() )
|
||||
lc->neutralize();
|
||||
|
||||
if ( s == STATE_RECORD_QUEUED )
|
||||
lc->neutralize();
|
||||
}
|
||||
|
||||
// check state of new clip, if getQueuePlay() == true, queueStop() all other scenes
|
||||
//if ( lc->getQueuePlay() )
|
||||
{
|
||||
for(int i = 0; i < NSCENES; i++) {
|
||||
// exclude current scene
|
||||
if ( i != scene ) {
|
||||
//LUPPP_NOTE("netralizing & qStop on scene %i due to press on %i", i, scene );
|
||||
LooperClip* ilc = jack->getLooper( track )->getClip( i );
|
||||
|
||||
ilc->neutralize();
|
||||
ilc->queueStop();
|
||||
jack->getControllerUpdater()->setSceneState(track, i, ilc->getState() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
s = lc->getState();
|
||||
#ifdef DEBUG_CLIP
|
||||
printf("GridLogic::pressed() after press state = %s\n", StateString[ int(s) ] );
|
||||
#endif
|
||||
jack->getControllerUpdater()->setSceneState(track, scene, s );
|
||||
}
|
||||
|
||||
|
||||
void GridLogic::released( int track, int scene )
|
||||
{
|
||||
GridLogic::State s = jack->getLooper( track )->getClip( scene )->getState();
|
||||
jack->getControllerUpdater()->setSceneState(track, scene, s );
|
||||
GridLogic::State s = jack->getLooper( track )->getClip( scene )->getState();
|
||||
jack->getControllerUpdater()->setSceneState(track, scene, s );
|
||||
}
|
||||
|
||||
void GridLogic::load(int track, int scene, AudioBuffer* ab)
|
||||
{
|
||||
jack->getLooper( track )->getClip( scene )->load( ab );
|
||||
GridLogic::State s = jack->getLooper( track )->getClip( scene )->getState();
|
||||
jack->getControllerUpdater()->setSceneState(track, scene, s );
|
||||
jack->getLooper( track )->getClip( scene )->load( ab );
|
||||
GridLogic::State s = jack->getLooper( track )->getClip( scene )->getState();
|
||||
jack->getControllerUpdater()->setSceneState(track, scene, s );
|
||||
}
|
||||
|
||||
|
||||
void GridLogic::updateState()
|
||||
{
|
||||
//printf("GridLogic::updateState() stub" );
|
||||
for(int t = 0; t < NTRACKS; t++)
|
||||
{
|
||||
for(int s = 0; s < NSCENES; s++)
|
||||
{
|
||||
GridLogic::State st = jack->getLooper( t )->getClip( s )->getState();
|
||||
EventGuiPrint e( GridLogic::StateString[st] );
|
||||
writeToGuiRingbuffer( &e );
|
||||
jack->getControllerUpdater()->setSceneState(t, s, st );
|
||||
}
|
||||
}
|
||||
//printf("GridLogic::updateState() stub" );
|
||||
for(int t = 0; t < NTRACKS; t++) {
|
||||
for(int s = 0; s < NSCENES; s++) {
|
||||
GridLogic::State st = jack->getLooper( t )->getClip( s )->getState();
|
||||
EventGuiPrint e( GridLogic::StateString[st] );
|
||||
writeToGuiRingbuffer( &e );
|
||||
jack->getControllerUpdater()->setSceneState(t, s, st );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GridLogic::bar()
|
||||
{
|
||||
#ifdef DEBUG_CLIP
|
||||
EventGuiPrint e( "GridLogic::bar()" );
|
||||
//writeToGuiRingbuffer( &e );
|
||||
EventGuiPrint e( "GridLogic::bar()" );
|
||||
//writeToGuiRingbuffer( &e );
|
||||
#endif
|
||||
|
||||
/// iterate over all clips, if they're set to QUEUED, set to the next state
|
||||
for( int i = 0; i < NTRACKS*NSCENES; i++ )
|
||||
{
|
||||
int track = i / NSCENES;
|
||||
int scene = i - track * NSCENES;
|
||||
jack->getLooper( track )->getClip(scene)->bar();
|
||||
|
||||
/// iterate over all clips, if they're set to QUEUED, set to the next state
|
||||
for( int i = 0; i < NTRACKS*NSCENES; i++ ) {
|
||||
int track = i / NSCENES;
|
||||
int scene = i - track * NSCENES;
|
||||
jack->getLooper( track )->getClip(scene)->bar();
|
||||
|
||||
#ifdef DEBUG_CLIP
|
||||
GridLogic::State s = jack->getLooper( track )->getClip( scene )->getState();
|
||||
if ( s != STATE_EMPTY )
|
||||
{
|
||||
//printf("%i, %i:after bar() state = %s\n", track, scene, StateString[ int(s) ] );
|
||||
}
|
||||
GridLogic::State s = jack->getLooper( track )->getClip( scene )->getState();
|
||||
if ( s != STATE_EMPTY ) {
|
||||
//printf("%i, %i:after bar() state = %s\n", track, scene, StateString[ int(s) ] );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GridLogic::beat()
|
||||
{
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -29,82 +29,85 @@ class AudioBuffer;
|
|||
* separtated from the Looper class so it can be repurposed by different
|
||||
* controllers and input devices. The UI and eg. APC / Launchpad all have a
|
||||
* similar grid style interface: the logic is implemented here once.
|
||||
*
|
||||
*
|
||||
* The class sends Looper messages to change its state, thus abstracting away
|
||||
* the details of the Looper control, and exposing its functionality using a
|
||||
* convinient API.
|
||||
*
|
||||
*
|
||||
* When the state of a block changes, it will update the state of the grid on
|
||||
* the controller.
|
||||
*
|
||||
*
|
||||
* It inherits from TimeObserver so it can change the state of the clip on the
|
||||
* bar / beat.
|
||||
**/
|
||||
class GridLogic : public TimeObserver
|
||||
{
|
||||
public:
|
||||
/// possible states of each square. Public so Controller subclasses can
|
||||
/// determine the state of the square
|
||||
enum State {
|
||||
STATE_EMPTY = 0,
|
||||
STATE_PLAYING,
|
||||
STATE_PLAY_QUEUED,
|
||||
STATE_STOPPED,
|
||||
STATE_STOP_QUEUED,
|
||||
STATE_RECORDING,
|
||||
STATE_RECORD_QUEUED,
|
||||
};
|
||||
|
||||
GridLogic();
|
||||
~GridLogic(){};
|
||||
|
||||
/// button press / click event
|
||||
void pressed( int track, int scene );
|
||||
|
||||
/// button release / click-release event
|
||||
void released( int track, int scene );
|
||||
|
||||
/// master controls, launches a horizontal scene with one event
|
||||
void launchScene( int scene );
|
||||
int getCurrentScene(){return sceneLaunch;}
|
||||
int getLaunchedScene();
|
||||
|
||||
/// selected track functions
|
||||
void setSelectTrackScene(bool b);
|
||||
void setSelectedTrack(int t);
|
||||
void setSelectedScene(int s);
|
||||
int getSelectedTrack();
|
||||
int getSelectedScene();
|
||||
|
||||
void selectedTrackSceneEvent(bool pressed);
|
||||
|
||||
void specialScene(int t, int s);
|
||||
|
||||
/// GUI load event
|
||||
void load(int track, int scene, AudioBuffer* ab);
|
||||
|
||||
/// resend entire grid state to controllers
|
||||
void updateState();
|
||||
|
||||
/// time functions, not for use by Controller subclasses
|
||||
void bar();
|
||||
void beat();
|
||||
|
||||
/// for debug purposes: use static_cast<int>(GridLogic::State) to access
|
||||
static const char* StateString[8];
|
||||
|
||||
public:
|
||||
/// possible states of each square. Public so Controller subclasses can
|
||||
/// determine the state of the square
|
||||
enum State {
|
||||
STATE_EMPTY = 0,
|
||||
STATE_PLAYING,
|
||||
STATE_PLAY_QUEUED,
|
||||
STATE_STOPPED,
|
||||
STATE_STOP_QUEUED,
|
||||
STATE_RECORDING,
|
||||
STATE_RECORD_QUEUED,
|
||||
};
|
||||
|
||||
GridLogic();
|
||||
~GridLogic() {};
|
||||
|
||||
/// button press / click event
|
||||
void pressed( int track, int scene );
|
||||
|
||||
/// button release / click-release event
|
||||
void released( int track, int scene );
|
||||
|
||||
/// master controls, launches a horizontal scene with one event
|
||||
void launchScene( int scene );
|
||||
int getCurrentScene()
|
||||
{
|
||||
return sceneLaunch;
|
||||
}
|
||||
int getLaunchedScene();
|
||||
|
||||
/// selected track functions
|
||||
void setSelectTrackScene(bool b);
|
||||
void setSelectedTrack(int t);
|
||||
void setSelectedScene(int s);
|
||||
int getSelectedTrack();
|
||||
int getSelectedScene();
|
||||
|
||||
void selectedTrackSceneEvent(bool pressed);
|
||||
|
||||
void specialScene(int t, int s);
|
||||
|
||||
/// GUI load event
|
||||
void load(int track, int scene, AudioBuffer* ab);
|
||||
|
||||
/// resend entire grid state to controllers
|
||||
void updateState();
|
||||
|
||||
/// time functions, not for use by Controller subclasses
|
||||
void bar();
|
||||
void beat();
|
||||
|
||||
/// for debug purposes: use static_cast<int>(GridLogic::State) to access
|
||||
static const char* StateString[8];
|
||||
|
||||
#ifdef BUILD_TESTS
|
||||
int runTests();
|
||||
int runTests();
|
||||
#endif
|
||||
|
||||
private:
|
||||
/// holds last scene launch
|
||||
int sceneLaunch;
|
||||
|
||||
/// holds selected track / scene for special clip
|
||||
bool sampleTrackScene; // turn on to have selected clip, press event acted on
|
||||
int selectedTrack;
|
||||
int selectedScene;
|
||||
private:
|
||||
/// holds last scene launch
|
||||
int sceneLaunch;
|
||||
|
||||
/// holds selected track / scene for special clip
|
||||
bool sampleTrackScene; // turn on to have selected clip, press event acted on
|
||||
int selectedTrack;
|
||||
int selectedScene;
|
||||
};
|
||||
|
||||
|
||||
|
|
294
src/gtrack.cxx
294
src/gtrack.cxx
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -33,199 +33,217 @@ static void gtrack_jacksendactivate_cb(Fl_Widget* w,void *data);
|
|||
|
||||
|
||||
GTrack::GTrack(int x, int y, int w, int h, const char* l ) :
|
||||
Fl_Group(x, y, w, h),
|
||||
bg( x, y , w, h, l ),
|
||||
|
||||
radial( x+5, y+ 26, 100, 100, ""),
|
||||
|
||||
clipSel(x + 5, y + 26 + 102, 100, 294,""),
|
||||
jackSendBox(x+5, y+422, 100, 45, ""),
|
||||
jackSendDial(x+21, y+422+8, 30,30, ""),
|
||||
jackSendActivate(x+66, y+422+11, 36,25, "FX"),
|
||||
volBox(x+5, y+422+50, 100, 172, ""),
|
||||
volume(x+66, y +425+50, 36, 166, ""),
|
||||
Fl_Group(x, y, w, h),
|
||||
bg( x, y , w, h, l ),
|
||||
|
||||
radial( x+5, y+ 26, 100, 100, ""),
|
||||
|
||||
clipSel(x + 5, y + 26 + 102, 100, 294,""),
|
||||
jackSendBox(x+5, y+422, 100, 45, ""),
|
||||
jackSendDial(x+21, y+422+8, 30,30, ""),
|
||||
jackSendActivate(x+66, y+422+11, 36,25, "FX"),
|
||||
volBox(x+5, y+422+50, 100, 172, ""),
|
||||
volume(x+66, y +425+50, 36, 166, ""),
|
||||
|
||||
|
||||
|
||||
|
||||
sendDial (x+21, y +430 + 50, 30, 30, ""),
|
||||
sendActive (x+11, y +430 + 82, 50, 25, "Snd"),
|
||||
|
||||
xsideDial (x+21, y +430 + 69+50, 30, 30, ""),
|
||||
keyActive (x+11, y +430 + 151, 50, 25, "Key"),
|
||||
|
||||
recordActive (x+11, y +430 + 182, 50, 25, "XRec")
|
||||
|
||||
|
||||
sendDial (x+21, y +430 + 50, 30, 30, ""),
|
||||
sendActive (x+11, y +430 + 82, 50, 25, "Snd"),
|
||||
|
||||
xsideDial (x+21, y +430 + 69+50, 30, 30, ""),
|
||||
keyActive (x+11, y +430 + 151, 50, 25, "Key"),
|
||||
|
||||
recordActive (x+11, y +430 + 182, 50, 25, "XRec")
|
||||
{
|
||||
ID = privateID++;
|
||||
|
||||
clipSel.setID( ID );
|
||||
|
||||
sendDial.callback( gtrack_sendDial_cb, this );
|
||||
sendActive.setColor( 0, 1.0, 0.0 );
|
||||
sendActive.callback( gtrack_send_cb, this );
|
||||
|
||||
xsideDial.callback( gtrack_xsideDial_cb, this );
|
||||
xsideDial.align( FL_ALIGN_BOTTOM );
|
||||
keyActive.callback( gtrack_key_cb, this );
|
||||
keyActive.setColor( 0, 0.6, 1 );
|
||||
|
||||
|
||||
recordActive.setColor( 1, 0.0, 0.0 );
|
||||
recordActive.callback( gtrack_record_cb, this );
|
||||
|
||||
volume.callback( gtrack_vol_cb, this );
|
||||
ID = privateID++;
|
||||
|
||||
jackSendActivate.setColor( 1, 1, 0 );
|
||||
jackSendActivate.callback(gtrack_jacksendactivate_cb,this);
|
||||
jackSendDial.align(FL_ALIGN_INSIDE);
|
||||
jackSendDial.callback(gtrack_jacksend_cb,this);
|
||||
jackSendDial.value(1.0);
|
||||
//volBox.color( fl_rgb_color( 0,0,0 ) );
|
||||
|
||||
end(); // close the group
|
||||
clipSel.setID( ID );
|
||||
|
||||
sendDial.callback( gtrack_sendDial_cb, this );
|
||||
sendActive.setColor( 0, 1.0, 0.0 );
|
||||
sendActive.callback( gtrack_send_cb, this );
|
||||
|
||||
xsideDial.callback( gtrack_xsideDial_cb, this );
|
||||
xsideDial.align( FL_ALIGN_BOTTOM );
|
||||
keyActive.callback( gtrack_key_cb, this );
|
||||
keyActive.setColor( 0, 0.6, 1 );
|
||||
|
||||
|
||||
recordActive.setColor( 1, 0.0, 0.0 );
|
||||
recordActive.callback( gtrack_record_cb, this );
|
||||
|
||||
volume.callback( gtrack_vol_cb, this );
|
||||
|
||||
jackSendActivate.setColor( 1, 1, 0 );
|
||||
jackSendActivate.callback(gtrack_jacksendactivate_cb,this);
|
||||
jackSendDial.align(FL_ALIGN_INSIDE);
|
||||
jackSendDial.callback(gtrack_jacksend_cb,this);
|
||||
jackSendDial.value(1.0);
|
||||
//volBox.color( fl_rgb_color( 0,0,0 ) );
|
||||
|
||||
end(); // close the group
|
||||
}
|
||||
|
||||
float GTrack::getSend(){return sendDial.value(); }
|
||||
float GTrack::getXSide(){return xsideDial.value(); }
|
||||
float GTrack::getSend()
|
||||
{
|
||||
return sendDial.value();
|
||||
}
|
||||
float GTrack::getXSide()
|
||||
{
|
||||
return xsideDial.value();
|
||||
}
|
||||
|
||||
bool GTrack::getSendActive (){return sendActive.value(); }
|
||||
bool GTrack::getKeyActive (){return keyActive.value(); }
|
||||
bool GTrack::getRecordActive(){return recordActive.value(); }
|
||||
bool GTrack::getSendActive ()
|
||||
{
|
||||
return sendActive.value();
|
||||
}
|
||||
bool GTrack::getKeyActive ()
|
||||
{
|
||||
return keyActive.value();
|
||||
}
|
||||
bool GTrack::getRecordActive()
|
||||
{
|
||||
return recordActive.value();
|
||||
}
|
||||
|
||||
|
||||
void GTrack::setSend(float s){ sendDial.value( s ); }
|
||||
void GTrack::setXSide(float s){ xsideDial.value( s ); }
|
||||
void GTrack::setSend(float s)
|
||||
{
|
||||
sendDial.value( s );
|
||||
}
|
||||
void GTrack::setXSide(float s)
|
||||
{
|
||||
xsideDial.value( s );
|
||||
}
|
||||
|
||||
void GTrack::setSendActive(bool a){ sendActive.value( a ); }
|
||||
void GTrack::setKeyActive(bool a){ keyActive.value( a ); }
|
||||
void GTrack::setRecordActive(bool a){ recordActive.value( a ); }
|
||||
void GTrack::setSendActive(bool a)
|
||||
{
|
||||
sendActive.value( a );
|
||||
}
|
||||
void GTrack::setKeyActive(bool a)
|
||||
{
|
||||
keyActive.value( a );
|
||||
}
|
||||
void GTrack::setRecordActive(bool a)
|
||||
{
|
||||
recordActive.value( a );
|
||||
}
|
||||
|
||||
void GTrack::setJackSend(float s)
|
||||
{
|
||||
jackSendDial.value(s);
|
||||
jackSendDial.value(s);
|
||||
}
|
||||
|
||||
void GTrack::setJackSendActivate(bool a)
|
||||
{
|
||||
jackSendActivate.value(a);
|
||||
jackSendActivate.value(a);
|
||||
}
|
||||
|
||||
float GTrack::getJackSend()
|
||||
{
|
||||
return jackSendDial.value();
|
||||
return jackSendDial.value();
|
||||
}
|
||||
|
||||
bool GTrack::getJackSendActivate()
|
||||
{
|
||||
return jackSendActivate.value();
|
||||
return jackSendActivate.value();
|
||||
}
|
||||
|
||||
void gtrack_sendDial_cb(Fl_Widget *w, void *data)
|
||||
{
|
||||
GTrack* track = (GTrack*) data;
|
||||
EventTrackSend e( track->ID, SEND_POSTFADER, ((Avtk::Dial*)w)->value() );
|
||||
writeToDspRingbuffer( &e );
|
||||
//printf("track %i reverb send %f\n", track->ID, ((Avtk::Dial*)w)->value() );
|
||||
GTrack* track = (GTrack*) data;
|
||||
EventTrackSend e( track->ID, SEND_POSTFADER, ((Avtk::Dial*)w)->value() );
|
||||
writeToDspRingbuffer( &e );
|
||||
//printf("track %i reverb send %f\n", track->ID, ((Avtk::Dial*)w)->value() );
|
||||
}
|
||||
|
||||
|
||||
void gtrack_key_cb(Fl_Widget *w, void *data)
|
||||
{
|
||||
GTrack* track = (GTrack*) data;
|
||||
Avtk::LightButton* d = (Avtk::LightButton*)w;
|
||||
bool b = d->value();
|
||||
if ( b < 0.5 )
|
||||
{
|
||||
EventTrackSendActive e( track->ID, SEND_KEY, true );
|
||||
writeToDspRingbuffer( &e );
|
||||
}
|
||||
else
|
||||
{
|
||||
EventTrackSendActive e( track->ID, SEND_KEY, false );
|
||||
writeToDspRingbuffer( &e );
|
||||
}
|
||||
//printf("track %i post send %s\n", track->ID, b ? "off" : "on" );
|
||||
GTrack* track = (GTrack*) data;
|
||||
Avtk::LightButton* d = (Avtk::LightButton*)w;
|
||||
bool b = d->value();
|
||||
if ( b < 0.5 ) {
|
||||
EventTrackSendActive e( track->ID, SEND_KEY, true );
|
||||
writeToDspRingbuffer( &e );
|
||||
} else {
|
||||
EventTrackSendActive e( track->ID, SEND_KEY, false );
|
||||
writeToDspRingbuffer( &e );
|
||||
}
|
||||
//printf("track %i post send %s\n", track->ID, b ? "off" : "on" );
|
||||
}
|
||||
|
||||
|
||||
void gtrack_xsideDial_cb(Fl_Widget *w, void *data)
|
||||
{
|
||||
GTrack* track = (GTrack*) data;
|
||||
EventTrackSend e( track->ID, SEND_XSIDE, ((Avtk::Dial*)w)->value() );
|
||||
writeToDspRingbuffer( &e );
|
||||
//printf("track %i side send %f\n", track->ID, ((Avtk::Dial*)w)->value() );
|
||||
GTrack* track = (GTrack*) data;
|
||||
EventTrackSend e( track->ID, SEND_XSIDE, ((Avtk::Dial*)w)->value() );
|
||||
writeToDspRingbuffer( &e );
|
||||
//printf("track %i side send %f\n", track->ID, ((Avtk::Dial*)w)->value() );
|
||||
}
|
||||
|
||||
void gtrack_vol_cb(Fl_Widget *w, void *data)
|
||||
{
|
||||
GTrack* track = (GTrack*) data;
|
||||
EventTrackVol e( track->ID, ((Avtk::Volume*)w)->value() );
|
||||
writeToDspRingbuffer( &e );
|
||||
//printf("track %i vol %f\n", track->ID, ((Avtk::Dial*)w)->value() );
|
||||
GTrack* track = (GTrack*) data;
|
||||
EventTrackVol e( track->ID, ((Avtk::Volume*)w)->value() );
|
||||
writeToDspRingbuffer( &e );
|
||||
//printf("track %i vol %f\n", track->ID, ((Avtk::Dial*)w)->value() );
|
||||
}
|
||||
|
||||
|
||||
void gtrack_send_cb(Fl_Widget *w, void *data)
|
||||
{
|
||||
GTrack* track = (GTrack*) data;
|
||||
Avtk::LightButton* d = (Avtk::LightButton*)w;
|
||||
bool b = d->value();
|
||||
d->value( !b );
|
||||
if ( b < 0.5 )
|
||||
{
|
||||
EventTrackSendActive e( track->ID, SEND_POSTFADER, 1.0f );
|
||||
writeToDspRingbuffer( &e );
|
||||
}
|
||||
else
|
||||
{
|
||||
EventTrackSendActive e( track->ID, SEND_POSTFADER, 0.0f );
|
||||
writeToDspRingbuffer( &e );
|
||||
}
|
||||
//printf("track %i reverb send %s\n", track->ID, b ? "true" : "false" );
|
||||
GTrack* track = (GTrack*) data;
|
||||
Avtk::LightButton* d = (Avtk::LightButton*)w;
|
||||
bool b = d->value();
|
||||
d->value( !b );
|
||||
if ( b < 0.5 ) {
|
||||
EventTrackSendActive e( track->ID, SEND_POSTFADER, 1.0f );
|
||||
writeToDspRingbuffer( &e );
|
||||
} else {
|
||||
EventTrackSendActive e( track->ID, SEND_POSTFADER, 0.0f );
|
||||
writeToDspRingbuffer( &e );
|
||||
}
|
||||
//printf("track %i reverb send %s\n", track->ID, b ? "true" : "false" );
|
||||
}
|
||||
void gtrack_jacksend_cb(Fl_Widget *w, void *data)
|
||||
{
|
||||
GTrack* track = (GTrack*) data;
|
||||
Avtk::Dial* d = (Avtk::Dial*)w;
|
||||
float v = d->value();
|
||||
EventTrackJackSend ev(track->ID,v);
|
||||
writeToDspRingbuffer(&ev);
|
||||
GTrack* track = (GTrack*) data;
|
||||
Avtk::Dial* d = (Avtk::Dial*)w;
|
||||
float v = d->value();
|
||||
EventTrackJackSend ev(track->ID,v);
|
||||
writeToDspRingbuffer(&ev);
|
||||
|
||||
//printf("track %i reverb send %s\n", track->ID, b ? "true" : "false" );
|
||||
//printf("track %i reverb send %s\n", track->ID, b ? "true" : "false" );
|
||||
}
|
||||
void gtrack_record_cb(Fl_Widget *w, void *data)
|
||||
{
|
||||
GTrack* track = (GTrack*) data;
|
||||
Avtk::LightButton* d = (Avtk::LightButton*)w;
|
||||
bool b = d->value();
|
||||
if ( b < 0.5 )
|
||||
{
|
||||
EventTrackRecordArm e( track->ID, 1.0f );
|
||||
writeToDspRingbuffer( &e );
|
||||
}
|
||||
else
|
||||
{
|
||||
EventTrackRecordArm e( track->ID, 0.0f );
|
||||
writeToDspRingbuffer( &e );
|
||||
}
|
||||
//printf("track %i record Arm %s\n", track->ID, b ? "off" : "on" );
|
||||
GTrack* track = (GTrack*) data;
|
||||
Avtk::LightButton* d = (Avtk::LightButton*)w;
|
||||
bool b = d->value();
|
||||
if ( b < 0.5 ) {
|
||||
EventTrackRecordArm e( track->ID, 1.0f );
|
||||
writeToDspRingbuffer( &e );
|
||||
} else {
|
||||
EventTrackRecordArm e( track->ID, 0.0f );
|
||||
writeToDspRingbuffer( &e );
|
||||
}
|
||||
//printf("track %i record Arm %s\n", track->ID, b ? "off" : "on" );
|
||||
}
|
||||
|
||||
void gtrack_jacksendactivate_cb(Fl_Widget* w,void *data)
|
||||
{
|
||||
GTrack* track = (GTrack*) data;
|
||||
Avtk::LightButton* d = (Avtk::LightButton*)w;
|
||||
bool b=d->value();
|
||||
// d->value(!b);
|
||||
if ( b < 0.5 )
|
||||
{
|
||||
EventTrackJackSendActivate e( track->ID, 1.0f );
|
||||
writeToDspRingbuffer( &e );
|
||||
}
|
||||
else
|
||||
{
|
||||
EventTrackJackSendActivate e( track->ID, 0.0f );
|
||||
writeToDspRingbuffer( &e );
|
||||
}
|
||||
GTrack* track = (GTrack*) data;
|
||||
Avtk::LightButton* d = (Avtk::LightButton*)w;
|
||||
bool b=d->value();
|
||||
// d->value(!b);
|
||||
if ( b < 0.5 ) {
|
||||
EventTrackJackSendActivate e( track->ID, 1.0f );
|
||||
writeToDspRingbuffer( &e );
|
||||
} else {
|
||||
EventTrackJackSendActivate e( track->ID, 0.0f );
|
||||
writeToDspRingbuffer( &e );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
123
src/gtrack.hxx
123
src/gtrack.hxx
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -45,63 +45,72 @@ using namespace std;
|
|||
|
||||
class GTrack : public Fl_Group
|
||||
{
|
||||
public:
|
||||
|
||||
Avtk::Volume* getVolume(){return &volume;}
|
||||
Avtk::RadialStatus* getRadialStatus(){return &radial;}
|
||||
Avtk::ClipSelector* getClipSelector(){return &clipSel;}
|
||||
|
||||
GTrack(int x, int y, int w, int h, const char* l = 0 );
|
||||
|
||||
|
||||
// getters
|
||||
float getSend();
|
||||
float getXSide();
|
||||
|
||||
bool getSendActive();
|
||||
bool getKeyActive();
|
||||
bool getRecordActive();
|
||||
|
||||
// setters
|
||||
void setSend(float s);
|
||||
void setXSide(float s);
|
||||
|
||||
void setSendActive(bool a);
|
||||
void setKeyActive(bool a);
|
||||
void setRecordActive(bool a);
|
||||
|
||||
void setJackSend(float s);
|
||||
void setJackSendActivate(bool a);
|
||||
|
||||
int ID;
|
||||
|
||||
Avtk::Background bg;
|
||||
|
||||
Avtk::RadialStatus radial;
|
||||
|
||||
Avtk::ClipSelector clipSel;
|
||||
public:
|
||||
|
||||
Avtk::Box volBox;
|
||||
|
||||
Avtk::Volume volume;
|
||||
|
||||
float getJackSend();
|
||||
bool getJackSendActivate();
|
||||
Avtk::Volume* getVolume()
|
||||
{
|
||||
return &volume;
|
||||
}
|
||||
Avtk::RadialStatus* getRadialStatus()
|
||||
{
|
||||
return &radial;
|
||||
}
|
||||
Avtk::ClipSelector* getClipSelector()
|
||||
{
|
||||
return &clipSel;
|
||||
}
|
||||
|
||||
GTrack(int x, int y, int w, int h, const char* l = 0 );
|
||||
|
||||
|
||||
// getters
|
||||
float getSend();
|
||||
float getXSide();
|
||||
|
||||
bool getSendActive();
|
||||
bool getKeyActive();
|
||||
bool getRecordActive();
|
||||
|
||||
// setters
|
||||
void setSend(float s);
|
||||
void setXSide(float s);
|
||||
|
||||
void setSendActive(bool a);
|
||||
void setKeyActive(bool a);
|
||||
void setRecordActive(bool a);
|
||||
|
||||
void setJackSend(float s);
|
||||
void setJackSendActivate(bool a);
|
||||
|
||||
int ID;
|
||||
|
||||
Avtk::Background bg;
|
||||
|
||||
Avtk::RadialStatus radial;
|
||||
|
||||
Avtk::ClipSelector clipSel;
|
||||
|
||||
Avtk::Box volBox;
|
||||
|
||||
Avtk::Volume volume;
|
||||
|
||||
float getJackSend();
|
||||
bool getJackSendActivate();
|
||||
private:
|
||||
Avtk::Box jackSendBox;
|
||||
Avtk::Dial jackSendDial;
|
||||
Avtk::LightButton jackSendActivate;
|
||||
Avtk::Box jackSendBox;
|
||||
Avtk::Dial jackSendDial;
|
||||
Avtk::LightButton jackSendActivate;
|
||||
|
||||
Avtk::Dial sendDial;
|
||||
Avtk::LightButton sendActive;
|
||||
|
||||
Avtk::Dial xsideDial;
|
||||
Avtk::LightButton keyActive;
|
||||
|
||||
Avtk::LightButton recordActive;
|
||||
|
||||
|
||||
static int privateID;
|
||||
Avtk::Dial sendDial;
|
||||
Avtk::LightButton sendActive;
|
||||
|
||||
Avtk::Dial xsideDial;
|
||||
Avtk::LightButton keyActive;
|
||||
|
||||
Avtk::LightButton recordActive;
|
||||
|
||||
|
||||
static int privateID;
|
||||
};
|
||||
|
||||
#endif // LUPPP_G_TRACK_H
|
||||
|
|
1311
src/gui.cxx
1311
src/gui.cxx
File diff suppressed because it is too large
Load diff
191
src/gui.hxx
191
src/gui.hxx
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -46,92 +46,107 @@ class AudioBuffer;
|
|||
|
||||
class Gui
|
||||
{
|
||||
public:
|
||||
Gui(const char* argZero);
|
||||
~Gui();
|
||||
|
||||
int show();
|
||||
|
||||
int quit();
|
||||
void askQuit();
|
||||
|
||||
/// returns the options window
|
||||
OptionsWindow* getOptionsWindow();
|
||||
|
||||
/// open audio editor window with an AudioBuffer
|
||||
AudioEditor* getAudioEditor();
|
||||
|
||||
/// resets the state to "new"
|
||||
void reset();
|
||||
|
||||
/// sets up MIDI controllers: must be done *after* backend is started
|
||||
void addMidiControllerToSetup(std::string);
|
||||
void setupMidiControllers();
|
||||
|
||||
GTrack* getTrack(int id);
|
||||
GMasterTrack* getMasterTrack(){return master;}
|
||||
|
||||
DiskWriter* getDiskWriter(){return diskWriter;}
|
||||
DiskReader* getDiskReader(){return diskReader;}
|
||||
|
||||
/// used to load samples into the grid
|
||||
void selectLoadSample( int track, int clip );
|
||||
void selectSaveSample( int track, int clip );
|
||||
char* selectSavePath();
|
||||
|
||||
/// allows the user to select a Controller definition
|
||||
static void selectLoadController(Fl_Widget* w, void*);
|
||||
|
||||
|
||||
int samplerate;
|
||||
|
||||
////Enable per track send and resturn jack ports
|
||||
bool enablePerTrackOutput;
|
||||
public:
|
||||
Gui(const char* argZero);
|
||||
~Gui();
|
||||
|
||||
int getWindowWidth(){return window.w();}
|
||||
|
||||
nsm_client_t* getNsm(){return nsm;}
|
||||
|
||||
|
||||
/// current special clip:
|
||||
int specialTrack;
|
||||
int specialScene;
|
||||
|
||||
/// The project directory is the default directoy which is shown upon load/save
|
||||
void setProjectsDir(string dir);
|
||||
string getProjectsDir();
|
||||
|
||||
// save a particular sample to path
|
||||
std::string saveBufferPath;
|
||||
|
||||
private:
|
||||
vector<std::string> controllerVector;
|
||||
|
||||
Fl_Double_Window window;
|
||||
|
||||
Fl_Group* lupppGroup;
|
||||
|
||||
OptionsWindow* optionWindow;
|
||||
|
||||
std::string lupppProjectsDir;
|
||||
|
||||
AudioEditor* audioEditor;
|
||||
|
||||
DiskReader* diskReader;
|
||||
DiskWriter* diskWriter;
|
||||
|
||||
GMasterTrack* master;
|
||||
|
||||
vector<GTrack*> tracks;
|
||||
|
||||
// FIXME: refactor tooltip code out..?
|
||||
std::string tooltip;
|
||||
Fl_Box* tooltipLabel;
|
||||
|
||||
// non-session-manager
|
||||
nsm_client_t* nsm;
|
||||
|
||||
static int keyboardHandler(int event);
|
||||
int show();
|
||||
|
||||
int quit();
|
||||
void askQuit();
|
||||
|
||||
/// returns the options window
|
||||
OptionsWindow* getOptionsWindow();
|
||||
|
||||
/// open audio editor window with an AudioBuffer
|
||||
AudioEditor* getAudioEditor();
|
||||
|
||||
/// resets the state to "new"
|
||||
void reset();
|
||||
|
||||
/// sets up MIDI controllers: must be done *after* backend is started
|
||||
void addMidiControllerToSetup(std::string);
|
||||
void setupMidiControllers();
|
||||
|
||||
GTrack* getTrack(int id);
|
||||
GMasterTrack* getMasterTrack()
|
||||
{
|
||||
return master;
|
||||
}
|
||||
|
||||
DiskWriter* getDiskWriter()
|
||||
{
|
||||
return diskWriter;
|
||||
}
|
||||
DiskReader* getDiskReader()
|
||||
{
|
||||
return diskReader;
|
||||
}
|
||||
|
||||
/// used to load samples into the grid
|
||||
void selectLoadSample( int track, int clip );
|
||||
void selectSaveSample( int track, int clip );
|
||||
char* selectSavePath();
|
||||
|
||||
/// allows the user to select a Controller definition
|
||||
static void selectLoadController(Fl_Widget* w, void*);
|
||||
|
||||
|
||||
int samplerate;
|
||||
|
||||
////Enable per track send and resturn jack ports
|
||||
bool enablePerTrackOutput;
|
||||
|
||||
int getWindowWidth()
|
||||
{
|
||||
return window.w();
|
||||
}
|
||||
|
||||
nsm_client_t* getNsm()
|
||||
{
|
||||
return nsm;
|
||||
}
|
||||
|
||||
|
||||
/// current special clip:
|
||||
int specialTrack;
|
||||
int specialScene;
|
||||
|
||||
/// The project directory is the default directoy which is shown upon load/save
|
||||
void setProjectsDir(string dir);
|
||||
string getProjectsDir();
|
||||
|
||||
// save a particular sample to path
|
||||
std::string saveBufferPath;
|
||||
|
||||
private:
|
||||
vector<std::string> controllerVector;
|
||||
|
||||
Fl_Double_Window window;
|
||||
|
||||
Fl_Group* lupppGroup;
|
||||
|
||||
OptionsWindow* optionWindow;
|
||||
|
||||
std::string lupppProjectsDir;
|
||||
|
||||
AudioEditor* audioEditor;
|
||||
|
||||
DiskReader* diskReader;
|
||||
DiskWriter* diskWriter;
|
||||
|
||||
GMasterTrack* master;
|
||||
|
||||
vector<GTrack*> tracks;
|
||||
|
||||
// FIXME: refactor tooltip code out..?
|
||||
std::string tooltip;
|
||||
Fl_Box* tooltipLabel;
|
||||
|
||||
// non-session-manager
|
||||
nsm_client_t* nsm;
|
||||
|
||||
static int keyboardHandler(int event);
|
||||
};
|
||||
|
||||
#endif // LUPPP_GUI
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -37,35 +37,35 @@ using namespace std;
|
|||
|
||||
class GUnitTrack : public Fl_Group
|
||||
{
|
||||
public:
|
||||
GUnitTrack(int x, int y, int w, int h, const char* l = 0 ) :
|
||||
Fl_Group(x, y, w, h),
|
||||
title( strdup(l) ),
|
||||
bg( x, y , w, h, title )
|
||||
{
|
||||
int uh = h / 5;
|
||||
unit[0] = new Avtk::Unit(x + 2, y + uh * 4 - 2, w - 6, h / 5 - 2,"1");
|
||||
unit[1] = new Avtk::Unit(x + 2, y + uh * 3 - 2, w - 6, h / 5 - 2,"2");
|
||||
unit[2] = new Avtk::Unit(x + 2, y + uh * 2 - 2, w - 6, h / 5 - 2,"3");
|
||||
unit[3] = new Avtk::Unit(x + 2, y + uh * 1 - 2, w - 6, h / 5 - 2,"4");
|
||||
unit[4] = new Avtk::Unit(x + 2, y - 2 , w - 6, h / 5 - 2,"5");
|
||||
|
||||
end(); // close the group
|
||||
}
|
||||
|
||||
~GUnitTrack()
|
||||
{
|
||||
free(title);
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
char* title;
|
||||
|
||||
Avtk::Background bg;
|
||||
|
||||
Avtk::Unit* unit[5];
|
||||
|
||||
public:
|
||||
GUnitTrack(int x, int y, int w, int h, const char* l = 0 ) :
|
||||
Fl_Group(x, y, w, h),
|
||||
title( strdup(l) ),
|
||||
bg( x, y , w, h, title )
|
||||
{
|
||||
int uh = h / 5;
|
||||
unit[0] = new Avtk::Unit(x + 2, y + uh * 4 - 2, w - 6, h / 5 - 2,"1");
|
||||
unit[1] = new Avtk::Unit(x + 2, y + uh * 3 - 2, w - 6, h / 5 - 2,"2");
|
||||
unit[2] = new Avtk::Unit(x + 2, y + uh * 2 - 2, w - 6, h / 5 - 2,"3");
|
||||
unit[3] = new Avtk::Unit(x + 2, y + uh * 1 - 2, w - 6, h / 5 - 2,"4");
|
||||
unit[4] = new Avtk::Unit(x + 2, y - 2 , w - 6, h / 5 - 2,"5");
|
||||
|
||||
end(); // close the group
|
||||
}
|
||||
|
||||
~GUnitTrack()
|
||||
{
|
||||
free(title);
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
char* title;
|
||||
|
||||
Avtk::Background bg;
|
||||
|
||||
Avtk::Unit* unit[5];
|
||||
|
||||
};
|
||||
|
||||
#endif // LUPPP_G_UNIT_TRACK_H
|
||||
|
|
1020
src/jack.cxx
1020
src/jack.cxx
File diff suppressed because it is too large
Load diff
288
src/jack.hxx
288
src/jack.hxx
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -54,144 +54,162 @@ using namespace std;
|
|||
**/
|
||||
class Jack
|
||||
{
|
||||
public:
|
||||
Jack(std::string name);
|
||||
~Jack();
|
||||
|
||||
static void setup(std::string name);
|
||||
|
||||
void activate();
|
||||
/// quits the JACK client, destroying ports etc. Call only on exit of Luppp.
|
||||
void quit();
|
||||
|
||||
int getBuffersize();
|
||||
int getSamplerate();
|
||||
|
||||
// Luppp process callback: bar() events can occur between these
|
||||
void processFrames(int nframes);
|
||||
public:
|
||||
Jack(std::string name);
|
||||
~Jack();
|
||||
|
||||
//Sets the first nframes of all the internal output buffers to zero. NO LIMIT CHECKS
|
||||
void clearInternalBuffers(int nframes);
|
||||
|
||||
/// get functions for components owned by Jack
|
||||
Looper* getLooper(int t);
|
||||
TrackOutput* getTrackOutput(int t);
|
||||
|
||||
State* getState(){return state;}
|
||||
Logic* getLogic(){return logic;}
|
||||
Metronome* getMetronome(){return metronome;}
|
||||
GridLogic* getGridLogic(){return gridLogic;}
|
||||
TimeManager* getTimeManager(){return timeManager;}
|
||||
ControllerUpdater* getControllerUpdater(){return controllerUpdater;}
|
||||
static void setup(std::string name);
|
||||
|
||||
void transportRolling(bool rolling);
|
||||
|
||||
/// register a MIDI observer
|
||||
void registerMidiIO( MidiIO* mo );
|
||||
void unregisterMidiIO( MidiIO* mo );
|
||||
|
||||
/// set the master i/o volume / sends
|
||||
void inputVolume( float vol );
|
||||
void masterVolume( float vol );
|
||||
void returnVolume( float vol );
|
||||
void inputTo(INPUT_TO to, float v);
|
||||
void inputToActive(INPUT_TO to, bool a);
|
||||
|
||||
jack_client_t* getJackClientPointer()
|
||||
{
|
||||
return client;
|
||||
};
|
||||
|
||||
void resetMidiBindingState();
|
||||
|
||||
// MIDI binding creation
|
||||
bool bindingEventRecordEnable;
|
||||
int bindingEventType;
|
||||
int bindingTrack;
|
||||
int bindingScene;
|
||||
int bindingSend;
|
||||
int bindingActive;
|
||||
void activate();
|
||||
/// quits the JACK client, destroying ports etc. Call only on exit of Luppp.
|
||||
void quit();
|
||||
|
||||
JackSendReturn *getJackSendReturn(int t);
|
||||
int getBuffersize();
|
||||
int getSamplerate();
|
||||
|
||||
// Luppp process callback: bar() events can occur between these
|
||||
void processFrames(int nframes);
|
||||
|
||||
//Sets the first nframes of all the internal output buffers to zero. NO LIMIT CHECKS
|
||||
void clearInternalBuffers(int nframes);
|
||||
|
||||
/// get functions for components owned by Jack
|
||||
Looper* getLooper(int t);
|
||||
TrackOutput* getTrackOutput(int t);
|
||||
|
||||
State* getState()
|
||||
{
|
||||
return state;
|
||||
}
|
||||
Logic* getLogic()
|
||||
{
|
||||
return logic;
|
||||
}
|
||||
Metronome* getMetronome()
|
||||
{
|
||||
return metronome;
|
||||
}
|
||||
GridLogic* getGridLogic()
|
||||
{
|
||||
return gridLogic;
|
||||
}
|
||||
TimeManager* getTimeManager()
|
||||
{
|
||||
return timeManager;
|
||||
}
|
||||
ControllerUpdater* getControllerUpdater()
|
||||
{
|
||||
return controllerUpdater;
|
||||
}
|
||||
|
||||
void transportRolling(bool rolling);
|
||||
|
||||
/// register a MIDI observer
|
||||
void registerMidiIO( MidiIO* mo );
|
||||
void unregisterMidiIO( MidiIO* mo );
|
||||
|
||||
/// set the master i/o volume / sends
|
||||
void inputVolume( float vol );
|
||||
void masterVolume( float vol );
|
||||
void returnVolume( float vol );
|
||||
void inputTo(INPUT_TO to, float v);
|
||||
void inputToActive(INPUT_TO to, bool a);
|
||||
|
||||
jack_client_t* getJackClientPointer()
|
||||
{
|
||||
return client;
|
||||
};
|
||||
|
||||
void resetMidiBindingState();
|
||||
|
||||
// MIDI binding creation
|
||||
bool bindingEventRecordEnable;
|
||||
int bindingEventType;
|
||||
int bindingTrack;
|
||||
int bindingScene;
|
||||
int bindingSend;
|
||||
int bindingActive;
|
||||
|
||||
JackSendReturn *getJackSendReturn(int t);
|
||||
private:
|
||||
int lastnframes;
|
||||
jack_client_t* client;
|
||||
|
||||
Buffers buffers;
|
||||
TimeManager* timeManager;
|
||||
Metronome* metronome;
|
||||
State* state;
|
||||
Logic* logic;
|
||||
GridLogic* gridLogic;
|
||||
ControllerUpdater* controllerUpdater;
|
||||
|
||||
vector<Looper*> loopers;
|
||||
vector<JackSendReturn*> tracksendreturns;
|
||||
vector<TrackOutput*> trackOutputs;
|
||||
|
||||
vector<MidiIO*> midiIO;
|
||||
|
||||
// FX
|
||||
DBMeter* inputMeter;
|
||||
DBMeter* masterMeter;
|
||||
|
||||
float inputVol;
|
||||
/// _toMasterLag is a volume that lags behind _toMaster when setMaster() is called
|
||||
/// This prohibits audible jumps when rapidly changing the volume
|
||||
float masterVol;
|
||||
float masterVolLag;
|
||||
float masterVolDiff;
|
||||
float returnVol;
|
||||
|
||||
float inputToMixVol;
|
||||
float inputToSendVol;
|
||||
float inputToXSideVol;
|
||||
|
||||
bool inputToKeyEnable;
|
||||
bool inputToMixEnable;
|
||||
bool inputToSendEnable;
|
||||
|
||||
// JACK member variables
|
||||
bool clientActive;
|
||||
int samplerate;
|
||||
|
||||
jack_port_t* masterInput;
|
||||
jack_port_t* masterOutputL;
|
||||
jack_port_t* masterOutputR;
|
||||
int lastnframes;
|
||||
jack_client_t* client;
|
||||
|
||||
jack_port_t* masterReturnL;
|
||||
jack_port_t* masterReturnR;
|
||||
jack_port_t* headphonesPort;
|
||||
|
||||
jack_port_t* sidechainKeyOutput;
|
||||
jack_port_t* sidechainSignalOutput;
|
||||
jack_port_t* sendOutput;
|
||||
|
||||
jack_port_t* masterMidiInput;
|
||||
Buffers buffers;
|
||||
TimeManager* timeManager;
|
||||
Metronome* metronome;
|
||||
State* state;
|
||||
Logic* logic;
|
||||
GridLogic* gridLogic;
|
||||
ControllerUpdater* controllerUpdater;
|
||||
|
||||
vector<Looper*> loopers;
|
||||
vector<JackSendReturn*> tracksendreturns;
|
||||
vector<TrackOutput*> trackOutputs;
|
||||
|
||||
vector<MidiIO*> midiIO;
|
||||
|
||||
// FX
|
||||
DBMeter* inputMeter;
|
||||
DBMeter* masterMeter;
|
||||
|
||||
float inputVol;
|
||||
/// _toMasterLag is a volume that lags behind _toMaster when setMaster() is called
|
||||
/// This prohibits audible jumps when rapidly changing the volume
|
||||
float masterVol;
|
||||
float masterVolLag;
|
||||
float masterVolDiff;
|
||||
float returnVol;
|
||||
|
||||
float inputToMixVol;
|
||||
float inputToSendVol;
|
||||
float inputToXSideVol;
|
||||
|
||||
bool inputToKeyEnable;
|
||||
bool inputToMixEnable;
|
||||
bool inputToSendEnable;
|
||||
|
||||
// JACK member variables
|
||||
bool clientActive;
|
||||
int samplerate;
|
||||
|
||||
jack_port_t* masterInput;
|
||||
jack_port_t* masterOutputL;
|
||||
jack_port_t* masterOutputR;
|
||||
|
||||
jack_port_t* masterReturnL;
|
||||
jack_port_t* masterReturnR;
|
||||
jack_port_t* headphonesPort;
|
||||
|
||||
jack_port_t* sidechainKeyOutput;
|
||||
jack_port_t* sidechainSignalOutput;
|
||||
jack_port_t* sendOutput;
|
||||
|
||||
jack_port_t* masterMidiInput;
|
||||
|
||||
jack_port_t* trackJackOutputPorts[NTRACKS];
|
||||
|
||||
// JACK callback
|
||||
int process (jack_nframes_t);
|
||||
|
||||
int timebase(jack_transport_state_t,
|
||||
jack_nframes_t,
|
||||
jack_position_t*,
|
||||
int );
|
||||
|
||||
// static JACK callbacks
|
||||
static int static_process (jack_nframes_t, void *);
|
||||
|
||||
static int static_timebase (jack_transport_state_t,
|
||||
jack_nframes_t,
|
||||
jack_position_t*,
|
||||
int,
|
||||
void* );
|
||||
|
||||
// UI update variables
|
||||
int uiUpdateCounter;
|
||||
int uiUpdateConstant;
|
||||
|
||||
jack_port_t* trackJackOutputPorts[NTRACKS];
|
||||
|
||||
// JACK callback
|
||||
int process (jack_nframes_t);
|
||||
|
||||
int timebase(jack_transport_state_t,
|
||||
jack_nframes_t,
|
||||
jack_position_t*,
|
||||
int );
|
||||
|
||||
// static JACK callbacks
|
||||
static int static_process (jack_nframes_t, void *);
|
||||
|
||||
static int static_timebase (jack_transport_state_t,
|
||||
jack_nframes_t,
|
||||
jack_position_t*,
|
||||
int,
|
||||
void* );
|
||||
|
||||
// UI update variables
|
||||
int uiUpdateCounter;
|
||||
int uiUpdateConstant;
|
||||
|
||||
};
|
||||
|
||||
#endif // LUPPP_JACK_H
|
||||
|
|
|
@ -4,63 +4,62 @@
|
|||
#include <assert.h>
|
||||
extern Jack* jack;
|
||||
JackSendReturn::JackSendReturn(int trackid, AudioProcessor *prev, jack_client_t *client)
|
||||
:m_trackid(trackid), m_previousProcessor(prev), m_sendvol(1.0f)
|
||||
:m_trackid(trackid), m_previousProcessor(prev), m_sendvol(1.0f)
|
||||
{
|
||||
char name[50];
|
||||
sprintf(name, "Send_track_%d\n",trackid);
|
||||
m_sendport=jack_port_register(client,name,JACK_DEFAULT_AUDIO_TYPE,JackPortIsOutput,0);
|
||||
sprintf(name, "Return_track_%d\n",trackid);
|
||||
m_returnport=jack_port_register(client,name,JACK_DEFAULT_AUDIO_TYPE,JackPortIsInput,0);
|
||||
m_active=false;
|
||||
m_counter=0;
|
||||
char name[50];
|
||||
sprintf(name, "Send_track_%d\n",trackid);
|
||||
m_sendport=jack_port_register(client,name,JACK_DEFAULT_AUDIO_TYPE,JackPortIsOutput,0);
|
||||
sprintf(name, "Return_track_%d\n",trackid);
|
||||
m_returnport=jack_port_register(client,name,JACK_DEFAULT_AUDIO_TYPE,JackPortIsInput,0);
|
||||
m_active=false;
|
||||
m_counter=0;
|
||||
}
|
||||
|
||||
void JackSendReturn::process(unsigned int nframes, Buffers *buffers)
|
||||
{
|
||||
//Reset send buffer
|
||||
int offset=m_counter%(buffers->nframes);
|
||||
float* sendtrack=&(buffers->audio[Buffers::SEND_TRACK_0+m_trackid][0]);
|
||||
//Reset send buffer
|
||||
int offset=m_counter%(buffers->nframes);
|
||||
float* sendtrack=&(buffers->audio[Buffers::SEND_TRACK_0+m_trackid][0]);
|
||||
|
||||
|
||||
float* rettrack=&(buffers->audio[Buffers::RETURN_TRACK_0+m_trackid][0]);
|
||||
float* rettrack=&(buffers->audio[Buffers::RETURN_TRACK_0+m_trackid][0]);
|
||||
|
||||
memset(sendtrack,0,nframes*sizeof(float));
|
||||
memset(sendtrack,0,nframes*sizeof(float));
|
||||
|
||||
//Process previous AudioProcessor
|
||||
m_previousProcessor->process(nframes,buffers);
|
||||
float* send=(float*)jack_port_get_buffer(m_sendport,(jack_nframes_t)(buffers->nframes));
|
||||
float* ret=(float*)jack_port_get_buffer(m_returnport,(jack_nframes_t)(buffers->nframes));
|
||||
if(offset)
|
||||
{
|
||||
send+=offset;
|
||||
ret+=offset;
|
||||
}
|
||||
//Process previous AudioProcessor
|
||||
m_previousProcessor->process(nframes,buffers);
|
||||
float* send=(float*)jack_port_get_buffer(m_sendport,(jack_nframes_t)(buffers->nframes));
|
||||
float* ret=(float*)jack_port_get_buffer(m_returnport,(jack_nframes_t)(buffers->nframes));
|
||||
if(offset) {
|
||||
send+=offset;
|
||||
ret+=offset;
|
||||
}
|
||||
|
||||
for(int i=0;i<nframes;i++)
|
||||
send[i]=m_sendvol*sendtrack[i];
|
||||
for(int i=0; i<nframes; i++)
|
||||
send[i]=m_sendvol*sendtrack[i];
|
||||
// if(nframes!=buffers->nframes)
|
||||
// {
|
||||
// cout<<send<<endl;
|
||||
// }
|
||||
|
||||
if(offset)
|
||||
assert(offset+nframes==buffers->nframes);
|
||||
if(offset)
|
||||
assert(offset+nframes==buffers->nframes);
|
||||
|
||||
if(m_active)
|
||||
memcpy(rettrack,ret,nframes*sizeof(float));
|
||||
else
|
||||
memcpy(rettrack,
|
||||
sendtrack,nframes*sizeof(float));
|
||||
m_counter+=nframes;
|
||||
if(m_active)
|
||||
memcpy(rettrack,ret,nframes*sizeof(float));
|
||||
else
|
||||
memcpy(rettrack,
|
||||
sendtrack,nframes*sizeof(float));
|
||||
m_counter+=nframes;
|
||||
|
||||
}
|
||||
|
||||
void JackSendReturn::activate(bool act)
|
||||
{
|
||||
m_active=act;
|
||||
m_active=act;
|
||||
}
|
||||
|
||||
void JackSendReturn::sendVolume(float vol)
|
||||
{
|
||||
m_sendvol=vol;
|
||||
m_sendvol=vol;
|
||||
}
|
||||
|
|
|
@ -30,25 +30,25 @@
|
|||
class JackSendReturn: public AudioProcessor
|
||||
{
|
||||
public:
|
||||
//Constructor: the registration of the jack send/return is done here
|
||||
JackSendReturn(int trackid,AudioProcessor* prev,jack_client_t* client);
|
||||
//Constructor: the registration of the jack send/return is done here
|
||||
JackSendReturn(int trackid,AudioProcessor* prev,jack_client_t* client);
|
||||
|
||||
//The process callback
|
||||
virtual void process(unsigned int nframes, Buffers* buffers);
|
||||
//The process callback
|
||||
virtual void process(unsigned int nframes, Buffers* buffers);
|
||||
|
||||
//Activate the return chain. When m_active=true then Buffers::RETURN_TRACK_0+m_trackid gets the data
|
||||
//from the return port. The send port always send the incoming data
|
||||
void activate(bool act);
|
||||
void sendVolume(float vol);
|
||||
//Activate the return chain. When m_active=true then Buffers::RETURN_TRACK_0+m_trackid gets the data
|
||||
//from the return port. The send port always send the incoming data
|
||||
void activate(bool act);
|
||||
void sendVolume(float vol);
|
||||
|
||||
private:
|
||||
bool m_active;
|
||||
float m_sendvol;
|
||||
jack_port_t* m_sendport;
|
||||
jack_port_t* m_returnport;
|
||||
int m_trackid;
|
||||
AudioProcessor* m_previousProcessor;
|
||||
int m_counter;
|
||||
bool m_active;
|
||||
float m_sendvol;
|
||||
jack_port_t* m_sendport;
|
||||
jack_port_t* m_returnport;
|
||||
int m_trackid;
|
||||
AudioProcessor* m_previousProcessor;
|
||||
int m_counter;
|
||||
};
|
||||
|
||||
|
||||
|
|
160
src/logic.cxx
160
src/logic.cxx
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -28,154 +28,130 @@ extern Jack* jack;
|
|||
#include "jacksendreturn.hxx"
|
||||
Logic::Logic()
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
void Logic::tapTempo()
|
||||
{
|
||||
jack->getTimeManager()->tap();
|
||||
jack->getTimeManager()->tap();
|
||||
}
|
||||
|
||||
void Logic::setBpm(float bpm)
|
||||
{
|
||||
jack->getTimeManager()->setBpm( bpm );
|
||||
jack->getTimeManager()->setBpm( bpm );
|
||||
}
|
||||
|
||||
void Logic::metronomeEnable(bool b)
|
||||
{
|
||||
jack->getMetronome()->setActive(b);
|
||||
jack->getControllerUpdater()->metronomeEnable( b );
|
||||
jack->getMetronome()->setActive(b);
|
||||
jack->getControllerUpdater()->metronomeEnable( b );
|
||||
}
|
||||
|
||||
void Logic::masterInputVol( float v )
|
||||
{
|
||||
jack->inputVolume( v );
|
||||
jack->getControllerUpdater()->masterInputVol( v );
|
||||
jack->inputVolume( v );
|
||||
jack->getControllerUpdater()->masterInputVol( v );
|
||||
}
|
||||
|
||||
void Logic::masterInputTo( int to, float v )
|
||||
{
|
||||
jack->inputTo( (Event::INPUT_TO)to, v );
|
||||
jack->getControllerUpdater()->masterInputTo( to, v );
|
||||
jack->inputTo( (Event::INPUT_TO)to, v );
|
||||
jack->getControllerUpdater()->masterInputTo( to, v );
|
||||
}
|
||||
|
||||
void Logic::masterInputToActive( int inputTo, bool active)
|
||||
{
|
||||
jack->inputToActive( (Event::INPUT_TO)inputTo, active);
|
||||
jack->getControllerUpdater()->masterInputToActive( (int)inputTo, active );
|
||||
jack->inputToActive( (Event::INPUT_TO)inputTo, active);
|
||||
jack->getControllerUpdater()->masterInputToActive( (int)inputTo, active );
|
||||
}
|
||||
|
||||
void Logic::masterReturn( int returnNum, float value )
|
||||
{
|
||||
jack->returnVolume( value );
|
||||
jack->getControllerUpdater()->masterReturnVolume( value );
|
||||
jack->returnVolume( value );
|
||||
jack->getControllerUpdater()->masterReturnVolume( value );
|
||||
}
|
||||
|
||||
void Logic::trackVolume(int t, float v)
|
||||
{
|
||||
if ( t == -1 ) // master track
|
||||
{
|
||||
jack->masterVolume(v);
|
||||
jack->getControllerUpdater()->masterVolume( v );
|
||||
}
|
||||
else if ( t >= 0 && t < NTRACKS )
|
||||
{
|
||||
jack->getTrackOutput( t )->setMaster( v );
|
||||
jack->getControllerUpdater()->volume( t, v );
|
||||
}
|
||||
else
|
||||
{
|
||||
LUPPP_WARN("invalid track number %i: check controller map has \"track\" field.", t );
|
||||
}
|
||||
if ( t == -1 ) { // master track
|
||||
jack->masterVolume(v);
|
||||
jack->getControllerUpdater()->masterVolume( v );
|
||||
} else if ( t >= 0 && t < NTRACKS ) {
|
||||
jack->getTrackOutput( t )->setMaster( v );
|
||||
jack->getControllerUpdater()->volume( t, v );
|
||||
} else {
|
||||
LUPPP_WARN("invalid track number %i: check controller map has \"track\" field.", t );
|
||||
}
|
||||
}
|
||||
|
||||
void Logic::trackRecordArm(int t, bool v)
|
||||
{
|
||||
if ( t >= 0 && t < NTRACKS )
|
||||
{
|
||||
jack->getTrackOutput( t )->recordArm( v );
|
||||
jack->getControllerUpdater()->recordArm( t, v );
|
||||
}
|
||||
else
|
||||
{
|
||||
LUPPP_WARN("invalid track number %i: check controller map has \"track\" field.", t );
|
||||
}
|
||||
if ( t >= 0 && t < NTRACKS ) {
|
||||
jack->getTrackOutput( t )->recordArm( v );
|
||||
jack->getControllerUpdater()->recordArm( t, v );
|
||||
} else {
|
||||
LUPPP_WARN("invalid track number %i: check controller map has \"track\" field.", t );
|
||||
}
|
||||
}
|
||||
|
||||
void Logic::trackSendActive(int t, int s, bool v)
|
||||
{
|
||||
if ( t >= 0 && t < NTRACKS )
|
||||
{
|
||||
jack->getTrackOutput( t )->setSendActive( s, v );
|
||||
jack->getControllerUpdater()->setTrackSendActive( t, s, v );
|
||||
}
|
||||
else
|
||||
{
|
||||
LUPPP_WARN("invalid track number %i: check controller map has \"track\" field.", t );
|
||||
}
|
||||
if ( t >= 0 && t < NTRACKS ) {
|
||||
jack->getTrackOutput( t )->setSendActive( s, v );
|
||||
jack->getControllerUpdater()->setTrackSendActive( t, s, v );
|
||||
} else {
|
||||
LUPPP_WARN("invalid track number %i: check controller map has \"track\" field.", t );
|
||||
}
|
||||
}
|
||||
|
||||
void Logic::trackSend(int t, int send, float v)
|
||||
{
|
||||
if ( t >= 0 && t < NTRACKS )
|
||||
{
|
||||
jack->getTrackOutput( t )->setSend( send, v );
|
||||
jack->getControllerUpdater()->setTrackSend( t, send, v );
|
||||
}
|
||||
else
|
||||
{
|
||||
LUPPP_WARN("invalid track number %i: check controller map has \"track\" field.", t );
|
||||
}
|
||||
if ( t >= 0 && t < NTRACKS ) {
|
||||
jack->getTrackOutput( t )->setSend( send, v );
|
||||
jack->getControllerUpdater()->setTrackSend( t, send, v );
|
||||
} else {
|
||||
LUPPP_WARN("invalid track number %i: check controller map has \"track\" field.", t );
|
||||
}
|
||||
}
|
||||
|
||||
void Logic::trackJackSendActivate(int t, bool active)
|
||||
{
|
||||
if ( t >= 0 && t < NTRACKS )
|
||||
{
|
||||
jack->getJackSendReturn(t)->activate(active);
|
||||
jack->getControllerUpdater()->setTrackJackSendActive( t, active );
|
||||
}
|
||||
else
|
||||
{
|
||||
LUPPP_WARN("invalid track number %i: check controller map has \"track\" field.", t );
|
||||
}
|
||||
if ( t >= 0 && t < NTRACKS ) {
|
||||
jack->getJackSendReturn(t)->activate(active);
|
||||
jack->getControllerUpdater()->setTrackJackSendActive( t, active );
|
||||
} else {
|
||||
LUPPP_WARN("invalid track number %i: check controller map has \"track\" field.", t );
|
||||
}
|
||||
}
|
||||
|
||||
void Logic::trackJackSend(int t, float vol)
|
||||
{
|
||||
if ( t >= 0 && t < NTRACKS )
|
||||
{
|
||||
jack->getJackSendReturn(t)->sendVolume(vol);
|
||||
jack->getControllerUpdater()->setTrackJackSend( t, vol );
|
||||
}
|
||||
else
|
||||
{
|
||||
LUPPP_WARN("invalid track number %i: check controller map has \"track\" field.", t );
|
||||
}
|
||||
if ( t >= 0 && t < NTRACKS ) {
|
||||
jack->getJackSendReturn(t)->sendVolume(vol);
|
||||
jack->getControllerUpdater()->setTrackJackSend( t, vol );
|
||||
} else {
|
||||
LUPPP_WARN("invalid track number %i: check controller map has \"track\" field.", t );
|
||||
}
|
||||
}
|
||||
|
||||
void Logic::looperClipLenght(int t, int s, int l)
|
||||
{
|
||||
if ( t >= 0 && t < NTRACKS )
|
||||
{
|
||||
jack->getLooper( t )->getClip( s )->setBeats(l);
|
||||
}
|
||||
else
|
||||
{
|
||||
LUPPP_WARN("invalid track number %i: check controller map has \"track\" field.", t );
|
||||
}
|
||||
if ( t >= 0 && t < NTRACKS ) {
|
||||
jack->getLooper( t )->getClip( s )->setBeats(l);
|
||||
} else {
|
||||
LUPPP_WARN("invalid track number %i: check controller map has \"track\" field.", t );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Logic::looperUseAsTempo(int t, int s)
|
||||
{
|
||||
size_t clipBeats = jack->getLooper( t )->getClip( s )->getBeats();
|
||||
size_t clipFrames = jack->getLooper( t )->getClip( s )->getBufferLenght();
|
||||
|
||||
if ( clipBeats > 0 )
|
||||
{
|
||||
size_t framesPerBeat = clipFrames / clipBeats;
|
||||
jack->getTimeManager()->setFpb( framesPerBeat );
|
||||
}
|
||||
|
||||
size_t clipBeats = jack->getLooper( t )->getClip( s )->getBeats();
|
||||
size_t clipFrames = jack->getLooper( t )->getClip( s )->getBufferLenght();
|
||||
|
||||
if ( clipBeats > 0 ) {
|
||||
size_t framesPerBeat = clipFrames / clipBeats;
|
||||
jack->getTimeManager()->setFpb( framesPerBeat );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -25,42 +25,42 @@
|
|||
* This class contains an interface exposing most functionality in Luppp. The
|
||||
* interface is used to have one central place from where each controller can
|
||||
* interact with Luppp using the same function calls.
|
||||
*
|
||||
*
|
||||
* This class should be used for input from any device. The interface is
|
||||
* deliberatly specific with regards to scheduling events: controllers should
|
||||
* NOT attempt to schedule changes: use the provided functions directly when
|
||||
* events occur on a controller.
|
||||
*
|
||||
*
|
||||
* The ControllerUpdater class is the opposite of this class, it provides
|
||||
* feedback of each event that occurs.
|
||||
*
|
||||
*
|
||||
* Note: The GridLogic class provides the interface to scene selection / state.
|
||||
**/
|
||||
class Logic
|
||||
{
|
||||
public:
|
||||
Logic();
|
||||
|
||||
void tapTempo();
|
||||
void setBpm(float bpm); /// 0-1 input
|
||||
|
||||
void metronomeEnable(bool b);
|
||||
|
||||
void masterInputVol( float v );
|
||||
void masterInputTo( int inputTo, float v);
|
||||
void masterInputToActive( int inputTo, bool active);
|
||||
|
||||
void masterReturn( int returnNum, float v);
|
||||
|
||||
void trackVolume(int track, float volume);
|
||||
void trackRecordArm(int track, bool armed);
|
||||
void trackSendActive(int track, int send, bool active);
|
||||
void trackSend(int track, int send, float value);
|
||||
public:
|
||||
Logic();
|
||||
|
||||
void trackJackSendActivate(int t, bool active);
|
||||
void trackJackSend(int t, float vol);
|
||||
void looperUseAsTempo(int track, int scene);
|
||||
void looperClipLenght(int track, int scene, int lenght);
|
||||
void tapTempo();
|
||||
void setBpm(float bpm); /// 0-1 input
|
||||
|
||||
void metronomeEnable(bool b);
|
||||
|
||||
void masterInputVol( float v );
|
||||
void masterInputTo( int inputTo, float v);
|
||||
void masterInputToActive( int inputTo, bool active);
|
||||
|
||||
void masterReturn( int returnNum, float v);
|
||||
|
||||
void trackVolume(int track, float volume);
|
||||
void trackRecordArm(int track, bool armed);
|
||||
void trackSendActive(int track, int send, bool active);
|
||||
void trackSend(int track, int send, float value);
|
||||
|
||||
void trackJackSendActivate(int t, bool active);
|
||||
void trackJackSend(int t, float vol);
|
||||
void looperUseAsTempo(int track, int scene);
|
||||
void looperClipLenght(int track, int scene, int lenght);
|
||||
};
|
||||
|
||||
#endif // LUPPP_LOGIC_H
|
||||
|
|
263
src/looper.cxx
263
src/looper.cxx
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -31,50 +31,50 @@
|
|||
extern Jack* jack;
|
||||
|
||||
Looper::Looper(int t) :
|
||||
AudioProcessor(),
|
||||
TimeObserver(),
|
||||
track(t)
|
||||
AudioProcessor(),
|
||||
TimeObserver(),
|
||||
track(t)
|
||||
{
|
||||
uiUpdateConstant= jack->getSamplerate() / 30.f;
|
||||
uiUpdateCounter = jack->getSamplerate() / 30.f;
|
||||
|
||||
// pre-zero the internal sample
|
||||
//tmpRecordBuffer = (float*)malloc( sizeof(float) * MAX_BUFFER_SIZE );
|
||||
//memset( tmpRecordBuffer, 0, sizeof(float) * MAX_BUFFER_SIZE );
|
||||
|
||||
for(int i = 0; i < 10; i++ )
|
||||
{
|
||||
clips[i] = new LooperClip(track, i);
|
||||
}
|
||||
|
||||
tmpBuffer.resize( MAX_BUFFER_SIZE );
|
||||
|
||||
fpb = 22050;
|
||||
|
||||
// init faust pitch shift variables
|
||||
fSamplingFreq = jack->getSamplerate();
|
||||
IOTA = 0;
|
||||
|
||||
//tmpRecordBuffer.resize(MAX_BUFFER_SIZE);
|
||||
|
||||
for (int i=0; i<65536; i++)
|
||||
fVec0[i] = 0;
|
||||
for (int i=0; i<2; i++)
|
||||
fRec0[i] = 0;
|
||||
semitoneShift = 0.0f;
|
||||
windowSize = 1000;
|
||||
crossfadeSize = 1000;
|
||||
uiUpdateConstant= jack->getSamplerate() / 30.f;
|
||||
uiUpdateCounter = jack->getSamplerate() / 30.f;
|
||||
|
||||
// pre-zero the internal sample
|
||||
//tmpRecordBuffer = (float*)malloc( sizeof(float) * MAX_BUFFER_SIZE );
|
||||
//memset( tmpRecordBuffer, 0, sizeof(float) * MAX_BUFFER_SIZE );
|
||||
|
||||
for(int i = 0; i < 10; i++ ) {
|
||||
clips[i] = new LooperClip(track, i);
|
||||
}
|
||||
|
||||
tmpBuffer.resize( MAX_BUFFER_SIZE );
|
||||
|
||||
fpb = 22050;
|
||||
|
||||
// init faust pitch shift variables
|
||||
fSamplingFreq = jack->getSamplerate();
|
||||
IOTA = 0;
|
||||
|
||||
//tmpRecordBuffer.resize(MAX_BUFFER_SIZE);
|
||||
|
||||
for (int i=0; i<65536; i++)
|
||||
fVec0[i] = 0;
|
||||
for (int i=0; i<2; i++)
|
||||
fRec0[i] = 0;
|
||||
semitoneShift = 0.0f;
|
||||
windowSize = 1000;
|
||||
crossfadeSize = 1000;
|
||||
}
|
||||
|
||||
LooperClip* Looper::getClip(int scene)
|
||||
{
|
||||
return clips[scene];
|
||||
return clips[scene];
|
||||
}
|
||||
|
||||
void Looper::beat()
|
||||
{//TODO needed?
|
||||
//FIXME: Need to keep looperClips in sync when there exists no int N
|
||||
// such that playSpeed*N==1
|
||||
{
|
||||
//TODO needed?
|
||||
//FIXME: Need to keep looperClips in sync when there exists no int N
|
||||
// such that playSpeed*N==1
|
||||
// for(int i=0;i<NSCENES;i++)
|
||||
// {
|
||||
// int iph=clips[i]->getPlayhead()+1.0;
|
||||
|
@ -94,117 +94,108 @@ void Looper::beat()
|
|||
|
||||
void Looper::setRequestedBuffer(int s, AudioBuffer* ab)
|
||||
{
|
||||
clips[s]->setRequestedBuffer( ab );
|
||||
clips[s]->setRequestedBuffer( ab );
|
||||
}
|
||||
|
||||
void Looper::setFpb(int f)
|
||||
{
|
||||
fpb = f;
|
||||
fpb = f;
|
||||
}
|
||||
|
||||
void Looper::process(unsigned int nframes, Buffers* buffers)
|
||||
{
|
||||
// process each clip individually: this allows for playback of one clip,
|
||||
// while another clip records.
|
||||
for ( int clip = 0; clip < NSCENES; clip++ )
|
||||
{
|
||||
// handle state of clip, and do what needs doing:
|
||||
// record into buffer, play from buffer, etc
|
||||
if ( clips[clip]->recording() )
|
||||
{
|
||||
if ( clips[clip]->recordSpaceAvailable() < LOOPER_SAMPLES_BEFORE_REQUEST &&
|
||||
!clips[clip]->newBufferInTransit() )
|
||||
{
|
||||
EventLooperClipRequestBuffer e( track, clip, clips[clip]->audioBufferSize() + LOOPER_SAMPLES_UPDATE_SIZE);
|
||||
writeToGuiRingbuffer( &e );
|
||||
clips[clip]->newBufferInTransit(true);
|
||||
}
|
||||
|
||||
// copy data from input buffer to recording buffer
|
||||
float* input = buffers->audio[Buffers::MASTER_INPUT];
|
||||
clips[clip]->record( nframes, input, 0 );
|
||||
}
|
||||
else if ( clips[clip]->playing() )
|
||||
{
|
||||
// copy data into tmpBuffer, then pitch-stretch into track buffer
|
||||
long targetFrames = clips[clip]->getBeats() * fpb;
|
||||
long actualFrames = clips[clip]->getActualAudioLength();//getBufferLenght();
|
||||
float playSpeed = 1.0;
|
||||
|
||||
if ( targetFrames != 0 && actualFrames != 0 )
|
||||
{
|
||||
playSpeed = float(actualFrames) / targetFrames;
|
||||
}
|
||||
|
||||
float* out = buffers->audio[Buffers::SEND_TRACK_0 + track];
|
||||
|
||||
for(unsigned int i = 0; i < nframes; i++ )
|
||||
{
|
||||
// REFACTOR into system that is better than per sample function calls
|
||||
float tmp = clips[clip]->getSample(playSpeed);
|
||||
|
||||
float deltaPitch = 12 * log ( playSpeed ) / log (2);
|
||||
semitoneShift = -deltaPitch;
|
||||
|
||||
// write the pitch-shifted signal to the track buffer
|
||||
//FIXME: pitchShift adds delay even for playSpeed = 1.0!!
|
||||
//we should use something better (e.g librubberband)
|
||||
if(playSpeed!=1.0f)
|
||||
pitchShift( 1, &tmp, &out[i] );
|
||||
else
|
||||
out[i]+=tmp;
|
||||
}
|
||||
|
||||
//printf("Looper %i playing(), speed = %f\n", track, playSpeed );
|
||||
|
||||
if ( uiUpdateCounter > uiUpdateConstant )
|
||||
{
|
||||
jack->getControllerUpdater()->setTrackSceneProgress(track, clip, clips[clip]->getProgress() );
|
||||
uiUpdateCounter = 0;
|
||||
}
|
||||
uiUpdateCounter += nframes;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// process each clip individually: this allows for playback of one clip,
|
||||
// while another clip records.
|
||||
for ( int clip = 0; clip < NSCENES; clip++ ) {
|
||||
// handle state of clip, and do what needs doing:
|
||||
// record into buffer, play from buffer, etc
|
||||
if ( clips[clip]->recording() ) {
|
||||
if ( clips[clip]->recordSpaceAvailable() < LOOPER_SAMPLES_BEFORE_REQUEST &&
|
||||
!clips[clip]->newBufferInTransit() ) {
|
||||
EventLooperClipRequestBuffer e( track, clip, clips[clip]->audioBufferSize() + LOOPER_SAMPLES_UPDATE_SIZE);
|
||||
writeToGuiRingbuffer( &e );
|
||||
clips[clip]->newBufferInTransit(true);
|
||||
}
|
||||
|
||||
// copy data from input buffer to recording buffer
|
||||
float* input = buffers->audio[Buffers::MASTER_INPUT];
|
||||
clips[clip]->record( nframes, input, 0 );
|
||||
} else if ( clips[clip]->playing() ) {
|
||||
// copy data into tmpBuffer, then pitch-stretch into track buffer
|
||||
long targetFrames = clips[clip]->getBeats() * fpb;
|
||||
long actualFrames = clips[clip]->getActualAudioLength();//getBufferLenght();
|
||||
float playSpeed = 1.0;
|
||||
|
||||
if ( targetFrames != 0 && actualFrames != 0 ) {
|
||||
playSpeed = float(actualFrames) / targetFrames;
|
||||
}
|
||||
|
||||
float* out = buffers->audio[Buffers::SEND_TRACK_0 + track];
|
||||
|
||||
for(unsigned int i = 0; i < nframes; i++ ) {
|
||||
// REFACTOR into system that is better than per sample function calls
|
||||
float tmp = clips[clip]->getSample(playSpeed);
|
||||
|
||||
float deltaPitch = 12 * log ( playSpeed ) / log (2);
|
||||
semitoneShift = -deltaPitch;
|
||||
|
||||
// write the pitch-shifted signal to the track buffer
|
||||
//FIXME: pitchShift adds delay even for playSpeed = 1.0!!
|
||||
//we should use something better (e.g librubberband)
|
||||
if(playSpeed!=1.0f)
|
||||
pitchShift( 1, &tmp, &out[i] );
|
||||
else
|
||||
out[i]+=tmp;
|
||||
}
|
||||
|
||||
//printf("Looper %i playing(), speed = %f\n", track, playSpeed );
|
||||
|
||||
if ( uiUpdateCounter > uiUpdateConstant ) {
|
||||
jack->getControllerUpdater()->setTrackSceneProgress(track, clip, clips[clip]->getProgress() );
|
||||
uiUpdateCounter = 0;
|
||||
}
|
||||
uiUpdateCounter += nframes;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void Looper::resetTimeState()
|
||||
{
|
||||
for(int i=0;i<NSCENES;i++)
|
||||
clips[i]->setPlayHead(0.0);
|
||||
for(int i=0; i<NSCENES; i++)
|
||||
clips[i]->setPlayHead(0.0);
|
||||
}
|
||||
|
||||
void Looper::pitchShift(int count, float* input, float* output)
|
||||
{
|
||||
float fSlow0 = windowSize;
|
||||
float fSlow1 = ((1 + fSlow0) - powf(2,(0.08333333333333333f * semitoneShift)));
|
||||
float fSlow2 = (1.0f / crossfadeSize);
|
||||
float fSlow3 = (fSlow0 - 1);
|
||||
float* input0 = &input[0];
|
||||
//float* output0 = &output[0];
|
||||
|
||||
for (int i=0; i<count; i++)
|
||||
{
|
||||
float fTemp0 = (float)input0[i];
|
||||
fVec0[IOTA&65535] = fTemp0;
|
||||
fRec0[0] = fmodf((fRec0[1] + fSlow1),fSlow0);
|
||||
int iTemp1 = int(fRec0[0]);
|
||||
int iTemp2 = (1 + iTemp1);
|
||||
float fTemp3 = min((fSlow2 * fRec0[0]), 1.f );
|
||||
float fTemp4 = (fSlow0 + fRec0[0]);
|
||||
int iTemp5 = int(fTemp4);
|
||||
float out=output[0];
|
||||
out += (float)(((1 - fTemp3) * (((fTemp4 - iTemp5) *
|
||||
fVec0[(IOTA-int((int((1 + iTemp5)) & 65535)))&65535]) + ((0 - ((
|
||||
fRec0[0] + fSlow3) - iTemp5)) * fVec0[(IOTA-int((iTemp5 & 65535)))
|
||||
&65535]))) + (fTemp3 * (((fRec0[0] - iTemp1) * fVec0[(IOTA-int((int(
|
||||
iTemp2) & 65535)))&65535]) + ((iTemp2 - fRec0[0]) * fVec0[(IOTA-int((
|
||||
iTemp1 & 65535)))&65535]))));
|
||||
|
||||
output[0]=out;
|
||||
fRec0[1] = fRec0[0];
|
||||
IOTA = IOTA+1;
|
||||
}
|
||||
float fSlow0 = windowSize;
|
||||
float fSlow1 = ((1 + fSlow0) - powf(2,(0.08333333333333333f * semitoneShift)));
|
||||
float fSlow2 = (1.0f / crossfadeSize);
|
||||
float fSlow3 = (fSlow0 - 1);
|
||||
float* input0 = &input[0];
|
||||
//float* output0 = &output[0];
|
||||
|
||||
for (int i=0; i<count; i++) {
|
||||
float fTemp0 = (float)input0[i];
|
||||
fVec0[IOTA&65535] = fTemp0;
|
||||
fRec0[0] = fmodf((fRec0[1] + fSlow1),fSlow0);
|
||||
int iTemp1 = int(fRec0[0]);
|
||||
int iTemp2 = (1 + iTemp1);
|
||||
float fTemp3 = min((fSlow2 * fRec0[0]), 1.f );
|
||||
float fTemp4 = (fSlow0 + fRec0[0]);
|
||||
int iTemp5 = int(fTemp4);
|
||||
float out=output[0];
|
||||
out += (float)(((1 - fTemp3) * (((fTemp4 - iTemp5) *
|
||||
fVec0[(IOTA-int((int((1 + iTemp5)) & 65535)))&65535]) + ((0 - ((
|
||||
fRec0[0] + fSlow3) - iTemp5)) * fVec0[(IOTA-int((iTemp5 & 65535)))
|
||||
&65535]))) + (fTemp3 * (((fRec0[0] - iTemp1) * fVec0[(IOTA-int((int(
|
||||
iTemp2) & 65535)))&65535]) + ((iTemp2 - fRec0[0]) * fVec0[(IOTA-int((
|
||||
iTemp1 & 65535)))&65535]))));
|
||||
|
||||
output[0]=out;
|
||||
fRec0[1] = fRec0[0];
|
||||
IOTA = IOTA+1;
|
||||
}
|
||||
}
|
||||
|
|
102
src/looper.hxx
102
src/looper.hxx
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -37,55 +37,55 @@ using namespace std;
|
|||
**/
|
||||
class Looper : public AudioProcessor, public TimeObserver
|
||||
{
|
||||
public:
|
||||
Looper(int t);
|
||||
|
||||
/// *sets* the new audiobuffer, but the content gets copied to the new buffer.
|
||||
/// Used for infinite lenght recording
|
||||
void setRequestedBuffer(int s, AudioBuffer* ab);
|
||||
|
||||
/// stores the framesPerBeat from TimeManager. Used to stretch audio
|
||||
void setFpb(int f);
|
||||
|
||||
/// Retrieve a clip from the Looper
|
||||
LooperClip* getClip(int scene);
|
||||
|
||||
/// Override beat(). Resyncs loperclips to beat in case playSpeed is funny fraction
|
||||
/// that doesnt add up to 1 (e.g if playSpeed=3/4 then 3/4+3/4+3/4+3/4=3!=1 bringing
|
||||
/// looperClip out of sync)
|
||||
virtual void beat();
|
||||
/// Process nframes of audio
|
||||
void process(unsigned int nframes, Buffers* buffers);
|
||||
public:
|
||||
Looper(int t);
|
||||
|
||||
/// reset timestate implementation: rest all looperClips
|
||||
virtual void resetTimeState();
|
||||
|
||||
private:
|
||||
const int track;
|
||||
|
||||
/// variables used to determing the current actions of the looper
|
||||
int playingScene;
|
||||
int queuedScene;
|
||||
|
||||
int fpb;
|
||||
|
||||
//vector<float> tmpRecordBuffer;
|
||||
LooperClip* clips[10];
|
||||
|
||||
// Pitch Shifting
|
||||
void pitchShift(int count, float* input, float* output);
|
||||
vector<float> tmpBuffer;
|
||||
|
||||
int IOTA;
|
||||
float fVec0[65536];
|
||||
float semitoneShift;
|
||||
float windowSize;
|
||||
float fRec0[2];
|
||||
float crossfadeSize;
|
||||
float fSamplingFreq;
|
||||
|
||||
int uiUpdateConstant;
|
||||
int uiUpdateCounter;
|
||||
/// *sets* the new audiobuffer, but the content gets copied to the new buffer.
|
||||
/// Used for infinite lenght recording
|
||||
void setRequestedBuffer(int s, AudioBuffer* ab);
|
||||
|
||||
/// stores the framesPerBeat from TimeManager. Used to stretch audio
|
||||
void setFpb(int f);
|
||||
|
||||
/// Retrieve a clip from the Looper
|
||||
LooperClip* getClip(int scene);
|
||||
|
||||
/// Override beat(). Resyncs loperclips to beat in case playSpeed is funny fraction
|
||||
/// that doesnt add up to 1 (e.g if playSpeed=3/4 then 3/4+3/4+3/4+3/4=3!=1 bringing
|
||||
/// looperClip out of sync)
|
||||
virtual void beat();
|
||||
/// Process nframes of audio
|
||||
void process(unsigned int nframes, Buffers* buffers);
|
||||
|
||||
/// reset timestate implementation: rest all looperClips
|
||||
virtual void resetTimeState();
|
||||
|
||||
private:
|
||||
const int track;
|
||||
|
||||
/// variables used to determing the current actions of the looper
|
||||
int playingScene;
|
||||
int queuedScene;
|
||||
|
||||
int fpb;
|
||||
|
||||
//vector<float> tmpRecordBuffer;
|
||||
LooperClip* clips[10];
|
||||
|
||||
// Pitch Shifting
|
||||
void pitchShift(int count, float* input, float* output);
|
||||
vector<float> tmpBuffer;
|
||||
|
||||
int IOTA;
|
||||
float fVec0[65536];
|
||||
float semitoneShift;
|
||||
float windowSize;
|
||||
float fRec0[2];
|
||||
float crossfadeSize;
|
||||
float fSamplingFreq;
|
||||
|
||||
int uiUpdateConstant;
|
||||
int uiUpdateCounter;
|
||||
};
|
||||
|
||||
#endif // LUPPP_LOOPER_H
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -33,465 +33,429 @@
|
|||
extern Jack* jack;
|
||||
|
||||
LooperClip::LooperClip(int t, int s) :
|
||||
Stately(),
|
||||
track(t),
|
||||
scene(s)
|
||||
Stately(),
|
||||
track(t),
|
||||
scene(s)
|
||||
{
|
||||
_buffer = new AudioBuffer();
|
||||
_buffer->nonRtResize( 4410 );
|
||||
init();
|
||||
_buffer = new AudioBuffer();
|
||||
_buffer->nonRtResize( 4410 );
|
||||
init();
|
||||
}
|
||||
|
||||
void LooperClip::init()
|
||||
{
|
||||
_loaded = false;
|
||||
_playing = false;
|
||||
_recording = false;
|
||||
|
||||
_queuePlay = false;
|
||||
_queueStop = false;
|
||||
_queueRecord= false;
|
||||
|
||||
if ( _buffer )
|
||||
{
|
||||
_buffer->init();
|
||||
}
|
||||
_newBufferInTransit = false;
|
||||
|
||||
_playhead = 0;
|
||||
_recordhead = 0;
|
||||
|
||||
|
||||
_loaded = false;
|
||||
_playing = false;
|
||||
_recording = false;
|
||||
|
||||
_queuePlay = false;
|
||||
_queueStop = false;
|
||||
_queueRecord= false;
|
||||
|
||||
if ( _buffer ) {
|
||||
_buffer->init();
|
||||
}
|
||||
_newBufferInTransit = false;
|
||||
|
||||
_playhead = 0;
|
||||
_recordhead = 0;
|
||||
|
||||
|
||||
}
|
||||
|
||||
void LooperClip::save()
|
||||
{
|
||||
// ensure the buffer exists, and is saveable (not recording)
|
||||
if ( _loaded && !_recording && !_queueRecord )
|
||||
{
|
||||
char buffer [50];
|
||||
sprintf (buffer, "LC::save() track %i, scene %i", track,scene);
|
||||
EventGuiPrint e( buffer );
|
||||
writeToGuiRingbuffer( &e );
|
||||
|
||||
int frames = _buffer->getAudioFrames();
|
||||
EventRequestSaveBuffer e2( track, scene, frames );
|
||||
writeToGuiRingbuffer( &e2 );
|
||||
}
|
||||
else
|
||||
{
|
||||
// notify of "success" of save if there *is* no state to save
|
||||
Stately::success();
|
||||
}
|
||||
// ensure the buffer exists, and is saveable (not recording)
|
||||
if ( _loaded && !_recording && !_queueRecord ) {
|
||||
char buffer [50];
|
||||
sprintf (buffer, "LC::save() track %i, scene %i", track,scene);
|
||||
EventGuiPrint e( buffer );
|
||||
writeToGuiRingbuffer( &e );
|
||||
|
||||
int frames = _buffer->getAudioFrames();
|
||||
EventRequestSaveBuffer e2( track, scene, frames );
|
||||
writeToGuiRingbuffer( &e2 );
|
||||
} else {
|
||||
// notify of "success" of save if there *is* no state to save
|
||||
Stately::success();
|
||||
}
|
||||
}
|
||||
|
||||
void LooperClip::reset()
|
||||
{
|
||||
// TODO make the LooperClip reset to initial state
|
||||
if ( _loaded )
|
||||
{
|
||||
char buffer [50];
|
||||
sprintf (buffer, "LC::reset() track %i, scene %i", track,scene);
|
||||
EventGuiPrint e( buffer );
|
||||
writeToGuiRingbuffer( &e );
|
||||
|
||||
// set "progress" to zero as there's no clip anymore
|
||||
jack->getControllerUpdater()->setTrackSceneProgress(track, scene, 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
//SaveAble::done();
|
||||
}
|
||||
|
||||
init();
|
||||
// TODO make the LooperClip reset to initial state
|
||||
if ( _loaded ) {
|
||||
char buffer [50];
|
||||
sprintf (buffer, "LC::reset() track %i, scene %i", track,scene);
|
||||
EventGuiPrint e( buffer );
|
||||
writeToGuiRingbuffer( &e );
|
||||
|
||||
// set "progress" to zero as there's no clip anymore
|
||||
jack->getControllerUpdater()->setTrackSceneProgress(track, scene, 0 );
|
||||
} else {
|
||||
//SaveAble::done();
|
||||
}
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
/// loads a sample: eg from disk, unloading current sample if necessary
|
||||
void LooperClip::load( AudioBuffer* ab )
|
||||
{
|
||||
_loaded = true;
|
||||
_recording = false;
|
||||
_playing = false;
|
||||
|
||||
_queuePlay = false;
|
||||
_queueStop = false;
|
||||
_queueRecord= false;
|
||||
|
||||
if ( _buffer )
|
||||
{
|
||||
EventDeallocateBuffer e( _buffer );
|
||||
writeToGuiRingbuffer( &e );
|
||||
}
|
||||
|
||||
_buffer = ab;
|
||||
|
||||
_playhead = 0;
|
||||
jack->getControllerUpdater()->setTrackSceneProgress(track, scene, 0 );
|
||||
|
||||
// set the endpoint to the buffer's size
|
||||
_recordhead = _buffer->getData().size();
|
||||
|
||||
_loaded = true;
|
||||
_recording = false;
|
||||
_playing = false;
|
||||
|
||||
_queuePlay = false;
|
||||
_queueStop = false;
|
||||
_queueRecord= false;
|
||||
|
||||
if ( _buffer ) {
|
||||
EventDeallocateBuffer e( _buffer );
|
||||
writeToGuiRingbuffer( &e );
|
||||
}
|
||||
|
||||
_buffer = ab;
|
||||
|
||||
_playhead = 0;
|
||||
jack->getControllerUpdater()->setTrackSceneProgress(track, scene, 0 );
|
||||
|
||||
// set the endpoint to the buffer's size
|
||||
_recordhead = _buffer->getData().size();
|
||||
|
||||
#ifdef DEBUG_BUFFER
|
||||
char buffer [50];
|
||||
sprintf (buffer, "LC::load() t %i, s %i, aF %i",track, scene, int(_buffer->getAudioFrames()) );
|
||||
EventGuiPrint e( buffer );
|
||||
writeToGuiRingbuffer( &e );
|
||||
char buffer [50];
|
||||
sprintf (buffer, "LC::load() t %i, s %i, aF %i",track, scene, int(_buffer->getAudioFrames()) );
|
||||
EventGuiPrint e( buffer );
|
||||
writeToGuiRingbuffer( &e );
|
||||
#endif
|
||||
}
|
||||
|
||||
void LooperClip::setRequestedBuffer( AudioBuffer* ab )
|
||||
{
|
||||
if ( _buffer )
|
||||
{
|
||||
size_t size = _buffer->getData().size();
|
||||
memcpy( &ab->getData().at(0), &_buffer->getData().at(0), sizeof(float)*size);
|
||||
|
||||
ab->setID ( _buffer->getID() );
|
||||
ab->setBeats( _buffer->getBeats() );
|
||||
|
||||
EventDeallocateBuffer e( _buffer );
|
||||
writeToGuiRingbuffer( &e );
|
||||
}
|
||||
|
||||
_buffer = ab;
|
||||
|
||||
_newBufferInTransit = false;
|
||||
if ( _buffer ) {
|
||||
size_t size = _buffer->getData().size();
|
||||
memcpy( &ab->getData().at(0), &_buffer->getData().at(0), sizeof(float)*size);
|
||||
|
||||
ab->setID ( _buffer->getID() );
|
||||
ab->setBeats( _buffer->getBeats() );
|
||||
|
||||
EventDeallocateBuffer e( _buffer );
|
||||
writeToGuiRingbuffer( &e );
|
||||
}
|
||||
|
||||
_buffer = ab;
|
||||
|
||||
_newBufferInTransit = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void LooperClip::recieveSaveBuffer( AudioBuffer* saveBuffer )
|
||||
{
|
||||
if ( saveBuffer->getData().size() >= _buffer->getData().at(0) )
|
||||
{
|
||||
// copy current contents into save buffer,
|
||||
size_t framesBySize = _buffer->getAudioFrames();
|
||||
memcpy( &saveBuffer->getData().at(0), &_buffer->getData().at(0), sizeof(float)*framesBySize);
|
||||
|
||||
saveBuffer->setID ( _buffer->getID() );
|
||||
saveBuffer->setBeats( _buffer->getBeats() );
|
||||
saveBuffer->setAudioFrames( _buffer->getAudioFrames() );
|
||||
|
||||
EventStateSaveBuffer e ( track, scene, saveBuffer );
|
||||
writeToGuiRingbuffer( &e );
|
||||
|
||||
Stately::success();
|
||||
}
|
||||
else
|
||||
{
|
||||
char buffer [50];
|
||||
sprintf (buffer, "LC:: %i, %i: can't save, buf too small",track, scene );
|
||||
EventGuiPrint e( buffer );
|
||||
writeToGuiRingbuffer( &e );
|
||||
Stately::error("");
|
||||
}
|
||||
if ( saveBuffer->getData().size() >= _buffer->getData().at(0) ) {
|
||||
// copy current contents into save buffer,
|
||||
size_t framesBySize = _buffer->getAudioFrames();
|
||||
memcpy( &saveBuffer->getData().at(0), &_buffer->getData().at(0), sizeof(float)*framesBySize);
|
||||
|
||||
saveBuffer->setID ( _buffer->getID() );
|
||||
saveBuffer->setBeats( _buffer->getBeats() );
|
||||
saveBuffer->setAudioFrames( _buffer->getAudioFrames() );
|
||||
|
||||
EventStateSaveBuffer e ( track, scene, saveBuffer );
|
||||
writeToGuiRingbuffer( &e );
|
||||
|
||||
Stately::success();
|
||||
} else {
|
||||
char buffer [50];
|
||||
sprintf (buffer, "LC:: %i, %i: can't save, buf too small",track, scene );
|
||||
EventGuiPrint e( buffer );
|
||||
writeToGuiRingbuffer( &e );
|
||||
Stately::error("");
|
||||
}
|
||||
}
|
||||
|
||||
void LooperClip::setPlayHead(float ph)
|
||||
{
|
||||
if(!_recording&&_playing)
|
||||
{
|
||||
_playhead = ph;
|
||||
jack->getControllerUpdater()->setTrackSceneProgress(track, scene, getProgress() );
|
||||
}
|
||||
if(!_recording&&_playing) {
|
||||
_playhead = ph;
|
||||
jack->getControllerUpdater()->setTrackSceneProgress(track, scene, getProgress() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void LooperClip::record(int count, float* L, float* R)
|
||||
{
|
||||
// write "count" samples into current buffer.
|
||||
if ( _buffer )
|
||||
{
|
||||
size_t size = _buffer->getData().size();
|
||||
|
||||
for(int i = 0; i < count; i++)
|
||||
{
|
||||
if ( _recordhead < size )
|
||||
{
|
||||
_buffer->getData().at( _recordhead ) = *L++;
|
||||
_recordhead++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// break: this is *BAD*, audio data is lost but the buffer isn't here
|
||||
// yet to hold new audio data so there's no option. This has not been
|
||||
// encountered in actual usage, only during the development process.
|
||||
char buffer [50];
|
||||
sprintf (buffer, "LooperClip t %i, s %i, Error: out of mem!",track, scene );
|
||||
EventGuiPrint e( buffer );
|
||||
writeToGuiRingbuffer( &e );
|
||||
// write "count" samples into current buffer.
|
||||
if ( _buffer ) {
|
||||
size_t size = _buffer->getData().size();
|
||||
|
||||
for(int i = 0; i < count; i++) {
|
||||
if ( _recordhead < size ) {
|
||||
_buffer->getData().at( _recordhead ) = *L++;
|
||||
_recordhead++;
|
||||
} else {
|
||||
// break: this is *BAD*, audio data is lost but the buffer isn't here
|
||||
// yet to hold new audio data so there's no option. This has not been
|
||||
// encountered in actual usage, only during the development process.
|
||||
char buffer [50];
|
||||
sprintf (buffer, "LooperClip t %i, s %i, Error: out of mem!",track, scene );
|
||||
EventGuiPrint e( buffer );
|
||||
writeToGuiRingbuffer( &e );
|
||||
#ifdef BUILD_TESTS
|
||||
LUPPP_WARN("%s","buffer has no space");
|
||||
LUPPP_WARN("%s","buffer has no space");
|
||||
#endif
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_loaded = true;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_loaded = true;
|
||||
}
|
||||
|
||||
unsigned long LooperClip::recordSpaceAvailable()
|
||||
{
|
||||
if ( _buffer )
|
||||
return _buffer->getData().size() - _recordhead;
|
||||
|
||||
return 0;
|
||||
if ( _buffer )
|
||||
return _buffer->getData().size() - _recordhead;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t LooperClip::audioBufferSize()
|
||||
{
|
||||
if ( _buffer )
|
||||
{
|
||||
return _buffer->getData().size();
|
||||
}
|
||||
return 0;
|
||||
if ( _buffer ) {
|
||||
return _buffer->getData().size();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void LooperClip::setBeats(int beats)
|
||||
{
|
||||
if ( _buffer )
|
||||
{
|
||||
_buffer->setBeats( beats );
|
||||
}
|
||||
if ( _buffer ) {
|
||||
_buffer->setBeats( beats );
|
||||
}
|
||||
}
|
||||
|
||||
int LooperClip::getBeats()
|
||||
{
|
||||
if ( _buffer )
|
||||
return _buffer->getBeats();
|
||||
|
||||
return 0;
|
||||
if ( _buffer )
|
||||
return _buffer->getBeats();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
long LooperClip::getBufferLenght()
|
||||
{
|
||||
return _recordhead;
|
||||
return _recordhead;
|
||||
}
|
||||
|
||||
long LooperClip::getActualAudioLength()
|
||||
{
|
||||
char cbuffer [50];
|
||||
char cbuffer [50];
|
||||
// sprintf (cbuffer, "LooperClip recordhead %f,audioFrames %d \n",_recordhead,(int)_buffer->getAudioFrames());
|
||||
// EventGuiPrint e( cbuffer );
|
||||
// writeToGuiRingbuffer( &e );
|
||||
// printf(cbuffer);
|
||||
return _buffer->getAudioFrames();
|
||||
return _buffer->getAudioFrames();
|
||||
}
|
||||
|
||||
void LooperClip::bar()
|
||||
{
|
||||
bool change = false;
|
||||
GridLogic::State s = GridLogic::STATE_EMPTY;
|
||||
|
||||
// first update the buffer, as time has passed
|
||||
if ( _recording )
|
||||
{
|
||||
// FIXME: assumes 4 beats in a bar
|
||||
_buffer->setBeats( _buffer->getBeats() + 4 );
|
||||
_buffer->setAudioFrames( jack->getTimeManager()->getFpb() * _buffer->getBeats() );
|
||||
}
|
||||
|
||||
if ( _playhead >= _recordhead )
|
||||
{
|
||||
_playhead = 0.f;
|
||||
}
|
||||
|
||||
if ( _queuePlay && _loaded )
|
||||
{
|
||||
//LUPPP_NOTE("QPLay + loaded" );
|
||||
_playing = true;
|
||||
s = GridLogic::STATE_PLAYING;
|
||||
_recording = false;
|
||||
_queuePlay = false;
|
||||
change = true;
|
||||
|
||||
_playhead = 0;
|
||||
}
|
||||
else if ( _queueStop && _loaded )
|
||||
{
|
||||
_playing = false;
|
||||
s = GridLogic::STATE_STOPPED;
|
||||
_recording = false;
|
||||
_queueStop = false;
|
||||
change = true;
|
||||
// set "progress" to zero, as we're stopped!
|
||||
jack->getControllerUpdater()->setTrackSceneProgress(track, scene, 0 );
|
||||
}
|
||||
else if ( _queueRecord )
|
||||
{
|
||||
_recording = true;
|
||||
s = GridLogic::STATE_RECORDING;
|
||||
_playing = false;
|
||||
_queueRecord = false;
|
||||
change = true;
|
||||
|
||||
if ( _buffer )
|
||||
{
|
||||
_buffer->setBeats( 0 );
|
||||
}
|
||||
|
||||
_recordhead = 0;
|
||||
}
|
||||
else if ( _queuePlay )
|
||||
{
|
||||
// clip was queued, but there's nothing loaded
|
||||
_queuePlay = false;
|
||||
change = true;
|
||||
}
|
||||
|
||||
if ( change )
|
||||
{
|
||||
jack->getControllerUpdater()->setSceneState(track, scene, s );
|
||||
}
|
||||
bool change = false;
|
||||
GridLogic::State s = GridLogic::STATE_EMPTY;
|
||||
|
||||
// first update the buffer, as time has passed
|
||||
if ( _recording ) {
|
||||
// FIXME: assumes 4 beats in a bar
|
||||
_buffer->setBeats( _buffer->getBeats() + 4 );
|
||||
_buffer->setAudioFrames( jack->getTimeManager()->getFpb() * _buffer->getBeats() );
|
||||
}
|
||||
|
||||
if ( _playhead >= _recordhead ) {
|
||||
_playhead = 0.f;
|
||||
}
|
||||
|
||||
if ( _queuePlay && _loaded ) {
|
||||
//LUPPP_NOTE("QPLay + loaded" );
|
||||
_playing = true;
|
||||
s = GridLogic::STATE_PLAYING;
|
||||
_recording = false;
|
||||
_queuePlay = false;
|
||||
change = true;
|
||||
|
||||
_playhead = 0;
|
||||
} else if ( _queueStop && _loaded ) {
|
||||
_playing = false;
|
||||
s = GridLogic::STATE_STOPPED;
|
||||
_recording = false;
|
||||
_queueStop = false;
|
||||
change = true;
|
||||
// set "progress" to zero, as we're stopped!
|
||||
jack->getControllerUpdater()->setTrackSceneProgress(track, scene, 0 );
|
||||
} else if ( _queueRecord ) {
|
||||
_recording = true;
|
||||
s = GridLogic::STATE_RECORDING;
|
||||
_playing = false;
|
||||
_queueRecord = false;
|
||||
change = true;
|
||||
|
||||
if ( _buffer ) {
|
||||
_buffer->setBeats( 0 );
|
||||
}
|
||||
|
||||
_recordhead = 0;
|
||||
} else if ( _queuePlay ) {
|
||||
// clip was queued, but there's nothing loaded
|
||||
_queuePlay = false;
|
||||
change = true;
|
||||
}
|
||||
|
||||
if ( change ) {
|
||||
jack->getControllerUpdater()->setSceneState(track, scene, s );
|
||||
}
|
||||
}
|
||||
|
||||
void LooperClip::neutralize()
|
||||
{
|
||||
_queuePlay = false;
|
||||
_queueRecord = false;
|
||||
_queueStop = false;
|
||||
_queuePlay = false;
|
||||
_queueRecord = false;
|
||||
_queueStop = false;
|
||||
}
|
||||
|
||||
bool LooperClip::somethingQueued()
|
||||
{
|
||||
if ( _queuePlay || _queueStop || _queueRecord )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
if ( _queuePlay || _queueStop || _queueRecord ) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void LooperClip::queuePlay(bool qP)
|
||||
{
|
||||
_queuePlay = true;
|
||||
_queueStop = false;
|
||||
_queueRecord = false;
|
||||
_queuePlay = true;
|
||||
_queueStop = false;
|
||||
_queueRecord = false;
|
||||
}
|
||||
|
||||
void LooperClip::queueStop()
|
||||
{
|
||||
// comment
|
||||
if ( _loaded )
|
||||
{
|
||||
_queueStop = true;
|
||||
_queuePlay = false;
|
||||
}
|
||||
// comment
|
||||
if ( _loaded ) {
|
||||
_queueStop = true;
|
||||
_queuePlay = false;
|
||||
}
|
||||
}
|
||||
|
||||
void LooperClip::queueRecord()
|
||||
{
|
||||
_queueRecord = true;
|
||||
_queuePlay = false;
|
||||
_queueStop = false;
|
||||
_queueRecord = true;
|
||||
_queuePlay = false;
|
||||
_queueStop = false;
|
||||
}
|
||||
|
||||
GridLogic::State LooperClip::getState()
|
||||
{
|
||||
GridLogic::State s = GridLogic::STATE_EMPTY;
|
||||
|
||||
if ( _loaded )
|
||||
s = GridLogic::STATE_STOPPED;
|
||||
if ( _playing )
|
||||
s = GridLogic::STATE_PLAYING;
|
||||
if ( _recording )
|
||||
s = GridLogic::STATE_RECORDING;
|
||||
if ( _queuePlay )
|
||||
s = GridLogic::STATE_PLAY_QUEUED;
|
||||
if ( _queueStop )
|
||||
s = GridLogic::STATE_STOP_QUEUED;
|
||||
if ( _queueRecord )
|
||||
s = GridLogic::STATE_RECORD_QUEUED;
|
||||
|
||||
return s;
|
||||
GridLogic::State s = GridLogic::STATE_EMPTY;
|
||||
|
||||
if ( _loaded )
|
||||
s = GridLogic::STATE_STOPPED;
|
||||
if ( _playing )
|
||||
s = GridLogic::STATE_PLAYING;
|
||||
if ( _recording )
|
||||
s = GridLogic::STATE_RECORDING;
|
||||
if ( _queuePlay )
|
||||
s = GridLogic::STATE_PLAY_QUEUED;
|
||||
if ( _queueStop )
|
||||
s = GridLogic::STATE_STOP_QUEUED;
|
||||
if ( _queueRecord )
|
||||
s = GridLogic::STATE_RECORD_QUEUED;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
bool LooperClip::playing()
|
||||
{
|
||||
return _playing;
|
||||
return _playing;
|
||||
}
|
||||
|
||||
bool LooperClip::getQueueStop()
|
||||
{
|
||||
return _queueStop;
|
||||
return _queueStop;
|
||||
}
|
||||
|
||||
bool LooperClip::getQueuePlay()
|
||||
{
|
||||
return _queuePlay;
|
||||
return _queuePlay;
|
||||
}
|
||||
|
||||
bool LooperClip::getLoaded()
|
||||
{
|
||||
return _loaded;
|
||||
return _loaded;
|
||||
}
|
||||
|
||||
bool LooperClip::recording()
|
||||
{
|
||||
return _recording;
|
||||
return _recording;
|
||||
}
|
||||
|
||||
void LooperClip::newBufferInTransit(bool n)
|
||||
{
|
||||
_newBufferInTransit = n;
|
||||
_newBufferInTransit = n;
|
||||
}
|
||||
|
||||
bool LooperClip::newBufferInTransit()
|
||||
{
|
||||
return _newBufferInTransit;
|
||||
return _newBufferInTransit;
|
||||
}
|
||||
|
||||
float LooperClip::getSample(float playSpeed)
|
||||
{
|
||||
if ( _buffer && _buffer->getData().size() > 0 )
|
||||
{
|
||||
if ( _playhead >= _recordhead ||
|
||||
_playhead >= _buffer->getData().size() ||
|
||||
_playhead < 0 )
|
||||
{
|
||||
_playhead = 0;
|
||||
|
||||
EventGuiPrint e( "LooperClip resetting _playhead" );
|
||||
//writeToGuiRingbuffer( &e );
|
||||
}
|
||||
|
||||
std::vector<float>& v = _buffer->getData();
|
||||
float tmp = v.at(_playhead);
|
||||
_playhead +=playSpeed;
|
||||
if ( _buffer && _buffer->getData().size() > 0 ) {
|
||||
if ( _playhead >= _recordhead ||
|
||||
_playhead >= _buffer->getData().size() ||
|
||||
_playhead < 0 ) {
|
||||
_playhead = 0;
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
return 0.f;
|
||||
EventGuiPrint e( "LooperClip resetting _playhead" );
|
||||
//writeToGuiRingbuffer( &e );
|
||||
}
|
||||
|
||||
std::vector<float>& v = _buffer->getData();
|
||||
float tmp = v.at(_playhead);
|
||||
_playhead +=playSpeed;
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
return 0.f;
|
||||
}
|
||||
|
||||
float LooperClip::getProgress()
|
||||
{
|
||||
if ( _buffer && _playing )
|
||||
{
|
||||
float p = float(_playhead) / _recordhead;
|
||||
//printf("LooperClip progress %f\n", p );
|
||||
return p;
|
||||
}
|
||||
return 0.f;
|
||||
if ( _buffer && _playing ) {
|
||||
float p = float(_playhead) / _recordhead;
|
||||
//printf("LooperClip progress %f\n", p );
|
||||
return p;
|
||||
}
|
||||
return 0.f;
|
||||
}
|
||||
|
||||
float LooperClip::getPlayhead()
|
||||
{
|
||||
return _playhead;
|
||||
return _playhead;
|
||||
}
|
||||
|
||||
#ifdef BUILD_TESTS
|
||||
void LooperClip::setState( bool load, bool play, bool rec, bool qPlay, bool qStop, bool qRec )
|
||||
{
|
||||
_loaded = load;
|
||||
_playing = play;
|
||||
_recording = rec;
|
||||
|
||||
_queuePlay = qPlay;
|
||||
_queueStop = qStop;
|
||||
_queueRecord = qRec;
|
||||
_loaded = load;
|
||||
_playing = play;
|
||||
_recording = rec;
|
||||
|
||||
_queuePlay = qPlay;
|
||||
_queueStop = qStop;
|
||||
_queueRecord = qRec;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -34,110 +34,113 @@ class AudioBuffer;
|
|||
* The transition between AudioBuffer instances is seamless: when the clip is
|
||||
* running out, the new one is requested. Upon its arrival the current data is
|
||||
* copied, and the old buffer is returned for deallocation.
|
||||
*
|
||||
*
|
||||
* This system allows for arbitrary length recordings, without huge
|
||||
* pre-allocated buffers while it is still quite simple.
|
||||
*
|
||||
*
|
||||
* Each clip has its properties like length and bars/beats, so the Looper knows
|
||||
* to dynamically stretch / process the audio appropriately. Controllers and the
|
||||
* UI are updated from this data.
|
||||
*
|
||||
*
|
||||
* This class inherits from SaveAble to save its state.
|
||||
**/
|
||||
class LooperClip : public Stately
|
||||
{
|
||||
public:
|
||||
LooperClip(int track, int scene);
|
||||
|
||||
void init();
|
||||
|
||||
/// loads a sample: eg from disk, unloading current sample if necessary
|
||||
void load( AudioBuffer* ab );
|
||||
|
||||
/// audio functionality
|
||||
float getSample(float playSpeed);
|
||||
void record(int count, float* L, float* R);
|
||||
|
||||
/// TimeObserver override
|
||||
void bar();
|
||||
|
||||
/// SaveAble overrides
|
||||
void save();
|
||||
void reset();
|
||||
|
||||
/// analyses current _playing _recording vars, returns the current State
|
||||
GridLogic::State getState();
|
||||
bool playing();
|
||||
bool getLoaded();
|
||||
bool getQueueStop();
|
||||
bool getQueuePlay();
|
||||
bool recording();
|
||||
|
||||
/// get buffer details
|
||||
int getBeats();
|
||||
float getProgress();
|
||||
float getPlayhead();
|
||||
//Return the length of the complete buffer
|
||||
long getBufferLenght();
|
||||
//Return the nr of samples holding actual audio. This is less then getBufferLength();
|
||||
long getActualAudioLength();
|
||||
size_t audioBufferSize();
|
||||
public:
|
||||
LooperClip(int track, int scene);
|
||||
|
||||
AudioBuffer* getAudioBuffer() {return _buffer;}
|
||||
|
||||
/// set clip state
|
||||
void queuePlay(bool=true);
|
||||
void queueStop();
|
||||
void queueRecord();
|
||||
|
||||
void neutralize(); // removes all play || record states if on
|
||||
bool somethingQueued(); // returns true if any state is queued
|
||||
|
||||
/// set buffer state
|
||||
void setBeats(int beats);
|
||||
|
||||
/// Luppp internal buffer resizing
|
||||
void newBufferInTransit(bool n);
|
||||
bool newBufferInTransit();
|
||||
unsigned long recordSpaceAvailable();
|
||||
|
||||
/** used to update the size of the buffer for this looperclip. The current
|
||||
* data is copied into the new buffer, then the smaller buffer is sent
|
||||
* for de-allocation.
|
||||
**/
|
||||
void setRequestedBuffer( AudioBuffer* ab );
|
||||
|
||||
/// used for saving the contents of this buffer to disk
|
||||
void recieveSaveBuffer( AudioBuffer* ab );
|
||||
void init();
|
||||
|
||||
/// loads a sample: eg from disk, unloading current sample if necessary
|
||||
void load( AudioBuffer* ab );
|
||||
|
||||
/// audio functionality
|
||||
float getSample(float playSpeed);
|
||||
void record(int count, float* L, float* R);
|
||||
|
||||
/// TimeObserver override
|
||||
void bar();
|
||||
|
||||
/// SaveAble overrides
|
||||
void save();
|
||||
void reset();
|
||||
|
||||
/// analyses current _playing _recording vars, returns the current State
|
||||
GridLogic::State getState();
|
||||
bool playing();
|
||||
bool getLoaded();
|
||||
bool getQueueStop();
|
||||
bool getQueuePlay();
|
||||
bool recording();
|
||||
|
||||
/// get buffer details
|
||||
int getBeats();
|
||||
float getProgress();
|
||||
float getPlayhead();
|
||||
//Return the length of the complete buffer
|
||||
long getBufferLenght();
|
||||
//Return the nr of samples holding actual audio. This is less then getBufferLength();
|
||||
long getActualAudioLength();
|
||||
size_t audioBufferSize();
|
||||
|
||||
AudioBuffer* getAudioBuffer()
|
||||
{
|
||||
return _buffer;
|
||||
}
|
||||
|
||||
/// set clip state
|
||||
void queuePlay(bool=true);
|
||||
void queueStop();
|
||||
void queueRecord();
|
||||
|
||||
void neutralize(); // removes all play || record states if on
|
||||
bool somethingQueued(); // returns true if any state is queued
|
||||
|
||||
/// set buffer state
|
||||
void setBeats(int beats);
|
||||
|
||||
/// Luppp internal buffer resizing
|
||||
void newBufferInTransit(bool n);
|
||||
bool newBufferInTransit();
|
||||
unsigned long recordSpaceAvailable();
|
||||
|
||||
/** used to update the size of the buffer for this looperclip. The current
|
||||
* data is copied into the new buffer, then the smaller buffer is sent
|
||||
* for de-allocation.
|
||||
**/
|
||||
void setRequestedBuffer( AudioBuffer* ab );
|
||||
|
||||
/// used for saving the contents of this buffer to disk
|
||||
void recieveSaveBuffer( AudioBuffer* ab );
|
||||
|
||||
///reset the play head to zero. Does nothing when recording
|
||||
void setPlayHead(float ph);
|
||||
|
||||
///reset the play head to zero. Does nothing when recording
|
||||
void setPlayHead(float ph);
|
||||
|
||||
#ifdef BUILD_TESTS
|
||||
// used only in test cases
|
||||
void setState( bool load, bool play, bool rec, bool qPlay, bool qStop, bool qRec );
|
||||
// used only in test cases
|
||||
void setState( bool load, bool play, bool rec, bool qPlay, bool qStop, bool qRec );
|
||||
#endif
|
||||
|
||||
private:
|
||||
int track, scene;
|
||||
|
||||
/** Luppp needs more than the current state of the clip to accuratly handle
|
||||
* it. The current state of the grid is kept up-to-date by GridLogic
|
||||
* abstracting detail away, sending GridLogic::State to Controllers.
|
||||
**/
|
||||
bool _loaded;
|
||||
bool _playing;
|
||||
bool _recording;
|
||||
|
||||
bool _queuePlay;
|
||||
bool _queueStop;
|
||||
bool _queueRecord;
|
||||
|
||||
bool _newBufferInTransit;
|
||||
|
||||
float _playhead;
|
||||
float _recordhead;
|
||||
AudioBuffer* _buffer;
|
||||
|
||||
private:
|
||||
int track, scene;
|
||||
|
||||
/** Luppp needs more than the current state of the clip to accuratly handle
|
||||
* it. The current state of the grid is kept up-to-date by GridLogic
|
||||
* abstracting detail away, sending GridLogic::State to Controllers.
|
||||
**/
|
||||
bool _loaded;
|
||||
bool _playing;
|
||||
bool _recording;
|
||||
|
||||
bool _queuePlay;
|
||||
bool _queueStop;
|
||||
bool _queueRecord;
|
||||
|
||||
bool _newBufferInTransit;
|
||||
|
||||
float _playhead;
|
||||
float _recordhead;
|
||||
AudioBuffer* _buffer;
|
||||
};
|
||||
|
||||
#endif // LUPPP_LOOPER_CLIP_H
|
||||
|
|
163
src/main.cxx
163
src/main.cxx
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -45,99 +45,92 @@ Jack* jack = 0;
|
|||
|
||||
void signalHanlder(int signum)
|
||||
{
|
||||
signalHanlderInt = signum;
|
||||
signalHanlderInt = signum;
|
||||
}
|
||||
|
||||
static void gui_static_loadSession_cb(void* inst)
|
||||
{
|
||||
char* tmp = (char*) inst;
|
||||
int sess = gui->getDiskReader()->readSession( tmp );
|
||||
if ( sess != LUPPP_RETURN_OK )
|
||||
LUPPP_ERROR( "Error loading session" );
|
||||
char* tmp = (char*) inst;
|
||||
int sess = gui->getDiskReader()->readSession( tmp );
|
||||
if ( sess != LUPPP_RETURN_OK )
|
||||
LUPPP_ERROR( "Error loading session" );
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
LUPPP_NOTE("Git: %s", GIT_VERSION );
|
||||
|
||||
bool runTests = false;
|
||||
if ( runTests ){} // remove unused warning if not built with BUILD_TESTS
|
||||
|
||||
for(int i = 0; i < argc; i++)
|
||||
{
|
||||
if ( strcmp(argv[i], "-test" ) == 0 ) {
|
||||
runTests = true;
|
||||
}
|
||||
else if ( i != 0 ) // don't try load with the program name!
|
||||
{
|
||||
// assume filename, try load it
|
||||
Fl::repeat_timeout( 1 / 30.f, &gui_static_loadSession_cb, argv[i] );
|
||||
}
|
||||
}
|
||||
|
||||
// setup the environment
|
||||
AVOIDDENORMALS();
|
||||
signal(SIGINT , signalHanlder);
|
||||
signal(SIGTERM, signalHanlder);
|
||||
|
||||
// allocate data to read from
|
||||
processDspMem = (EventBase*)malloc( sizeof(EventBase) );
|
||||
processGuiMem = (EventBase*)malloc( sizeof(EventBase) );
|
||||
|
||||
rbToDsp = jack_ringbuffer_create( 5000 * sizeof(EventBase));
|
||||
rbToGui = jack_ringbuffer_create( 5000 * sizeof(EventBase));
|
||||
|
||||
|
||||
LUPPP_NOTE("Git: %s", GIT_VERSION );
|
||||
|
||||
bool runTests = false;
|
||||
if ( runTests ) {} // remove unused warning if not built with BUILD_TESTS
|
||||
|
||||
for(int i = 0; i < argc; i++) {
|
||||
if ( strcmp(argv[i], "-test" ) == 0 ) {
|
||||
runTests = true;
|
||||
} else if ( i != 0 ) { // don't try load with the program name!
|
||||
// assume filename, try load it
|
||||
Fl::repeat_timeout( 1 / 30.f, &gui_static_loadSession_cb, argv[i] );
|
||||
}
|
||||
}
|
||||
|
||||
// setup the environment
|
||||
AVOIDDENORMALS();
|
||||
signal(SIGINT , signalHanlder);
|
||||
signal(SIGTERM, signalHanlder);
|
||||
|
||||
// allocate data to read from
|
||||
processDspMem = (EventBase*)malloc( sizeof(EventBase) );
|
||||
processGuiMem = (EventBase*)malloc( sizeof(EventBase) );
|
||||
|
||||
rbToDsp = jack_ringbuffer_create( 5000 * sizeof(EventBase));
|
||||
rbToGui = jack_ringbuffer_create( 5000 * sizeof(EventBase));
|
||||
|
||||
|
||||
#ifdef BUILD_TESTS
|
||||
LUPPP_NOTE("Built with BUILD_TESTS enabled");
|
||||
if ( runTests )
|
||||
{
|
||||
// counts failures
|
||||
int testResult = 0;
|
||||
|
||||
// setup the testing Gui / JACK: Jack first, then GUI
|
||||
gui = new Gui( argv[0] );
|
||||
Jack::setup("LupppTEST");
|
||||
|
||||
// test offline functionality
|
||||
testResult += gui->getDiskReader()->runTests();
|
||||
testResult += gui->getDiskWriter()->runTests();
|
||||
|
||||
// test realtime functionality
|
||||
testResult += jack->getGridLogic()->runTests();
|
||||
|
||||
jack->quit();
|
||||
|
||||
delete gui;
|
||||
delete jack;
|
||||
jack = 0;
|
||||
|
||||
// running tests == quitting after testing finishes
|
||||
return testResult;
|
||||
}
|
||||
|
||||
LUPPP_NOTE("Built with BUILD_TESTS enabled");
|
||||
if ( runTests ) {
|
||||
// counts failures
|
||||
int testResult = 0;
|
||||
|
||||
// setup the testing Gui / JACK: Jack first, then GUI
|
||||
gui = new Gui( argv[0] );
|
||||
Jack::setup("LupppTEST");
|
||||
|
||||
// test offline functionality
|
||||
testResult += gui->getDiskReader()->runTests();
|
||||
testResult += gui->getDiskWriter()->runTests();
|
||||
|
||||
// test realtime functionality
|
||||
testResult += jack->getGridLogic()->runTests();
|
||||
|
||||
jack->quit();
|
||||
|
||||
delete gui;
|
||||
delete jack;
|
||||
jack = 0;
|
||||
|
||||
// running tests == quitting after testing finishes
|
||||
return testResult;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
// Create a GUI, check for NSM integration
|
||||
gui = new Gui( argv[0] );
|
||||
|
||||
if ( gui->getNsm() )
|
||||
{
|
||||
// the NSM OSC Open message will trigger Jack initialization: necessary
|
||||
// to use the right name to create the JACK client.
|
||||
}
|
||||
else
|
||||
{
|
||||
Jack::setup("Luppp");
|
||||
jack->activate();
|
||||
}
|
||||
|
||||
gui->show();
|
||||
|
||||
|
||||
return 0;
|
||||
|
||||
|
||||
// Create a GUI, check for NSM integration
|
||||
gui = new Gui( argv[0] );
|
||||
|
||||
if ( gui->getNsm() ) {
|
||||
// the NSM OSC Open message will trigger Jack initialization: necessary
|
||||
// to use the right name to create the JACK client.
|
||||
} else {
|
||||
Jack::setup("Luppp");
|
||||
jack->activate();
|
||||
}
|
||||
|
||||
gui->show();
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -30,91 +30,88 @@ extern Jack* jack;
|
|||
using namespace std;
|
||||
|
||||
Metronome::Metronome() :
|
||||
TimeObserver(),
|
||||
playBar (false),
|
||||
active (false),
|
||||
vol (1),
|
||||
playPoint (0)
|
||||
TimeObserver(),
|
||||
playBar (false),
|
||||
active (false),
|
||||
vol (1),
|
||||
playPoint (0)
|
||||
{
|
||||
//Create Beat/Bar samples
|
||||
beatSample=new float[jack->getSamplerate()];
|
||||
barSample=new float[jack->getSamplerate()];
|
||||
// create beat and bar samples
|
||||
endPoint = ( jack->getSamplerate()/10 );
|
||||
// samples per cycle of
|
||||
float scale = 2 * 3.1415 *880/jack->getSamplerate();
|
||||
|
||||
// And fill it up
|
||||
for(int i=0;i < jack->getSamplerate();i++){
|
||||
beatSample[i]= sin(i*scale);
|
||||
barSample [i]= sin(i*scale*2);
|
||||
}
|
||||
|
||||
// don't play after creation
|
||||
playPoint = endPoint + 1;
|
||||
//Create Beat/Bar samples
|
||||
beatSample=new float[jack->getSamplerate()];
|
||||
barSample=new float[jack->getSamplerate()];
|
||||
// create beat and bar samples
|
||||
endPoint = ( jack->getSamplerate()/10 );
|
||||
// samples per cycle of
|
||||
float scale = 2 * 3.1415 *880/jack->getSamplerate();
|
||||
|
||||
// And fill it up
|
||||
for(int i=0; i < jack->getSamplerate(); i++) {
|
||||
beatSample[i]= sin(i*scale);
|
||||
barSample [i]= sin(i*scale*2);
|
||||
}
|
||||
|
||||
// don't play after creation
|
||||
playPoint = endPoint + 1;
|
||||
}
|
||||
|
||||
Metronome::~Metronome()
|
||||
{
|
||||
if(beatSample)
|
||||
delete [] beatSample;
|
||||
if(barSample)
|
||||
delete [] barSample;
|
||||
if(beatSample)
|
||||
delete [] beatSample;
|
||||
if(barSample)
|
||||
delete [] barSample;
|
||||
}
|
||||
|
||||
void Metronome::setActive(bool a)
|
||||
{
|
||||
active = a;
|
||||
// don't play immidiatly
|
||||
playPoint = endPoint + 1;
|
||||
active = a;
|
||||
// don't play immidiatly
|
||||
playPoint = endPoint + 1;
|
||||
}
|
||||
|
||||
void Metronome::setVolume( float v )
|
||||
{
|
||||
vol = v;
|
||||
printf(" vol = %f \n", vol );
|
||||
vol = v;
|
||||
printf(" vol = %f \n", vol );
|
||||
}
|
||||
|
||||
void Metronome::bar()
|
||||
{
|
||||
playPoint = 0;
|
||||
playBar = true;
|
||||
playPoint = 0;
|
||||
playBar = true;
|
||||
}
|
||||
|
||||
void Metronome::beat()
|
||||
{
|
||||
playPoint = 0;
|
||||
playBar = false;
|
||||
playPoint = 0;
|
||||
playBar = false;
|
||||
}
|
||||
|
||||
void Metronome::setFpb(int f)
|
||||
{
|
||||
fpb = f;
|
||||
|
||||
// disable play until next beat
|
||||
playPoint = endPoint + 1;
|
||||
fpb = f;
|
||||
|
||||
// disable play until next beat
|
||||
playPoint = endPoint + 1;
|
||||
}
|
||||
|
||||
void Metronome::process(int nframes, Buffers* buffers)
|
||||
{
|
||||
if ( not active )
|
||||
return;
|
||||
|
||||
float* out = buffers->audio[Buffers::HEADPHONES_OUT];
|
||||
|
||||
float* sample = &beatSample[0];
|
||||
if( playBar )
|
||||
{
|
||||
sample = &barSample[0];
|
||||
}
|
||||
|
||||
for(int i = 0; i < nframes; i++)
|
||||
{
|
||||
if ( playPoint < endPoint )
|
||||
{
|
||||
out[i] += sample[playPoint] * vol;
|
||||
playPoint++;
|
||||
}
|
||||
}
|
||||
if ( not active )
|
||||
return;
|
||||
|
||||
float* out = buffers->audio[Buffers::HEADPHONES_OUT];
|
||||
|
||||
float* sample = &beatSample[0];
|
||||
if( playBar ) {
|
||||
sample = &barSample[0];
|
||||
}
|
||||
|
||||
for(int i = 0; i < nframes; i++) {
|
||||
if ( playPoint < endPoint ) {
|
||||
out[i] += sample[playPoint] * vol;
|
||||
playPoint++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -30,30 +30,30 @@ using namespace std;
|
|||
|
||||
class Metronome : public TimeObserver
|
||||
{
|
||||
public:
|
||||
Metronome();
|
||||
~Metronome();
|
||||
|
||||
void setActive(bool a);
|
||||
|
||||
void bar();
|
||||
void beat();
|
||||
void setFpb(int f);
|
||||
|
||||
void setVolume( float v );
|
||||
|
||||
void process(int nframes, Buffers* buffers);
|
||||
|
||||
private:
|
||||
int fpb;
|
||||
bool playBar;
|
||||
bool active;
|
||||
float vol;
|
||||
|
||||
int playPoint, endPoint;
|
||||
float* barSample;
|
||||
float* beatSample;
|
||||
|
||||
public:
|
||||
Metronome();
|
||||
~Metronome();
|
||||
|
||||
void setActive(bool a);
|
||||
|
||||
void bar();
|
||||
void beat();
|
||||
void setFpb(int f);
|
||||
|
||||
void setVolume( float v );
|
||||
|
||||
void process(int nframes, Buffers* buffers);
|
||||
|
||||
private:
|
||||
int fpb;
|
||||
bool playBar;
|
||||
bool active;
|
||||
float vol;
|
||||
|
||||
int playPoint, endPoint;
|
||||
float* barSample;
|
||||
float* beatSample;
|
||||
|
||||
};
|
||||
|
||||
#endif // LUPPP_METRONOME_H
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -25,109 +25,101 @@
|
|||
extern Jack* jack;
|
||||
|
||||
MidiIO::MidiIO() :
|
||||
portsRegistered(false),
|
||||
jackInputPort(0),
|
||||
jackOutputPort(0)
|
||||
portsRegistered(false),
|
||||
jackInputPort(0),
|
||||
jackOutputPort(0)
|
||||
{
|
||||
//LUPPP_NOTE("MidiIO %i",this);
|
||||
//LUPPP_NOTE("MidiIO %i",this);
|
||||
}
|
||||
|
||||
MidiIO::~MidiIO()
|
||||
{
|
||||
jack->unregisterMidiIO( this );
|
||||
|
||||
//LUPPP_NOTE("~MidiIO unregistring ports");
|
||||
jack_port_unregister( jack->getJackClientPointer(), jackInputPort );
|
||||
jack_port_unregister( jack->getJackClientPointer(), jackOutputPort );
|
||||
jack->unregisterMidiIO( this );
|
||||
|
||||
//LUPPP_NOTE("~MidiIO unregistring ports");
|
||||
jack_port_unregister( jack->getJackClientPointer(), jackInputPort );
|
||||
jack_port_unregister( jack->getJackClientPointer(), jackOutputPort );
|
||||
}
|
||||
|
||||
|
||||
void MidiIO::writeMidi( unsigned char* data )
|
||||
{
|
||||
void* portBuffer = jack_port_get_buffer( jackOutputPort, jack->getBuffersize() );
|
||||
|
||||
unsigned char* buffer = jack_midi_event_reserve( portBuffer, 0, 3);
|
||||
if( buffer == 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
//memcpy( buffer, data, sizeof(unsigned char)*3 );
|
||||
buffer[0] = data[0];
|
||||
buffer[1] = data[1];
|
||||
buffer[2] = data[2];
|
||||
}
|
||||
|
||||
void* portBuffer = jack_port_get_buffer( jackOutputPort, jack->getBuffersize() );
|
||||
|
||||
unsigned char* buffer = jack_midi_event_reserve( portBuffer, 0, 3);
|
||||
if( buffer == 0 ) {
|
||||
return;
|
||||
} else {
|
||||
//memcpy( buffer, data, sizeof(unsigned char)*3 );
|
||||
buffer[0] = data[0];
|
||||
buffer[1] = data[1];
|
||||
buffer[2] = data[2];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int MidiIO::registerMidiPorts(std::string name)
|
||||
{
|
||||
if( !jack )
|
||||
{
|
||||
LUPPP_ERROR("Attempted register of controller, JACK not instantiated yet!");
|
||||
return LUPPP_RETURN_ERROR;
|
||||
}
|
||||
|
||||
jack_client_t* c = jack->getJackClientPointer();
|
||||
|
||||
// register the JACK MIDI ports
|
||||
stringstream i;
|
||||
i << name << " in";
|
||||
jackInputPort = jack_port_register( c,
|
||||
i.str().c_str(),
|
||||
JACK_DEFAULT_MIDI_TYPE,
|
||||
JackPortIsInput,
|
||||
0 );
|
||||
stringstream o;
|
||||
o << name << " out";
|
||||
jackOutputPort = jack_port_register( c,
|
||||
o.str().c_str(),
|
||||
JACK_DEFAULT_MIDI_TYPE,
|
||||
JackPortIsOutput,
|
||||
0 );
|
||||
|
||||
if ( jackInputPort && jackOutputPort )
|
||||
{
|
||||
//LUPPP_NOTE("%i, %i", jackInputPort, jackOutputPort );
|
||||
portsRegistered = true;
|
||||
return LUPPP_RETURN_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
LUPPP_ERROR("Error registering JACK ports" );
|
||||
return LUPPP_RETURN_ERROR;
|
||||
}
|
||||
if( !jack ) {
|
||||
LUPPP_ERROR("Attempted register of controller, JACK not instantiated yet!");
|
||||
return LUPPP_RETURN_ERROR;
|
||||
}
|
||||
|
||||
jack_client_t* c = jack->getJackClientPointer();
|
||||
|
||||
// register the JACK MIDI ports
|
||||
stringstream i;
|
||||
i << name << " in";
|
||||
jackInputPort = jack_port_register( c,
|
||||
i.str().c_str(),
|
||||
JACK_DEFAULT_MIDI_TYPE,
|
||||
JackPortIsInput,
|
||||
0 );
|
||||
stringstream o;
|
||||
o << name << " out";
|
||||
jackOutputPort = jack_port_register( c,
|
||||
o.str().c_str(),
|
||||
JACK_DEFAULT_MIDI_TYPE,
|
||||
JackPortIsOutput,
|
||||
0 );
|
||||
|
||||
if ( jackInputPort && jackOutputPort ) {
|
||||
//LUPPP_NOTE("%i, %i", jackInputPort, jackOutputPort );
|
||||
portsRegistered = true;
|
||||
return LUPPP_RETURN_OK;
|
||||
} else {
|
||||
LUPPP_ERROR("Error registering JACK ports" );
|
||||
return LUPPP_RETURN_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MidiIO::initBuffers(int nframes)
|
||||
{
|
||||
if ( !portsRegistered )
|
||||
return;
|
||||
|
||||
// clear the output buffer
|
||||
void* outputBuffer= (void*) jack_port_get_buffer( jackOutputPort, nframes );
|
||||
jack_midi_clear_buffer( outputBuffer );
|
||||
if ( !portsRegistered )
|
||||
return;
|
||||
|
||||
// clear the output buffer
|
||||
void* outputBuffer= (void*) jack_port_get_buffer( jackOutputPort, nframes );
|
||||
jack_midi_clear_buffer( outputBuffer );
|
||||
}
|
||||
|
||||
void MidiIO::process(int nframes)
|
||||
{
|
||||
if ( !portsRegistered )
|
||||
return;
|
||||
|
||||
// get port buffers and setup
|
||||
void* inputBuffer = (void*) jack_port_get_buffer( jackInputPort, nframes );
|
||||
|
||||
jack_midi_event_t event;
|
||||
int index = 0;
|
||||
int event_count = (int) jack_midi_get_event_count( inputBuffer );
|
||||
while ( index < event_count )
|
||||
{
|
||||
jack_midi_event_get(&event, inputBuffer, index);
|
||||
midi( (unsigned char*) &event.buffer[0] );
|
||||
//printf( "MIDI %i %i %i\n", int(event.buffer[0]), int(event.buffer[1]), int(event.buffer[2]) );
|
||||
index++;
|
||||
}
|
||||
|
||||
if ( !portsRegistered )
|
||||
return;
|
||||
|
||||
// get port buffers and setup
|
||||
void* inputBuffer = (void*) jack_port_get_buffer( jackInputPort, nframes );
|
||||
|
||||
jack_midi_event_t event;
|
||||
int index = 0;
|
||||
int event_count = (int) jack_midi_get_event_count( inputBuffer );
|
||||
while ( index < event_count ) {
|
||||
jack_midi_event_get(&event, inputBuffer, index);
|
||||
midi( (unsigned char*) &event.buffer[0] );
|
||||
//printf( "MIDI %i %i %i\n", int(event.buffer[0]), int(event.buffer[1]), int(event.buffer[2]) );
|
||||
index++;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -32,32 +32,32 @@ extern Jack* jack;
|
|||
**/
|
||||
class MidiIO
|
||||
{
|
||||
public:
|
||||
MidiIO();
|
||||
virtual ~MidiIO();
|
||||
|
||||
/// name string to show in UI
|
||||
virtual std::string getName() = 0;
|
||||
|
||||
/// gets / clears MIDI buffers
|
||||
void initBuffers(int nframes);
|
||||
|
||||
/// gets called each process() in JACK
|
||||
void process(int nframes);
|
||||
|
||||
/// called by the subclass to create MIDI ports
|
||||
int registerMidiPorts(std::string name);
|
||||
|
||||
virtual void midi(unsigned char* /*data*/){};
|
||||
|
||||
void writeMidi( unsigned char* /*data*/ );
|
||||
|
||||
private:
|
||||
bool portsRegistered;
|
||||
// there are jack_port_t* registered ports
|
||||
jack_port_t* jackInputPort;
|
||||
jack_port_t* jackOutputPort;
|
||||
|
||||
public:
|
||||
MidiIO();
|
||||
virtual ~MidiIO();
|
||||
|
||||
/// name string to show in UI
|
||||
virtual std::string getName() = 0;
|
||||
|
||||
/// gets / clears MIDI buffers
|
||||
void initBuffers(int nframes);
|
||||
|
||||
/// gets called each process() in JACK
|
||||
void process(int nframes);
|
||||
|
||||
/// called by the subclass to create MIDI ports
|
||||
int registerMidiPorts(std::string name);
|
||||
|
||||
virtual void midi(unsigned char* /*data*/) {};
|
||||
|
||||
void writeMidi( unsigned char* /*data*/ );
|
||||
|
||||
private:
|
||||
bool portsRegistered;
|
||||
// there are jack_port_t* registered ports
|
||||
jack_port_t* jackInputPort;
|
||||
jack_port_t* jackOutputPort;
|
||||
|
||||
};
|
||||
|
||||
#endif // LUPPP_MIDI_IO_H
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -25,6 +25,6 @@ extern Jack* jack;
|
|||
|
||||
TimeObserver::TimeObserver()
|
||||
{
|
||||
jack->getTimeManager()->registerObserver( this );
|
||||
jack->getTimeManager()->registerObserver( this );
|
||||
}
|
||||
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -23,23 +23,23 @@
|
|||
|
||||
class TimeObserver
|
||||
{
|
||||
public:
|
||||
/// registers with TimeManager
|
||||
TimeObserver();
|
||||
virtual ~TimeObserver(){};
|
||||
|
||||
virtual void setFpb(int fpb){};
|
||||
|
||||
//Reset any internal set of this object regarding time. Don't reset/delete any buffers!!
|
||||
//This is not to be confused with Stately::reset()
|
||||
virtual void resetTimeState(){};
|
||||
|
||||
virtual void bar(){};
|
||||
|
||||
virtual void beat(){};
|
||||
|
||||
virtual void tapTempo(bool b){};
|
||||
|
||||
public:
|
||||
/// registers with TimeManager
|
||||
TimeObserver();
|
||||
virtual ~TimeObserver() {};
|
||||
|
||||
virtual void setFpb(int fpb) {};
|
||||
|
||||
//Reset any internal set of this object regarding time. Don't reset/delete any buffers!!
|
||||
//This is not to be confused with Stately::reset()
|
||||
virtual void resetTimeState() {};
|
||||
|
||||
virtual void bar() {};
|
||||
|
||||
virtual void beat() {};
|
||||
|
||||
virtual void tapTempo(bool b) {};
|
||||
|
||||
};
|
||||
|
||||
#endif // LUPPP_TIME_OBSERVER_H
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -34,38 +34,36 @@ State::State()
|
|||
|
||||
void State::registerStately(Stately* s)
|
||||
{
|
||||
statelys.push_back( s );
|
||||
statelys.push_back( s );
|
||||
}
|
||||
|
||||
void State::save()
|
||||
{
|
||||
for( unsigned int i = 0; i < statelys.size(); i++)
|
||||
{
|
||||
statelys.at(i)->save();
|
||||
}
|
||||
for( unsigned int i = 0; i < statelys.size(); i++) {
|
||||
statelys.at(i)->save();
|
||||
}
|
||||
}
|
||||
|
||||
void State::reset()
|
||||
{
|
||||
for( unsigned int i = 0; i < statelys.size(); i++)
|
||||
{
|
||||
statelys.at(i)->reset();
|
||||
}
|
||||
|
||||
jack->getGridLogic()->updateState();
|
||||
for( unsigned int i = 0; i < statelys.size(); i++) {
|
||||
statelys.at(i)->reset();
|
||||
}
|
||||
|
||||
jack->getGridLogic()->updateState();
|
||||
}
|
||||
|
||||
void State::finish()
|
||||
{
|
||||
// trigger the GUI to write the metadata to disk, as each component of the
|
||||
// engine is done saving
|
||||
|
||||
EventStateSaveFinish e;
|
||||
writeToGuiRingbuffer( &e );
|
||||
|
||||
// trigger the GUI to write the metadata to disk, as each component of the
|
||||
// engine is done saving
|
||||
|
||||
EventStateSaveFinish e;
|
||||
writeToGuiRingbuffer( &e );
|
||||
|
||||
}
|
||||
|
||||
int State::getNumStatelys()
|
||||
{
|
||||
return statelys.size();
|
||||
return statelys.size();
|
||||
}
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -29,24 +29,24 @@
|
|||
**/
|
||||
class State
|
||||
{
|
||||
public:
|
||||
State();
|
||||
|
||||
/// called to initiate a save on all Statelys
|
||||
void save();
|
||||
|
||||
/// called to initiate a reset on all Statelys
|
||||
void reset();
|
||||
|
||||
/// called when each part is finished, and we can flush the metadata to disk
|
||||
void finish();
|
||||
|
||||
void registerStately(Stately* s);
|
||||
|
||||
int getNumStatelys();
|
||||
|
||||
private:
|
||||
std::vector<Stately*> statelys;
|
||||
public:
|
||||
State();
|
||||
|
||||
/// called to initiate a save on all Statelys
|
||||
void save();
|
||||
|
||||
/// called to initiate a reset on all Statelys
|
||||
void reset();
|
||||
|
||||
/// called when each part is finished, and we can flush the metadata to disk
|
||||
void finish();
|
||||
|
||||
void registerStately(Stately* s);
|
||||
|
||||
int getNumStatelys();
|
||||
|
||||
private:
|
||||
std::vector<Stately*> statelys;
|
||||
};
|
||||
|
||||
#endif // LUPPP_STATE_H
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -29,7 +29,7 @@ int Stately::saveErrors = 0;
|
|||
|
||||
Stately::Stately()
|
||||
{
|
||||
jack->getState()->registerStately( this );
|
||||
jack->getState()->registerStately( this );
|
||||
}
|
||||
|
||||
|
||||
|
@ -43,34 +43,32 @@ void Stately::save()
|
|||
|
||||
void Stately::checkCompletedSave()
|
||||
{
|
||||
if ( (saveSuccess + saveErrors) >= jack->getState()->getNumStatelys() )
|
||||
{
|
||||
jack->getState()->finish();
|
||||
|
||||
if ( saveErrors )
|
||||
{
|
||||
// send message to UI to be printed, noting # of clips unsaved due to errors
|
||||
char buf[50];
|
||||
sprintf( buf, "Saved with %i clips !saved due to errors", saveErrors);
|
||||
EventGuiPrint e( buf );
|
||||
writeToGuiRingbuffer( &e );
|
||||
}
|
||||
|
||||
// reset in case of another save before quit
|
||||
saveErrors = 0;
|
||||
saveSuccess = 0;
|
||||
}
|
||||
if ( (saveSuccess + saveErrors) >= jack->getState()->getNumStatelys() ) {
|
||||
jack->getState()->finish();
|
||||
|
||||
if ( saveErrors ) {
|
||||
// send message to UI to be printed, noting # of clips unsaved due to errors
|
||||
char buf[50];
|
||||
sprintf( buf, "Saved with %i clips !saved due to errors", saveErrors);
|
||||
EventGuiPrint e( buf );
|
||||
writeToGuiRingbuffer( &e );
|
||||
}
|
||||
|
||||
// reset in case of another save before quit
|
||||
saveErrors = 0;
|
||||
saveSuccess = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Stately::success()
|
||||
{
|
||||
saveSuccess++;
|
||||
checkCompletedSave();
|
||||
saveSuccess++;
|
||||
checkCompletedSave();
|
||||
}
|
||||
|
||||
void Stately::error(const char* errorString)
|
||||
{
|
||||
// CRITICAL FIXME: add error handling code, noting an error occured, perhaps prompt user?
|
||||
saveErrors++;
|
||||
checkCompletedSave();
|
||||
// CRITICAL FIXME: add error handling code, noting an error occured, perhaps prompt user?
|
||||
saveErrors++;
|
||||
checkCompletedSave();
|
||||
}
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -21,40 +21,40 @@
|
|||
|
||||
/** Stately
|
||||
* This class is inherited from by all classes that have state.
|
||||
*
|
||||
*
|
||||
* save() should be overriden if the object needs to save its state
|
||||
* reset() should be overriden if the object can clear its state
|
||||
*
|
||||
*
|
||||
* The flexibility allows eg LooperClips to request buffers to tranfser audio
|
||||
* data into the GUI thread for disk serialization, and scales for future
|
||||
* data into the GUI thread for disk serialization, and scales for future
|
||||
* classes which also need to request memory in order to save in a RT safe way.
|
||||
**/
|
||||
class Stately
|
||||
{
|
||||
public:
|
||||
Stately();
|
||||
|
||||
/// this function being called resets the state of the instance to blank
|
||||
virtual void reset();
|
||||
|
||||
/// this function is called when the user initiates a save action
|
||||
virtual void save();
|
||||
|
||||
/// this function *must* be called by each sub-class when it is *finished*
|
||||
/// a successful save action. Once each Stately is done, the final save is OK-ed.
|
||||
static void success();
|
||||
|
||||
/// this function notes that a stately could *not* successfully save: buffer
|
||||
/// size mismatch in LooperClip for example.
|
||||
static void error(const char* errorString);
|
||||
|
||||
private:
|
||||
/// holds the amount of successful / error-full saves. Used by success()
|
||||
/// and error()
|
||||
static int saveSuccess;
|
||||
static int saveErrors;
|
||||
|
||||
static void checkCompletedSave();
|
||||
public:
|
||||
Stately();
|
||||
|
||||
/// this function being called resets the state of the instance to blank
|
||||
virtual void reset();
|
||||
|
||||
/// this function is called when the user initiates a save action
|
||||
virtual void save();
|
||||
|
||||
/// this function *must* be called by each sub-class when it is *finished*
|
||||
/// a successful save action. Once each Stately is done, the final save is OK-ed.
|
||||
static void success();
|
||||
|
||||
/// this function notes that a stately could *not* successfully save: buffer
|
||||
/// size mismatch in LooperClip for example.
|
||||
static void error(const char* errorString);
|
||||
|
||||
private:
|
||||
/// holds the amount of successful / error-full saves. Used by success()
|
||||
/// and error()
|
||||
static int saveSuccess;
|
||||
static int saveErrors;
|
||||
|
||||
static void checkCompletedSave();
|
||||
};
|
||||
|
||||
#endif // LUPPP_STATELY_H
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -32,21 +32,21 @@ extern bool testsPassed;
|
|||
|
||||
int DiskReader::runTests()
|
||||
{
|
||||
QUnit::UnitTest qunit( QUnit::normal );
|
||||
|
||||
// set the session path to /tmp for test writing
|
||||
|
||||
string path = "/tmp";
|
||||
string session = "testSession";
|
||||
|
||||
//AudioBuffer ab(440);
|
||||
//gui->getDiskWriter()->initialize(path, session);
|
||||
|
||||
QUNIT_IS_TRUE( gui->getDiskReader()->loadSample( 0, 0,"/tmp/lupppTestMaterial/beat.wav" ) == LUPPP_RETURN_OK );
|
||||
|
||||
QUNIT_IS_TRUE( gui->getDiskReader()->readSession("/tmp/lupppTestMaterial/lupppTest" ) == LUPPP_RETURN_OK );
|
||||
|
||||
return qunit.errors();
|
||||
QUnit::UnitTest qunit( QUnit::normal );
|
||||
|
||||
// set the session path to /tmp for test writing
|
||||
|
||||
string path = "/tmp";
|
||||
string session = "testSession";
|
||||
|
||||
//AudioBuffer ab(440);
|
||||
//gui->getDiskWriter()->initialize(path, session);
|
||||
|
||||
QUNIT_IS_TRUE( gui->getDiskReader()->loadSample( 0, 0,"/tmp/lupppTestMaterial/beat.wav" ) == LUPPP_RETURN_OK );
|
||||
|
||||
QUNIT_IS_TRUE( gui->getDiskReader()->readSession("/tmp/lupppTestMaterial/lupppTest" ) == LUPPP_RETURN_OK );
|
||||
|
||||
return qunit.errors();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -35,51 +35,51 @@ extern bool testsPassed;
|
|||
|
||||
int DiskWriter::runTests()
|
||||
{
|
||||
QUnit::UnitTest qunit( QUnit::normal );
|
||||
|
||||
// set the session path to /tmp for test writing
|
||||
|
||||
string path = "/tmp";
|
||||
string session = "testSession";
|
||||
|
||||
AudioBuffer ab(440);
|
||||
gui->getDiskWriter()->initialize(path, session);
|
||||
|
||||
QUNIT_IS_TRUE( gui->getDiskWriter()->writeAudioBuffer(0, 0, &ab) == LUPPP_RETURN_OK );
|
||||
QUNIT_IS_TRUE( gui->getDiskWriter()->writeSession() == LUPPP_RETURN_OK );
|
||||
|
||||
QUNIT_IS_TRUE( strcmp( gui->getDiskWriter()->getLastSavePath().c_str(), path.c_str() ) == 0 );
|
||||
QUNIT_IS_TRUE( strcmp( gui->getDiskWriter()->getLastSaveName().c_str(), session.c_str() ) == 0 );
|
||||
|
||||
/** write controller test:
|
||||
* This test ensures that when writing a GenericMIDI* controller to disk the
|
||||
* data is correct. A dummy controller instance is setup, and then written to
|
||||
* disk.
|
||||
**/
|
||||
int waste = 0;
|
||||
GenericMIDI* dummy = new GenericMIDI( waste, "dummy" );
|
||||
std::string name = "dummy name";
|
||||
std::string author = "dummy author";
|
||||
std::string link = "www.dummylink.com";
|
||||
|
||||
int d = gui->getDiskWriter()->writeControllerFile( dummy );
|
||||
QUNIT_IS_TRUE( d == LUPPP_RETURN_OK );
|
||||
|
||||
dummy->setupBinding( Event::TRACK_VOLUME, 176, 7, 0, 0, 0, 0 );
|
||||
dummy->setupBinding( Event::GRID_LAUNCH_SCENE, 144, 60, 0, 2, 0, 0 );
|
||||
|
||||
int d1 = gui->getDiskWriter()->writeControllerFile( dummy );
|
||||
QUNIT_IS_TRUE( d1 == LUPPP_RETURN_OK );
|
||||
|
||||
/// test dynamic cast, null, and invalid Controller* type
|
||||
int r1 = gui->getDiskWriter()->writeControllerFile( 0 );
|
||||
QUNIT_IS_TRUE( r1 == LUPPP_RETURN_ERROR );
|
||||
|
||||
Controller* non = new NonSeq();
|
||||
int r2 = gui->getDiskWriter()->writeControllerFile( non);
|
||||
QUNIT_IS_TRUE( r2 == LUPPP_RETURN_ERROR );
|
||||
|
||||
return qunit.errors();
|
||||
QUnit::UnitTest qunit( QUnit::normal );
|
||||
|
||||
// set the session path to /tmp for test writing
|
||||
|
||||
string path = "/tmp";
|
||||
string session = "testSession";
|
||||
|
||||
AudioBuffer ab(440);
|
||||
gui->getDiskWriter()->initialize(path, session);
|
||||
|
||||
QUNIT_IS_TRUE( gui->getDiskWriter()->writeAudioBuffer(0, 0, &ab) == LUPPP_RETURN_OK );
|
||||
QUNIT_IS_TRUE( gui->getDiskWriter()->writeSession() == LUPPP_RETURN_OK );
|
||||
|
||||
QUNIT_IS_TRUE( strcmp( gui->getDiskWriter()->getLastSavePath().c_str(), path.c_str() ) == 0 );
|
||||
QUNIT_IS_TRUE( strcmp( gui->getDiskWriter()->getLastSaveName().c_str(), session.c_str() ) == 0 );
|
||||
|
||||
/** write controller test:
|
||||
* This test ensures that when writing a GenericMIDI* controller to disk the
|
||||
* data is correct. A dummy controller instance is setup, and then written to
|
||||
* disk.
|
||||
**/
|
||||
int waste = 0;
|
||||
GenericMIDI* dummy = new GenericMIDI( waste, "dummy" );
|
||||
std::string name = "dummy name";
|
||||
std::string author = "dummy author";
|
||||
std::string link = "www.dummylink.com";
|
||||
|
||||
int d = gui->getDiskWriter()->writeControllerFile( dummy );
|
||||
QUNIT_IS_TRUE( d == LUPPP_RETURN_OK );
|
||||
|
||||
dummy->setupBinding( Event::TRACK_VOLUME, 176, 7, 0, 0, 0, 0 );
|
||||
dummy->setupBinding( Event::GRID_LAUNCH_SCENE, 144, 60, 0, 2, 0, 0 );
|
||||
|
||||
int d1 = gui->getDiskWriter()->writeControllerFile( dummy );
|
||||
QUNIT_IS_TRUE( d1 == LUPPP_RETURN_OK );
|
||||
|
||||
/// test dynamic cast, null, and invalid Controller* type
|
||||
int r1 = gui->getDiskWriter()->writeControllerFile( 0 );
|
||||
QUNIT_IS_TRUE( r1 == LUPPP_RETURN_ERROR );
|
||||
|
||||
Controller* non = new NonSeq();
|
||||
int r2 = gui->getDiskWriter()->writeControllerFile( non);
|
||||
QUNIT_IS_TRUE( r2 == LUPPP_RETURN_ERROR );
|
||||
|
||||
return qunit.errors();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -26,14 +26,14 @@
|
|||
|
||||
int OptionsWindow::runTests()
|
||||
{
|
||||
QUnit::UnitTest qunit( QUnit::normal, true );
|
||||
|
||||
OptionsWindow opts;
|
||||
//opts.show();
|
||||
//Fl::run();
|
||||
|
||||
//QUNIT_IS_TRUE( jack->getGridLogic()->getLaunchedScene() == s );
|
||||
return 0;
|
||||
QUnit::UnitTest qunit( QUnit::normal, true );
|
||||
|
||||
OptionsWindow opts;
|
||||
//opts.show();
|
||||
//Fl::run();
|
||||
|
||||
//QUNIT_IS_TRUE( jack->getGridLogic()->getLaunchedScene() == s );
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // BUILD_TESTS
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -32,124 +32,124 @@ extern Jack* jack;
|
|||
|
||||
int GridLogic::runTests()
|
||||
{
|
||||
QUnit::UnitTest qunit( QUnit::normal, true );
|
||||
int t = 0;
|
||||
int s = 0;
|
||||
LooperClip* lc = jack->getLooper( t )->getClip( s );
|
||||
|
||||
// "pretty" prints the state of the clip
|
||||
//LUPPP_NOTE("%s", GridLogic::StateString[ lc->getState() ] );
|
||||
|
||||
/// SCENE LAUNCH
|
||||
lc->init();
|
||||
jack->getGridLogic()->launchScene( s );
|
||||
QUNIT_IS_TRUE( jack->getGridLogic()->getLaunchedScene() == s );
|
||||
|
||||
/// QUEUE s1, then launch s2, s1
|
||||
int launchScene = s + 1;
|
||||
lc->init();
|
||||
lc->setState( true, false, false, true, false, false ); // loaded + qplay
|
||||
LUPPP_NOTE("state before = %s", GridLogic::StateString[ lc->getState() ] );
|
||||
jack->getGridLogic()->launchScene( launchScene ); // launch different clip
|
||||
|
||||
QUNIT_IS_TRUE( jack->getGridLogic()->getLaunchedScene() == launchScene );
|
||||
LUPPP_NOTE("state after launch before bar = %s", GridLogic::StateString[ lc->getState() ] );
|
||||
QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_STOPPED );
|
||||
|
||||
jack->getGridLogic()->bar();
|
||||
|
||||
LUPPP_NOTE("state after bar = %s", GridLogic::StateString[ lc->getState() ] );
|
||||
QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_STOPPED );
|
||||
|
||||
/// s1 playing, then launch s2, s1
|
||||
lc->init();
|
||||
lc->setState( true, true, false, false, false, false ); // playing
|
||||
//LUPPP_NOTE("state before = %s", GridLogic::StateString[ lc->getState() ] );
|
||||
jack->getGridLogic()->launchScene( launchScene ); // launch different clip
|
||||
QUNIT_IS_TRUE( jack->getGridLogic()->getLaunchedScene() == launchScene );
|
||||
//LUPPP_NOTE("state after before bar = %s", GridLogic::StateString[ lc->getState() ] );
|
||||
QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_STOP_QUEUED );
|
||||
jack->getGridLogic()->bar();
|
||||
//LUPPP_NOTE("state after bar = %s", GridLogic::StateString[ lc->getState() ] );
|
||||
QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_STOPPED );
|
||||
|
||||
|
||||
/// PRESS PAD
|
||||
// empty -> recording
|
||||
lc->init();
|
||||
QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_EMPTY );
|
||||
jack->getGridLogic()->pressed( t, s );
|
||||
jack->getGridLogic()->released( t, s );
|
||||
QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_RECORD_QUEUED );
|
||||
jack->getGridLogic()->bar();
|
||||
QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_RECORDING );
|
||||
|
||||
float buffer[64];
|
||||
lc->record(64, &buffer[0], &buffer[0]);
|
||||
|
||||
// recording -> playing
|
||||
jack->getGridLogic()->pressed( t, s );
|
||||
jack->getGridLogic()->released( t, s );
|
||||
QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_PLAY_QUEUED );
|
||||
jack->getGridLogic()->bar();
|
||||
QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_PLAYING );
|
||||
// playing -> stopped
|
||||
jack->getGridLogic()->pressed( t, s );
|
||||
jack->getGridLogic()->released( t, s );
|
||||
QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_STOP_QUEUED );
|
||||
jack->getGridLogic()->bar();
|
||||
QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_STOPPED );
|
||||
// stopped -> playing
|
||||
jack->getGridLogic()->pressed( t, s );
|
||||
jack->getGridLogic()->released( t, s );
|
||||
QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_PLAY_QUEUED );
|
||||
jack->getGridLogic()->bar();
|
||||
QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_PLAYING );
|
||||
|
||||
|
||||
/// DOUBLE PRESS PAD
|
||||
// empty -> recordQ -> empty
|
||||
lc->init();
|
||||
QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_EMPTY );
|
||||
jack->getGridLogic()->pressed( t, s );
|
||||
jack->getGridLogic()->released( t, s );
|
||||
QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_RECORD_QUEUED );
|
||||
jack->getGridLogic()->pressed( t, s );
|
||||
jack->getGridLogic()->released( t, s );
|
||||
QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_EMPTY );
|
||||
lc->bar();
|
||||
|
||||
// recording -> playing -> stopped
|
||||
lc->setState( true, false, true, false, false, false );
|
||||
QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_RECORDING );
|
||||
jack->getGridLogic()->pressed( t, s );
|
||||
jack->getGridLogic()->released( t, s );
|
||||
QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_PLAY_QUEUED );
|
||||
jack->getGridLogic()->pressed( t, s );
|
||||
jack->getGridLogic()->released( t, s );
|
||||
QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_STOP_QUEUED );
|
||||
lc->bar();
|
||||
|
||||
// stopped -> playing -> stopped
|
||||
lc->setState( true, false, false, false, false, false );
|
||||
QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_STOPPED );
|
||||
jack->getGridLogic()->pressed( t, s );
|
||||
jack->getGridLogic()->released( t, s );
|
||||
QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_PLAY_QUEUED );
|
||||
jack->getGridLogic()->pressed( t, s );
|
||||
jack->getGridLogic()->released( t, s );
|
||||
QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_STOP_QUEUED );
|
||||
|
||||
// stopped -> playing
|
||||
lc->setState( true, true, false, false, false, false );
|
||||
QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_PLAYING );
|
||||
jack->getGridLogic()->pressed( t, s );
|
||||
jack->getGridLogic()->released( t, s );
|
||||
QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_STOP_QUEUED );
|
||||
jack->getGridLogic()->pressed( t, s );
|
||||
jack->getGridLogic()->released( t, s );
|
||||
QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_PLAYING );
|
||||
return qunit.errors();
|
||||
QUnit::UnitTest qunit( QUnit::normal, true );
|
||||
int t = 0;
|
||||
int s = 0;
|
||||
LooperClip* lc = jack->getLooper( t )->getClip( s );
|
||||
|
||||
// "pretty" prints the state of the clip
|
||||
//LUPPP_NOTE("%s", GridLogic::StateString[ lc->getState() ] );
|
||||
|
||||
/// SCENE LAUNCH
|
||||
lc->init();
|
||||
jack->getGridLogic()->launchScene( s );
|
||||
QUNIT_IS_TRUE( jack->getGridLogic()->getLaunchedScene() == s );
|
||||
|
||||
/// QUEUE s1, then launch s2, s1
|
||||
int launchScene = s + 1;
|
||||
lc->init();
|
||||
lc->setState( true, false, false, true, false, false ); // loaded + qplay
|
||||
LUPPP_NOTE("state before = %s", GridLogic::StateString[ lc->getState() ] );
|
||||
jack->getGridLogic()->launchScene( launchScene ); // launch different clip
|
||||
|
||||
QUNIT_IS_TRUE( jack->getGridLogic()->getLaunchedScene() == launchScene );
|
||||
LUPPP_NOTE("state after launch before bar = %s", GridLogic::StateString[ lc->getState() ] );
|
||||
QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_STOPPED );
|
||||
|
||||
jack->getGridLogic()->bar();
|
||||
|
||||
LUPPP_NOTE("state after bar = %s", GridLogic::StateString[ lc->getState() ] );
|
||||
QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_STOPPED );
|
||||
|
||||
/// s1 playing, then launch s2, s1
|
||||
lc->init();
|
||||
lc->setState( true, true, false, false, false, false ); // playing
|
||||
//LUPPP_NOTE("state before = %s", GridLogic::StateString[ lc->getState() ] );
|
||||
jack->getGridLogic()->launchScene( launchScene ); // launch different clip
|
||||
QUNIT_IS_TRUE( jack->getGridLogic()->getLaunchedScene() == launchScene );
|
||||
//LUPPP_NOTE("state after before bar = %s", GridLogic::StateString[ lc->getState() ] );
|
||||
QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_STOP_QUEUED );
|
||||
jack->getGridLogic()->bar();
|
||||
//LUPPP_NOTE("state after bar = %s", GridLogic::StateString[ lc->getState() ] );
|
||||
QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_STOPPED );
|
||||
|
||||
|
||||
/// PRESS PAD
|
||||
// empty -> recording
|
||||
lc->init();
|
||||
QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_EMPTY );
|
||||
jack->getGridLogic()->pressed( t, s );
|
||||
jack->getGridLogic()->released( t, s );
|
||||
QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_RECORD_QUEUED );
|
||||
jack->getGridLogic()->bar();
|
||||
QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_RECORDING );
|
||||
|
||||
float buffer[64];
|
||||
lc->record(64, &buffer[0], &buffer[0]);
|
||||
|
||||
// recording -> playing
|
||||
jack->getGridLogic()->pressed( t, s );
|
||||
jack->getGridLogic()->released( t, s );
|
||||
QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_PLAY_QUEUED );
|
||||
jack->getGridLogic()->bar();
|
||||
QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_PLAYING );
|
||||
// playing -> stopped
|
||||
jack->getGridLogic()->pressed( t, s );
|
||||
jack->getGridLogic()->released( t, s );
|
||||
QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_STOP_QUEUED );
|
||||
jack->getGridLogic()->bar();
|
||||
QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_STOPPED );
|
||||
// stopped -> playing
|
||||
jack->getGridLogic()->pressed( t, s );
|
||||
jack->getGridLogic()->released( t, s );
|
||||
QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_PLAY_QUEUED );
|
||||
jack->getGridLogic()->bar();
|
||||
QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_PLAYING );
|
||||
|
||||
|
||||
/// DOUBLE PRESS PAD
|
||||
// empty -> recordQ -> empty
|
||||
lc->init();
|
||||
QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_EMPTY );
|
||||
jack->getGridLogic()->pressed( t, s );
|
||||
jack->getGridLogic()->released( t, s );
|
||||
QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_RECORD_QUEUED );
|
||||
jack->getGridLogic()->pressed( t, s );
|
||||
jack->getGridLogic()->released( t, s );
|
||||
QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_EMPTY );
|
||||
lc->bar();
|
||||
|
||||
// recording -> playing -> stopped
|
||||
lc->setState( true, false, true, false, false, false );
|
||||
QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_RECORDING );
|
||||
jack->getGridLogic()->pressed( t, s );
|
||||
jack->getGridLogic()->released( t, s );
|
||||
QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_PLAY_QUEUED );
|
||||
jack->getGridLogic()->pressed( t, s );
|
||||
jack->getGridLogic()->released( t, s );
|
||||
QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_STOP_QUEUED );
|
||||
lc->bar();
|
||||
|
||||
// stopped -> playing -> stopped
|
||||
lc->setState( true, false, false, false, false, false );
|
||||
QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_STOPPED );
|
||||
jack->getGridLogic()->pressed( t, s );
|
||||
jack->getGridLogic()->released( t, s );
|
||||
QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_PLAY_QUEUED );
|
||||
jack->getGridLogic()->pressed( t, s );
|
||||
jack->getGridLogic()->released( t, s );
|
||||
QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_STOP_QUEUED );
|
||||
|
||||
// stopped -> playing
|
||||
lc->setState( true, true, false, false, false, false );
|
||||
QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_PLAYING );
|
||||
jack->getGridLogic()->pressed( t, s );
|
||||
jack->getGridLogic()->released( t, s );
|
||||
QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_STOP_QUEUED );
|
||||
jack->getGridLogic()->pressed( t, s );
|
||||
jack->getGridLogic()->released( t, s );
|
||||
QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_PLAYING );
|
||||
return qunit.errors();
|
||||
}
|
||||
|
||||
#endif // BUILD_TESTS
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -33,259 +33,241 @@ extern Jack* jack;
|
|||
using namespace std;
|
||||
|
||||
TimeManager::TimeManager():
|
||||
transportState( TRANSPORT_ROLLING ),
|
||||
observers()
|
||||
transportState( TRANSPORT_ROLLING ),
|
||||
observers()
|
||||
{
|
||||
samplerate = jack->getSamplerate();
|
||||
// 120 BPM default
|
||||
fpb = samplerate / 2;
|
||||
|
||||
//Counter for current bar/beat
|
||||
barCounter = 0;
|
||||
beatCounter = 0;
|
||||
|
||||
previousBeat = 0;
|
||||
|
||||
//In process() we want to immediately process bar(), beat() of all observers
|
||||
// thats why beatFrameCountdown<nframes, but we don't know yet what value nframes has
|
||||
// so set beatFrameCountdown to a value that garantees beatFrameCountdown<nframes
|
||||
beatFrameCountdown = -1;//fpb;
|
||||
|
||||
totalFrameCounter = 0;
|
||||
|
||||
tapTempoPos = 0;
|
||||
tapTempo[0] = 0;
|
||||
tapTempo[1] = 0;
|
||||
tapTempo[2] = 0;
|
||||
samplerate = jack->getSamplerate();
|
||||
// 120 BPM default
|
||||
fpb = samplerate / 2;
|
||||
|
||||
//Counter for current bar/beat
|
||||
barCounter = 0;
|
||||
beatCounter = 0;
|
||||
|
||||
previousBeat = 0;
|
||||
|
||||
//In process() we want to immediately process bar(), beat() of all observers
|
||||
// thats why beatFrameCountdown<nframes, but we don't know yet what value nframes has
|
||||
// so set beatFrameCountdown to a value that garantees beatFrameCountdown<nframes
|
||||
beatFrameCountdown = -1;//fpb;
|
||||
|
||||
totalFrameCounter = 0;
|
||||
|
||||
tapTempoPos = 0;
|
||||
tapTempo[0] = 0;
|
||||
tapTempo[1] = 0;
|
||||
tapTempo[2] = 0;
|
||||
}
|
||||
|
||||
|
||||
int TimeManager::getFpb()
|
||||
{
|
||||
return fpb;
|
||||
return fpb;
|
||||
}
|
||||
|
||||
void TimeManager::setBpm(float bpm)
|
||||
{
|
||||
#ifdef DEBUG_TIME
|
||||
LUPPP_NOTE("%s %f","setBpm()",bpm);
|
||||
LUPPP_NOTE("%s %f","setBpm()",bpm);
|
||||
#endif
|
||||
setFpb( samplerate / bpm * 60 );
|
||||
barCounter = 0;
|
||||
beatCounter = 0;
|
||||
beatFrameCountdown = -1;
|
||||
/*
|
||||
for(int i=0;i<observers.size();i++)
|
||||
observers[i]->resetTimeState();
|
||||
*/
|
||||
setFpb( samplerate / bpm * 60 );
|
||||
barCounter = 0;
|
||||
beatCounter = 0;
|
||||
beatFrameCountdown = -1;
|
||||
/*
|
||||
for(int i=0;i<observers.size();i++)
|
||||
observers[i]->resetTimeState();
|
||||
*/
|
||||
}
|
||||
|
||||
void TimeManager::setBpmZeroOne(float b)
|
||||
{
|
||||
setBpm( b * 160 + 60 ); // 60 - 220
|
||||
setBpm( b * 160 + 60 ); // 60 - 220
|
||||
}
|
||||
|
||||
|
||||
void TimeManager::setFpb(float f)
|
||||
{
|
||||
fpb = f;
|
||||
int bpm = ( samplerate * 60) / f;
|
||||
|
||||
char buffer [50];
|
||||
sprintf (buffer, "TM, setFpb() %i, bpm = %i", int(f), int(bpm) );
|
||||
EventGuiPrint e( buffer );
|
||||
writeToGuiRingbuffer( &e );
|
||||
|
||||
EventTimeBPM e2( bpm );
|
||||
writeToGuiRingbuffer( &e2 );
|
||||
|
||||
for(uint i = 0; i < observers.size(); i++)
|
||||
{
|
||||
observers.at(i)->setFpb(fpb);
|
||||
}
|
||||
fpb = f;
|
||||
int bpm = ( samplerate * 60) / f;
|
||||
|
||||
char buffer [50];
|
||||
sprintf (buffer, "TM, setFpb() %i, bpm = %i", int(f), int(bpm) );
|
||||
EventGuiPrint e( buffer );
|
||||
writeToGuiRingbuffer( &e );
|
||||
|
||||
EventTimeBPM e2( bpm );
|
||||
writeToGuiRingbuffer( &e2 );
|
||||
|
||||
for(uint i = 0; i < observers.size(); i++) {
|
||||
observers.at(i)->setFpb(fpb);
|
||||
}
|
||||
}
|
||||
|
||||
void TimeManager::registerObserver(TimeObserver* o)
|
||||
{
|
||||
//LUPPP_NOTE("%s","registerObserver()");
|
||||
observers.push_back(o);
|
||||
o->setFpb( fpb );
|
||||
|
||||
int bpm = ( samplerate * 60) / fpb;
|
||||
EventTimeBPM e2( bpm );
|
||||
writeToGuiRingbuffer( &e2 );
|
||||
//LUPPP_NOTE("%s","registerObserver()");
|
||||
observers.push_back(o);
|
||||
o->setFpb( fpb );
|
||||
|
||||
int bpm = ( samplerate * 60) / fpb;
|
||||
EventTimeBPM e2( bpm );
|
||||
writeToGuiRingbuffer( &e2 );
|
||||
}
|
||||
|
||||
void TimeManager::tap()
|
||||
{
|
||||
// reset tap tempo to "first tap" if more than 5 secs elapsed since last tap
|
||||
if ( tapTempo[0] < totalFrameCounter - samplerate * 5 )
|
||||
{
|
||||
tapTempoPos = 0;
|
||||
}
|
||||
|
||||
if ( tapTempoPos < 3 )
|
||||
{
|
||||
tapTempo[tapTempoPos] = totalFrameCounter;
|
||||
tapTempoPos++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// calculate frames per tap
|
||||
int tapFpb1 = tapTempo[1] - tapTempo[0];
|
||||
int tapFpb2 = tapTempo[2] - tapTempo[1];
|
||||
int tapFpb3 = totalFrameCounter - tapTempo[2]; // last tap, until now
|
||||
|
||||
int average = (tapFpb1 + tapFpb2 + tapFpb3) / 3;
|
||||
// reset tap tempo to "first tap" if more than 5 secs elapsed since last tap
|
||||
if ( tapTempo[0] < totalFrameCounter - samplerate * 5 ) {
|
||||
tapTempoPos = 0;
|
||||
}
|
||||
|
||||
if( average < 13000 )
|
||||
{
|
||||
char buffer [50];
|
||||
sprintf (buffer, "TM, tap() average too slow! quitting");
|
||||
EventGuiPrint e( buffer );
|
||||
writeToGuiRingbuffer( &e );
|
||||
return;
|
||||
}
|
||||
|
||||
char buffer [50];
|
||||
sprintf (buffer, "TM, tap() average = %i", average );
|
||||
EventGuiPrint e( buffer );
|
||||
writeToGuiRingbuffer( &e );
|
||||
|
||||
if ( tapTempoPos < 3 ) {
|
||||
tapTempo[tapTempoPos] = totalFrameCounter;
|
||||
tapTempoPos++;
|
||||
} else {
|
||||
// calculate frames per tap
|
||||
int tapFpb1 = tapTempo[1] - tapTempo[0];
|
||||
int tapFpb2 = tapTempo[2] - tapTempo[1];
|
||||
int tapFpb3 = totalFrameCounter - tapTempo[2]; // last tap, until now
|
||||
|
||||
setFpb(average);
|
||||
|
||||
// reset, so next 3 taps restart process
|
||||
tapTempoPos = 0;
|
||||
}
|
||||
int average = (tapFpb1 + tapFpb2 + tapFpb3) / 3;
|
||||
|
||||
if( average < 13000 ) {
|
||||
char buffer [50];
|
||||
sprintf (buffer, "TM, tap() average too slow! quitting");
|
||||
EventGuiPrint e( buffer );
|
||||
writeToGuiRingbuffer( &e );
|
||||
return;
|
||||
}
|
||||
|
||||
char buffer [50];
|
||||
sprintf (buffer, "TM, tap() average = %i", average );
|
||||
EventGuiPrint e( buffer );
|
||||
writeToGuiRingbuffer( &e );
|
||||
|
||||
|
||||
setFpb(average);
|
||||
|
||||
// reset, so next 3 taps restart process
|
||||
tapTempoPos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int TimeManager::getNframesToBeat()
|
||||
{
|
||||
// FIXME
|
||||
return -1; //beatFrameCountdown;
|
||||
// FIXME
|
||||
return -1; //beatFrameCountdown;
|
||||
}
|
||||
|
||||
void TimeManager::setTransportState( TRANSPORT_STATE s )
|
||||
{
|
||||
transportState = s;
|
||||
if(transportState == TRANSPORT_STOPPED)
|
||||
jack->transportRolling(false);
|
||||
else
|
||||
{
|
||||
jack->transportRolling(true);
|
||||
barCounter = 0;
|
||||
beatCounter = 0;
|
||||
beatFrameCountdown = -1;
|
||||
for(int i=0;i<observers.size();i++)
|
||||
observers[i]->resetTimeState();
|
||||
}
|
||||
transportState = s;
|
||||
if(transportState == TRANSPORT_STOPPED)
|
||||
jack->transportRolling(false);
|
||||
else {
|
||||
jack->transportRolling(true);
|
||||
barCounter = 0;
|
||||
beatCounter = 0;
|
||||
beatFrameCountdown = -1;
|
||||
for(int i=0; i<observers.size(); i++)
|
||||
observers[i]->resetTimeState();
|
||||
}
|
||||
}
|
||||
|
||||
void TimeManager::process(Buffers* buffers)
|
||||
{
|
||||
// time signature?
|
||||
//buffers->transportPosition->beats_per_bar = 4;
|
||||
//buffers->transportPosition->beat_type = 4;
|
||||
|
||||
if ( transportState == TRANSPORT_STOPPED )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int nframes = buffers->nframes;
|
||||
|
||||
// time signature?
|
||||
//buffers->transportPosition->beats_per_bar = 4;
|
||||
//buffers->transportPosition->beat_type = 4;
|
||||
|
||||
if ( transportState == TRANSPORT_STOPPED ) {
|
||||
return;
|
||||
}
|
||||
|
||||
int nframes = buffers->nframes;
|
||||
|
||||
|
||||
|
||||
if ( beatFrameCountdown < nframes )
|
||||
{
|
||||
//length of beat is not multiple of nframes, so need to process last frames of last beat *before* setting next beat
|
||||
//then set new beat (get the queued actions: play, rec etc)
|
||||
// then process first frames *after* new beat
|
||||
int before=(beatCounter*fpb)%nframes;
|
||||
int after=nframes-before;
|
||||
|
||||
if ( before < nframes && after <= nframes && before + after == nframes )
|
||||
{
|
||||
char buffer [50];
|
||||
|
||||
|
||||
if ( beatFrameCountdown < nframes ) {
|
||||
//length of beat is not multiple of nframes, so need to process last frames of last beat *before* setting next beat
|
||||
//then set new beat (get the queued actions: play, rec etc)
|
||||
// then process first frames *after* new beat
|
||||
int before=(beatCounter*fpb)%nframes;
|
||||
int after=nframes-before;
|
||||
|
||||
if ( before < nframes && after <= nframes && before + after == nframes ) {
|
||||
char buffer [50];
|
||||
// sprintf (buffer, "Timing OK: before %i, after %i, b+a %i", before, after, before+after );
|
||||
// EventGuiPrint e2( buffer );
|
||||
// writeToGuiRingbuffer( &e2 );
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
char buffer [50];
|
||||
sprintf (buffer, "Timing Error: before: %i, after %i", before, after );
|
||||
EventGuiPrint e2( buffer );
|
||||
writeToGuiRingbuffer( &e2 );
|
||||
}
|
||||
|
||||
// process before beat:
|
||||
if(before)
|
||||
jack->processFrames( before );
|
||||
|
||||
// handle beat:
|
||||
// inform observers of new beat FIRST
|
||||
for(uint i = 0; i < observers.size(); i++)
|
||||
{
|
||||
observers.at(i)->beat();
|
||||
}
|
||||
|
||||
if ( beatCounter % 4 == 0 )
|
||||
{
|
||||
// inform observers of new bar SECOND
|
||||
for(uint i = 0; i < observers.size(); i++)
|
||||
{
|
||||
observers.at(i)->bar();
|
||||
}
|
||||
barCounter++;
|
||||
//beatCounter=0;
|
||||
}
|
||||
|
||||
// process after
|
||||
// we need to clear internal buffers in order to write *after* frames to them
|
||||
jack->clearInternalBuffers(nframes);
|
||||
if(after)
|
||||
jack->processFrames( after );
|
||||
|
||||
// write new beat to UI (bar info currently not used)
|
||||
EventTimeBarBeat e( barCounter, beatCounter );
|
||||
writeToGuiRingbuffer( &e );
|
||||
|
||||
|
||||
|
||||
beatFrameCountdown = fpb-after;
|
||||
beatCounter++;
|
||||
}
|
||||
else
|
||||
{
|
||||
jack->processFrames( nframes );
|
||||
beatFrameCountdown -= nframes;
|
||||
} else {
|
||||
char buffer [50];
|
||||
sprintf (buffer, "Timing Error: before: %i, after %i", before, after );
|
||||
EventGuiPrint e2( buffer );
|
||||
writeToGuiRingbuffer( &e2 );
|
||||
}
|
||||
|
||||
}
|
||||
// process before beat:
|
||||
if(before)
|
||||
jack->processFrames( before );
|
||||
|
||||
totalFrameCounter += nframes;
|
||||
|
||||
// write BPM / transport info to JACK
|
||||
int bpm = ( samplerate * 60) / fpb;
|
||||
if ( buffers->transportPosition )
|
||||
{
|
||||
buffers->transportPosition->valid = (jack_position_bits_t)(JackPositionBBT | JackTransportPosition);
|
||||
|
||||
buffers->transportPosition->bar = beatCounter / 4 + 1;// bars 1-based
|
||||
buffers->transportPosition->beat = (beatCounter % 4) + 1; // beats 1-4
|
||||
|
||||
float part = float( fpb-beatFrameCountdown) / fpb;
|
||||
buffers->transportPosition->tick = part > 1.0f? 0.9999*1920 : part*1920;
|
||||
|
||||
buffers->transportPosition->frame = totalFrameCounter;
|
||||
|
||||
buffers->transportPosition->ticks_per_beat = 1920;
|
||||
buffers->transportPosition->beats_per_bar = 4;
|
||||
|
||||
buffers->transportPosition->beats_per_minute = bpm;
|
||||
}
|
||||
// handle beat:
|
||||
// inform observers of new beat FIRST
|
||||
for(uint i = 0; i < observers.size(); i++) {
|
||||
observers.at(i)->beat();
|
||||
}
|
||||
|
||||
if ( beatCounter % 4 == 0 ) {
|
||||
// inform observers of new bar SECOND
|
||||
for(uint i = 0; i < observers.size(); i++) {
|
||||
observers.at(i)->bar();
|
||||
}
|
||||
barCounter++;
|
||||
//beatCounter=0;
|
||||
}
|
||||
|
||||
// process after
|
||||
// we need to clear internal buffers in order to write *after* frames to them
|
||||
jack->clearInternalBuffers(nframes);
|
||||
if(after)
|
||||
jack->processFrames( after );
|
||||
|
||||
// write new beat to UI (bar info currently not used)
|
||||
EventTimeBarBeat e( barCounter, beatCounter );
|
||||
writeToGuiRingbuffer( &e );
|
||||
|
||||
|
||||
|
||||
beatFrameCountdown = fpb-after;
|
||||
beatCounter++;
|
||||
} else {
|
||||
jack->processFrames( nframes );
|
||||
beatFrameCountdown -= nframes;
|
||||
|
||||
}
|
||||
|
||||
totalFrameCounter += nframes;
|
||||
|
||||
// write BPM / transport info to JACK
|
||||
int bpm = ( samplerate * 60) / fpb;
|
||||
if ( buffers->transportPosition ) {
|
||||
buffers->transportPosition->valid = (jack_position_bits_t)(JackPositionBBT | JackTransportPosition);
|
||||
|
||||
buffers->transportPosition->bar = beatCounter / 4 + 1;// bars 1-based
|
||||
buffers->transportPosition->beat = (beatCounter % 4) + 1; // beats 1-4
|
||||
|
||||
float part = float( fpb-beatFrameCountdown) / fpb;
|
||||
buffers->transportPosition->tick = part > 1.0f? 0.9999*1920 : part*1920;
|
||||
|
||||
buffers->transportPosition->frame = totalFrameCounter;
|
||||
|
||||
buffers->transportPosition->ticks_per_beat = 1920;
|
||||
buffers->transportPosition->beats_per_bar = 4;
|
||||
|
||||
buffers->transportPosition->beats_per_minute = bpm;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -32,57 +32,57 @@ using namespace std;
|
|||
|
||||
class TimeManager
|
||||
{
|
||||
public:
|
||||
TimeManager();
|
||||
|
||||
int getFpb();
|
||||
void setBpm(float bpm);
|
||||
void setBpmZeroOne(float bpm);
|
||||
void setFpb(float f);
|
||||
|
||||
/// add a component to be updated for time events
|
||||
void registerObserver(TimeObserver* o);
|
||||
|
||||
/// call this when a tempo-tap occurs
|
||||
void tap();
|
||||
|
||||
/// called to process buffers->nframes samples. If a beat is present, this
|
||||
/// is handled gracefully, first calling process up to the beat, then doing
|
||||
/// a beat() event on all TimeObservers, and processing the remaining samples
|
||||
void process(Buffers* buffers);
|
||||
|
||||
/// returns the number of samples till beat if a beat exists in this process
|
||||
/// Otherwise returns nframes
|
||||
int getNframesToBeat();
|
||||
|
||||
/// TRANSPORT_STATE is defined in transport.hxx
|
||||
void setTransportState( TRANSPORT_STATE s );
|
||||
|
||||
private:
|
||||
int samplerate;
|
||||
|
||||
/// the "state" of the transport: rolling or stopped
|
||||
TRANSPORT_STATE transportState;
|
||||
|
||||
/// number of frames per beat
|
||||
int fpb;
|
||||
|
||||
/// holds the number of frames processed
|
||||
long long totalFrameCounter;
|
||||
|
||||
/// frame number of the last beat
|
||||
long previousBeat;
|
||||
|
||||
long beatFrameCountdown;
|
||||
|
||||
/// counts bars / beats processed
|
||||
int barCounter;
|
||||
int beatCounter;
|
||||
|
||||
int tapTempoPos;
|
||||
long long tapTempo[3];
|
||||
|
||||
std::vector<TimeObserver*> observers;
|
||||
public:
|
||||
TimeManager();
|
||||
|
||||
int getFpb();
|
||||
void setBpm(float bpm);
|
||||
void setBpmZeroOne(float bpm);
|
||||
void setFpb(float f);
|
||||
|
||||
/// add a component to be updated for time events
|
||||
void registerObserver(TimeObserver* o);
|
||||
|
||||
/// call this when a tempo-tap occurs
|
||||
void tap();
|
||||
|
||||
/// called to process buffers->nframes samples. If a beat is present, this
|
||||
/// is handled gracefully, first calling process up to the beat, then doing
|
||||
/// a beat() event on all TimeObservers, and processing the remaining samples
|
||||
void process(Buffers* buffers);
|
||||
|
||||
/// returns the number of samples till beat if a beat exists in this process
|
||||
/// Otherwise returns nframes
|
||||
int getNframesToBeat();
|
||||
|
||||
/// TRANSPORT_STATE is defined in transport.hxx
|
||||
void setTransportState( TRANSPORT_STATE s );
|
||||
|
||||
private:
|
||||
int samplerate;
|
||||
|
||||
/// the "state" of the transport: rolling or stopped
|
||||
TRANSPORT_STATE transportState;
|
||||
|
||||
/// number of frames per beat
|
||||
int fpb;
|
||||
|
||||
/// holds the number of frames processed
|
||||
long long totalFrameCounter;
|
||||
|
||||
/// frame number of the last beat
|
||||
long previousBeat;
|
||||
|
||||
long beatFrameCountdown;
|
||||
|
||||
/// counts bars / beats processed
|
||||
int barCounter;
|
||||
int beatCounter;
|
||||
|
||||
int tapTempoPos;
|
||||
long long tapTempo[3];
|
||||
|
||||
std::vector<TimeObserver*> observers;
|
||||
};
|
||||
|
||||
#endif // LUPPP_TIME_H
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -22,149 +22,145 @@
|
|||
extern Jack* jack;
|
||||
|
||||
TrackOutput::TrackOutput(int t, AudioProcessor* ap) :
|
||||
AudioProcessor(),
|
||||
track(t),
|
||||
_recordArm(false),
|
||||
previousInChain(ap)
|
||||
AudioProcessor(),
|
||||
track(t),
|
||||
_recordArm(false),
|
||||
previousInChain(ap)
|
||||
{
|
||||
// UI update
|
||||
uiUpdateConstant = jack->getSamplerate() / 30;
|
||||
uiUpdateCounter = jack->getSamplerate() / 30;
|
||||
|
||||
dbMeter = new DBMeter( jack->getSamplerate() );
|
||||
|
||||
_toMaster = 0.8;
|
||||
_toMasterLag = 0.8;
|
||||
_toMasterDiff = 0;
|
||||
_toReverb = 0.0;
|
||||
_toSidechain = 0.0;
|
||||
_toPostSidechain = 0.0;
|
||||
|
||||
_toPostfaderActive = 0;
|
||||
_toKeyActive = 0;
|
||||
_toXSideActive = true;
|
||||
// UI update
|
||||
uiUpdateConstant = jack->getSamplerate() / 30;
|
||||
uiUpdateCounter = jack->getSamplerate() / 30;
|
||||
|
||||
dbMeter = new DBMeter( jack->getSamplerate() );
|
||||
|
||||
_toMaster = 0.8;
|
||||
_toMasterLag = 0.8;
|
||||
_toMasterDiff = 0;
|
||||
_toReverb = 0.0;
|
||||
_toSidechain = 0.0;
|
||||
_toPostSidechain = 0.0;
|
||||
|
||||
_toPostfaderActive = 0;
|
||||
_toKeyActive = 0;
|
||||
_toXSideActive = true;
|
||||
}
|
||||
|
||||
|
||||
void TrackOutput::setMaster(float value)
|
||||
{
|
||||
if(value < 0.01)
|
||||
value = 0.f;
|
||||
_toMaster = value;
|
||||
_toMasterDiff=_toMaster-_toMasterLag;
|
||||
if(value < 0.01)
|
||||
value = 0.f;
|
||||
_toMaster = value;
|
||||
_toMasterDiff=_toMaster-_toMasterLag;
|
||||
}
|
||||
|
||||
float TrackOutput::getMaster()
|
||||
{
|
||||
return _toMaster;
|
||||
return _toMaster;
|
||||
}
|
||||
|
||||
|
||||
bool TrackOutput::recordArm()
|
||||
{
|
||||
return _recordArm;
|
||||
return _recordArm;
|
||||
}
|
||||
|
||||
void TrackOutput::recordArm(bool r)
|
||||
{
|
||||
_recordArm = r;
|
||||
_recordArm = r;
|
||||
}
|
||||
|
||||
void TrackOutput::setSendActive( int send, bool a )
|
||||
{
|
||||
switch( send )
|
||||
{
|
||||
case SEND_POSTFADER:
|
||||
_toPostfaderActive = a;
|
||||
break;
|
||||
case SEND_KEY:
|
||||
_toKeyActive = a;
|
||||
break;
|
||||
//case SEND_XSIDE:
|
||||
// _toXSideActive = a;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
switch( send ) {
|
||||
case SEND_POSTFADER:
|
||||
_toPostfaderActive = a;
|
||||
break;
|
||||
case SEND_KEY:
|
||||
_toKeyActive = a;
|
||||
break;
|
||||
//case SEND_XSIDE:
|
||||
// _toXSideActive = a;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void TrackOutput::setSend( int send, float value )
|
||||
{
|
||||
switch( send )
|
||||
{
|
||||
case SEND_POSTFADER:
|
||||
_toReverb = value;
|
||||
break;
|
||||
case SEND_KEY:
|
||||
// setSendActive() handles on/off for this send
|
||||
//_toSidechain = value;
|
||||
break;
|
||||
case SEND_XSIDE:
|
||||
_toPostSidechain = value;
|
||||
break;
|
||||
}
|
||||
switch( send ) {
|
||||
case SEND_POSTFADER:
|
||||
_toReverb = value;
|
||||
break;
|
||||
case SEND_KEY:
|
||||
// setSendActive() handles on/off for this send
|
||||
//_toSidechain = value;
|
||||
break;
|
||||
case SEND_XSIDE:
|
||||
_toPostSidechain = value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void TrackOutput::process(unsigned int nframes, Buffers* buffers)
|
||||
{
|
||||
//compute master volume lag;
|
||||
if(fabs(_toMaster-_toMasterLag)>=fabs(_toMasterDiff/100.0))
|
||||
_toMasterLag+=_toMasterDiff/10.0;
|
||||
// get & zero track buffer
|
||||
float* trackBuffer = buffers->audio[Buffers::RETURN_TRACK_0 + track];
|
||||
memset( trackBuffer, 0, sizeof(float)*nframes );
|
||||
|
||||
// call process() up the chain
|
||||
previousInChain->process( nframes, buffers );
|
||||
|
||||
// run the meter
|
||||
dbMeter->process( nframes, trackBuffer, trackBuffer );
|
||||
|
||||
if (uiUpdateCounter > uiUpdateConstant )
|
||||
{
|
||||
float l = dbMeter->getLeftDB() * _toMasterLag;
|
||||
float r = dbMeter->getRightDB() * _toMasterLag;
|
||||
EventTrackSignalLevel e( track, l, r );
|
||||
writeToGuiRingbuffer( &e );
|
||||
uiUpdateCounter = 0;
|
||||
}
|
||||
|
||||
uiUpdateCounter += nframes;
|
||||
|
||||
// copy audio data into reverb / sidechain / master buffers
|
||||
float* reverb = buffers->audio[Buffers::SEND];
|
||||
float* sidechain = buffers->audio[Buffers::SIDECHAIN_KEY];
|
||||
float* postSidechain = buffers->audio[Buffers::SIDECHAIN_SIGNAL];
|
||||
|
||||
float* masterL = buffers->audio[Buffers::MASTER_OUT_L];
|
||||
float* masterR = buffers->audio[Buffers::MASTER_OUT_R];
|
||||
//compute master volume lag;
|
||||
if(fabs(_toMaster-_toMasterLag)>=fabs(_toMasterDiff/100.0))
|
||||
_toMasterLag+=_toMasterDiff/10.0;
|
||||
// get & zero track buffer
|
||||
float* trackBuffer = buffers->audio[Buffers::RETURN_TRACK_0 + track];
|
||||
memset( trackBuffer, 0, sizeof(float)*nframes );
|
||||
|
||||
// call process() up the chain
|
||||
previousInChain->process( nframes, buffers );
|
||||
|
||||
// run the meter
|
||||
dbMeter->process( nframes, trackBuffer, trackBuffer );
|
||||
|
||||
if (uiUpdateCounter > uiUpdateConstant ) {
|
||||
float l = dbMeter->getLeftDB() * _toMasterLag;
|
||||
float r = dbMeter->getRightDB() * _toMasterLag;
|
||||
EventTrackSignalLevel e( track, l, r );
|
||||
writeToGuiRingbuffer( &e );
|
||||
uiUpdateCounter = 0;
|
||||
}
|
||||
|
||||
uiUpdateCounter += nframes;
|
||||
|
||||
// copy audio data into reverb / sidechain / master buffers
|
||||
float* reverb = buffers->audio[Buffers::SEND];
|
||||
float* sidechain = buffers->audio[Buffers::SIDECHAIN_KEY];
|
||||
float* postSidechain = buffers->audio[Buffers::SIDECHAIN_SIGNAL];
|
||||
|
||||
float* masterL = buffers->audio[Buffers::MASTER_OUT_L];
|
||||
float* masterR = buffers->audio[Buffers::MASTER_OUT_R];
|
||||
|
||||
|
||||
float* jackoutput = buffers->audio[Buffers::JACK_TRACK_0+track];
|
||||
|
||||
for(unsigned int i = 0; i < nframes; i++)
|
||||
{
|
||||
// * master for "post-fader" sends
|
||||
float tmp = trackBuffer[i];
|
||||
|
||||
// post-sidechain *moves* signal between "before/after" ducking, not add!
|
||||
masterL[i] += tmp * _toMasterLag * (1-_toPostSidechain);
|
||||
masterR[i] += tmp * _toMasterLag * (1-_toPostSidechain);
|
||||
if(jackoutput)
|
||||
jackoutput[i] = tmp * _toMasterLag * (1-_toPostSidechain);
|
||||
if ( _toPostfaderActive )
|
||||
reverb[i] += tmp * _toReverb * _toMasterLag;
|
||||
|
||||
if ( _toXSideActive )
|
||||
postSidechain[i] += tmp * _toPostSidechain * _toMasterLag;
|
||||
|
||||
// turning down an element in the mix should *NOT* influence sidechaining
|
||||
if ( _toKeyActive )
|
||||
sidechain[i] += tmp;
|
||||
|
||||
}
|
||||
float* jackoutput = buffers->audio[Buffers::JACK_TRACK_0+track];
|
||||
|
||||
for(unsigned int i = 0; i < nframes; i++) {
|
||||
// * master for "post-fader" sends
|
||||
float tmp = trackBuffer[i];
|
||||
|
||||
// post-sidechain *moves* signal between "before/after" ducking, not add!
|
||||
masterL[i] += tmp * _toMasterLag * (1-_toPostSidechain);
|
||||
masterR[i] += tmp * _toMasterLag * (1-_toPostSidechain);
|
||||
if(jackoutput)
|
||||
jackoutput[i] = tmp * _toMasterLag * (1-_toPostSidechain);
|
||||
if ( _toPostfaderActive )
|
||||
reverb[i] += tmp * _toReverb * _toMasterLag;
|
||||
|
||||
if ( _toXSideActive )
|
||||
postSidechain[i] += tmp * _toPostSidechain * _toMasterLag;
|
||||
|
||||
// turning down an element in the mix should *NOT* influence sidechaining
|
||||
if ( _toKeyActive )
|
||||
sidechain[i] += tmp;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
TrackOutput::~TrackOutput()
|
||||
{
|
||||
delete dbMeter;
|
||||
delete dbMeter;
|
||||
}
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -35,52 +35,52 @@
|
|||
**/
|
||||
class TrackOutput : public AudioProcessor
|
||||
{
|
||||
public:
|
||||
TrackOutput(int t, AudioProcessor* ap);
|
||||
|
||||
/// set main mix, 0-1
|
||||
void setMaster(float value);
|
||||
|
||||
float getMaster();
|
||||
|
||||
bool recordArm();
|
||||
void recordArm(bool r);
|
||||
|
||||
/// set send
|
||||
void setSend( int send, float value );
|
||||
void setSendActive( int send, bool active );
|
||||
|
||||
/// copies the track output to master buffer, sidechain & post-side buffer
|
||||
void process(unsigned int nframes, Buffers* buffers);
|
||||
|
||||
~TrackOutput();
|
||||
|
||||
private:
|
||||
int track;
|
||||
|
||||
bool _recordArm;
|
||||
/// _toMasterLag is a volume that lags behind _toMaster when setMaster() is called
|
||||
/// This prohibits audible jumps when rapidly changing the volume
|
||||
float _toMaster;
|
||||
float _toMasterLag;
|
||||
float _toMasterDiff;
|
||||
public:
|
||||
TrackOutput(int t, AudioProcessor* ap);
|
||||
|
||||
/// set main mix, 0-1
|
||||
void setMaster(float value);
|
||||
|
||||
float getMaster();
|
||||
|
||||
bool recordArm();
|
||||
void recordArm(bool r);
|
||||
|
||||
/// set send
|
||||
void setSend( int send, float value );
|
||||
void setSendActive( int send, bool active );
|
||||
|
||||
/// copies the track output to master buffer, sidechain & post-side buffer
|
||||
void process(unsigned int nframes, Buffers* buffers);
|
||||
|
||||
~TrackOutput();
|
||||
|
||||
private:
|
||||
int track;
|
||||
|
||||
bool _recordArm;
|
||||
/// _toMasterLag is a volume that lags behind _toMaster when setMaster() is called
|
||||
/// This prohibits audible jumps when rapidly changing the volume
|
||||
float _toMaster;
|
||||
float _toMasterLag;
|
||||
float _toMasterDiff;
|
||||
|
||||
float _toReverb;
|
||||
float _toSidechain;
|
||||
float _toPostSidechain;
|
||||
|
||||
bool _toPostfaderActive;
|
||||
bool _toKeyActive;
|
||||
bool _toXSideActive;
|
||||
|
||||
/// Pointer to "previous" processor: the graph is backwards
|
||||
AudioProcessor* previousInChain;
|
||||
|
||||
// Metering variables
|
||||
long uiUpdateCounter;
|
||||
long uiUpdateConstant;
|
||||
DBMeter* dbMeter;
|
||||
|
||||
float _toReverb;
|
||||
float _toSidechain;
|
||||
float _toPostSidechain;
|
||||
|
||||
bool _toPostfaderActive;
|
||||
bool _toKeyActive;
|
||||
bool _toXSideActive;
|
||||
|
||||
/// Pointer to "previous" processor: the graph is backwards
|
||||
AudioProcessor* previousInChain;
|
||||
|
||||
// Metering variables
|
||||
long uiUpdateCounter;
|
||||
long uiUpdateConstant;
|
||||
DBMeter* dbMeter;
|
||||
|
||||
};
|
||||
|
||||
#endif // LUPPP_TRACK_OUTPUT_H
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -19,10 +19,9 @@
|
|||
#ifndef LUPPP_TRANSPORT_H
|
||||
#define LUPPP_TRANSPORT_H
|
||||
|
||||
enum TRANSPORT_STATE
|
||||
{
|
||||
TRANSPORT_STOPPED = 0,
|
||||
TRANSPORT_ROLLING,
|
||||
enum TRANSPORT_STATE {
|
||||
TRANSPORT_STOPPED = 0,
|
||||
TRANSPORT_ROLLING,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Add table
Reference in a new issue