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:
Harry van Haaren 2016-12-27 12:47:19 +00:00
parent 0020d9a672
commit 01f71ec5e4
93 changed files with 11792 additions and 11466 deletions

1
.gitignore vendored
View file

@ -5,6 +5,7 @@ src/*.o
luppp
*.zip
*.orig
build/*
buildTest/*

View file

@ -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);
}
/*

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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;
};
}

View file

@ -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

View file

@ -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

View file

@ -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);
}
}

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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/>.
*/

View file

@ -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

View file

@ -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;
}

View file

@ -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

View file

@ -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

View file

@ -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 );
}

View file

@ -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

View file

@ -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;
}

View file

@ -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

View file

@ -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);
}

View file

@ -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

View file

@ -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" );
}

View file

@ -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,

View file

@ -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__

File diff suppressed because it is too large Load diff

View file

@ -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

View file

@ -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();
}

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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;
}

View file

@ -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

View file

@ -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;
}
}

File diff suppressed because it is too large Load diff

View file

@ -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/>.
*/

View file

@ -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

View file

@ -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

View file

@ -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;
}

View file

@ -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

View file

@ -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);
}

View file

@ -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

View file

@ -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;
}

View file

@ -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

View file

@ -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()
{
}

View file

@ -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;
};

View file

@ -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 );
}
}

View file

@ -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

File diff suppressed because it is too large Load diff

View file

@ -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

View file

@ -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

File diff suppressed because it is too large Load diff

View file

@ -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

View file

@ -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;
}

View file

@ -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;
};

View file

@ -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 );
}
}

View file

@ -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

View file

@ -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;
}
}

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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;
}

View file

@ -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++;
}
}
}

View file

@ -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

View file

@ -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++;
}
}

View file

@ -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

View file

@ -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 );
}

View file

@ -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

View file

@ -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();
}

View file

@ -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

View file

@ -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();
}

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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;
}
}

View file

@ -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

View file

@ -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;
}

View file

@ -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

View file

@ -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