-Refactored Worker into DiskReader and DiskWriter classes. Refactored ClipSelector into hxx / cxx pair

This commit is contained in:
Harry van Haaren 2013-09-05 18:33:16 +01:00
parent f37c87e48a
commit 13b5853034
13 changed files with 569 additions and 544 deletions

View file

@ -6,5 +6,5 @@ CFLAGS += -g -Wall -march=native -msse -mfpmath=sse -ffast-math
INCLUDES += `pkg-config --cflags jack sndfile cairomm-1.0 ntk ntk_images`
: foreach *.cxx observer/*.cxx save/*.cxx cjson/*.c dsp/*.cxx controller/*.cxx \
|> g++ $(CFLAGS) -c %f $(INCLUDES) -o %o |> %B.o
avtk/*.cxx |> g++ $(CFLAGS) -c %f $(INCLUDES) -o %o |> %B.o

View file

@ -3,8 +3,12 @@
#define LUPPP_AUDIOBUFFER_H
#include <vector>
#include <string>
#include <cstring>
#include <iostream>
using namespace std;
/// AudioBuffer stores float samples in a big vector.
class AudioBuffer
{
@ -36,9 +40,12 @@ class AudioBuffer
void setName(const char* n)
{
if ( strlen(n) > 19 )
{
#ifdef DEBUG_BUFFER
printf("AudioBuffer setName too long!\n" );
#endif return;
cout << "AudioBuffer setName too long!" << endl;
#endif
return;
}
memcpy( name, n, sizeof(char)* 20 );
}
@ -51,7 +58,7 @@ class AudioBuffer
void setBeats(int b)
{
#ifdef DEBUG_BUFFER
printf("AudioBuffer now has %i beats\n", b );
cout << "AudioBuffer now has " << b << " beats\n" << endl;
#endif
numBeats = b;
}

View file

@ -1,464 +0,0 @@
/*
* 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 2 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
*/
#ifndef AVTK_CLIP_SELECTOR_H
#define AVTK_CLIP_SELECTOR_H
#include <FL/Fl_Button.H>
#include <string>
#include <sstream>
#include "../gridlogic.hxx"
#include "../worker.hxx"
#include "../looper.hxx"
#include "../audiobuffer.hxx"
#include "../eventhandler.hxx"
using namespace std;
extern void luppp_tooltip(std::string s);
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;
};
class ClipSelector : public Fl_Button
{
public:
ClipSelector(int _x, int _y, int _w, int _h, const char *_label, bool master = false):
Fl_Button(_x, _y, _w, _h, _label)
{
x = _x;
y = _y;
w = _w;
h = _h;
label = _label;
_master = master;
if ( _master )
{
for(int i = 0; i < 10; i++ )
{
stringstream s;
s << i + 1;
clips[i].setName( s.str() );
}
}
highlight = false;
mouseOver = false;
}
int ID;
static const int numClips = 10;
ClipState clips[numClips];
bool _master;
bool mouseOver;
bool highlight;
int x, y, w, h;
const char* label;
void setID( int id )
{
ID = 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 )
{
#ifdef DEBUG_CLIP
cout << "setState clipNum = " << clipNum << " state = " << s << endl;
#endif
switch(s)
{
case GridLogic::STATE_RECORDING:
case GridLogic::STATE_STOPPED:
case GridLogic::STATE_EMPTY:
case GridLogic::STATE_PLAYING:
case GridLogic::STATE_PLAY_QUEUED:
case GridLogic::STATE_RECORD_QUEUED:
case GridLogic::STATE_STOP_QUEUED:
default: break;
}
clips[clipNum].setState( s );
redraw();
}
std::string clipName(int clip)
{
return clips[clip].getName();
}
void 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);
int drawY = y + 1;
for( int i = 0; i < numClips; i++) // draw each clip
{
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_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, x+10, drawY+8 );
cairo_line_to( cr, x+19, drawY+13 );
cairo_line_to( cr, x+10, drawY+18 );
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, x+10, drawY+8 );
cairo_line_to( cr, x+19, drawY+13 );
cairo_line_to( cr, x+10, drawY+18 );
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, x+14, drawY+13, 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, x+14, drawY+13, 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, x+14, drawY+13, 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 + 10, drawY + 17 );
cairo_set_source_rgba( cr, 255 / 255.f, 255 / 255.f , 255 / 255.f , 0.9 );
cairo_set_font_size( cr, 11 );
cairo_show_text( cr, clips[i].getName().c_str() );
drawY += clipHeight;
}
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;
{
// 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" },
{ "Bars", 0, 0, 0, FL_SUBMENU },
{"1 "},
{"2"},
{"4"},
{"8"},
{"16"},
{"32"},
{"64"},
{0},
//{ "Record" },
{ "Use as tempo" },
{ "Rename" },
{ 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 )
{
// FIXME: refactor
string path;
Fl_Native_File_Chooser fnfc;
fnfc.title("Pick a file");
fnfc.type(Fl_Native_File_Chooser::BROWSE_FILE);
//fnfc.filter("Wav\t*.wav");
fnfc.directory( getenv("HOME") ); // 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 directory: %s\n", fnfc.filename());
// update path and load it
path = fnfc.filename();
break;
}
if ( strcmp( path.c_str(), "" ) == 0 )
return 0;
AudioBuffer* ab = Worker::loadSample( path );
EventLooperLoad e = EventLooperLoad( ID, clipNum, ab );
writeToDspRingbuffer( &e );
}
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(), "Rename") == 0 )
{
const char* name = fl_input( "Scene name: ", clips[clipNum].getName().c_str() );
if ( name )
clips[clipNum].setName( name );
}
else if ( strcmp(m->label(), "Record") == 0 )
{
/*
//recordingClip = clipNum;
EventLooperState e = EventLooperState( ID, clipNum, Looper::STATE_RECORD_QUEUED);
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;
// push help string to UI tooltip area
luppp_tooltip( "Clip selector" );
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
#endif // AVTK_CLIP_SELECTOR_H

378
src/avtk/clipselector.cxx Normal file
View file

@ -0,0 +1,378 @@
/*
* 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 2 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
*/
#include "clipselector.hxx"
#include "../gui.hxx"
extern Gui* gui;
namespace Avtk
{
ClipSelector::ClipSelector( int _x, int _y, int _w, int _h,
const char *_label, bool master ) :
Fl_Button(_x, _y, _w, _h, _label)
{
x = _x;
y = _y;
w = _w;
h = _h;
label = _label;
_master = master;
if ( _master )
{
for(int i = 0; i < 10; i++ )
{
stringstream s;
s << i + 1;
clips[i].setName( s.str() );
}
}
highlight = false;
mouseOver = false;
}
void ClipSelector::setID( int id )
{
ID = 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 ClipSelector::setState( int clipNum, GridLogic::State s )
{
#ifdef DEBUG_CLIP
cout << "setState clipNum = " << clipNum << " state = " << s << endl;
#endif
switch(s)
{
case GridLogic::STATE_RECORDING:
case GridLogic::STATE_STOPPED:
case GridLogic::STATE_EMPTY:
case GridLogic::STATE_PLAYING:
case GridLogic::STATE_PLAY_QUEUED:
case GridLogic::STATE_RECORD_QUEUED:
case GridLogic::STATE_STOP_QUEUED:
default: break;
}
clips[clipNum].setState( s );
redraw();
}
std::string ClipSelector::clipName(int clip)
{
return clips[clip].getName();
}
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);
int drawY = y + 1;
for( int i = 0; i < numClips; i++) // draw each clip
{
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_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, x+10, drawY+8 );
cairo_line_to( cr, x+19, drawY+13 );
cairo_line_to( cr, x+10, drawY+18 );
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, x+10, drawY+8 );
cairo_line_to( cr, x+19, drawY+13 );
cairo_line_to( cr, x+10, drawY+18 );
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, x+14, drawY+13, 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, x+14, drawY+13, 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, x+14, drawY+13, 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 + 10, drawY + 17 );
cairo_set_source_rgba( cr, 255 / 255.f, 255 / 255.f , 255 / 255.f , 0.9 );
cairo_set_font_size( cr, 11 );
cairo_show_text( cr, clips[i].getName().c_str() );
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();
}
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" },
{ "Bars", 0, 0, 0, FL_SUBMENU },
{"1 "},
{"2"},
{"4"},
{"8"},
{"16"},
{"32"},
{"64"},
{0},
//{ "Record" },
{ "Use as tempo" },
{ "Rename" },
{ 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(), "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(), "Rename") == 0 )
{
const char* name = fl_input( "Scene name: ", clips[clipNum].getName().c_str() );
if ( name )
clips[clipNum].setName( name );
}
else if ( strcmp(m->label(), "Record") == 0 )
{
/*
//recordingClip = clipNum;
EventLooperState e = EventLooperState( ID, clipNum, Looper::STATE_RECORD_QUEUED);
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

111
src/avtk/clipselector.hxx Normal file
View file

@ -0,0 +1,111 @@
/*
* 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 2 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
*/
#ifndef AVTK_CLIP_SELECTOR_H
#define AVTK_CLIP_SELECTOR_H
#include <string>
#include <sstream>
#include <FL/Fl_Button.H>
#include "../config.hxx"
#include "../looper.hxx"
#include "../gridlogic.hxx"
#include "../audiobuffer.hxx"
#include "../eventhandler.hxx"
using namespace std;
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;
};
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];
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 );
std::string clipName(int clip);
void draw();
int handle(int event);
void resize(int X, int Y, int W, int H);
};
} // Avtk
#endif // AVTK_CLIP_SELECTOR_H

View file

@ -10,7 +10,10 @@
#include "event.hxx"
#include "eventhandler.hxx"
#include "worker.hxx"
#include "audiobuffer.hxx"
#include <sndfile.hh>
using namespace std;
@ -18,6 +21,28 @@ DiskReader::DiskReader()
{
};
AudioBuffer* DiskReader::loadSample( string path )
{
SndfileHandle infile( path, SFM_READ );
AudioBuffer* ab = new AudioBuffer();
std::vector<float> buf( infile.frames(), 0.f );
infile.read( &buf[0] , infile.frames() );
// read data from file
ab->setBeats(4);
ab->nonRtSetSample( buf );
cout << "Worker: loadSample() " << path << " size: " << infile.frames() << endl;
if ( infile.frames() > 0 )
return ab;
return 0;
}
void DiskReader::readSession( std::string path )
{
cout << "DiskReader::readSession() " << path << endl;
@ -140,7 +165,7 @@ void DiskReader::readGrid()
#endif
// load it
AudioBuffer* ab = Worker::loadSample( sampleFilePath.str() );
AudioBuffer* ab = loadSample( sampleFilePath.str() );
EventLooperLoad e = EventLooperLoad( t, s, ab );
writeToDspRingbuffer( &e );

View file

@ -25,6 +25,10 @@ class DiskReader
public:
DiskReader();
/// loads a sample into a new AudioBuffer, returning the buffer
AudioBuffer* loadSample( std::string path );
/// reads a session from disk, parsing and restoring state
void readSession( std::string path );
private:

View file

@ -10,9 +10,10 @@
#include <sys/stat.h>
#include "gui.hxx"
#include "worker.hxx"
#include "gmastertrack.hxx"
#include <sndfile.hh>
extern Gui* gui;
using namespace std;
@ -59,7 +60,10 @@ void DiskWriter::writeAudioBuffer(int track, int scene, AudioBuffer* ab )
// or alternatively t_<track>_s_<scene>.wav
stringstream path;
path << sessionPath << "/" << sessionName << "/samples/" << filename.str();
Worker::writeSample( path.str(), ab );
SndfileHandle outfile( path.str(), SFM_WRITE, SF_FORMAT_WAV | SF_FORMAT_FLOAT, 1, 44100);
cout << "Worker::writeSample() " << path << " size: " << ab->getData().size() << endl;
outfile.write( &ab->getData()[0], ab->getData().size() );
// de allocate the AudioBuffer
delete ab;
@ -139,7 +143,7 @@ void DiskWriter::writeSession( std::string path, std::string sessionName )
cJSON_AddItemToArray( clips, clip );
// replace blank string if clip exists
for(int i = 0; i < clipData.size(); i++)
for(unsigned int i = 0; i < clipData.size(); i++)
{
if ( clipData.at(i).track == t &&
clipData.at(i).scene == s )

View file

@ -15,9 +15,9 @@
#include "avtk/avtk_reverb.h"
#include "avtk/avtk_background.h"
#include "avtk/avtk_light_button.h"
#include "avtk/avtk_clip_selector.h"
#include "avtk/avtk_sidechain_gain.h"
#include "avtk/clipselector.hxx"
#include "eventhandler.hxx"

View file

@ -15,12 +15,11 @@
#include "avtk/avtk_button.h"
#include "avtk/avtk_background.h"
#include "avtk/avtk_light_button.h"
#include "avtk/avtk_clip_selector.h"
#include "avtk/avtk_radial_status.h"
#include "avtk/clipselector.hxx"
#include "config.hxx"
#include "worker.hxx"
#include "audiobuffer.hxx"
#include "eventhandler.hxx"

View file

@ -6,7 +6,6 @@
#include "jack.hxx"
#include "audiobuffer.hxx"
#include "worker.hxx"
#include <FL/fl_ask.H>
@ -23,19 +22,6 @@ using namespace std;
extern Gui* gui;
void luppp_tooltip(std::string s)
{
return;
//gui->setTooltip(s);
}
void Gui::setTooltip( std::string s )
{
tooltip = s;
tooltipLabel->label( tooltip.c_str() );
}
void close_cb(Fl_Widget*o, void*) {
if ((Fl::event() == FL_KEYDOWN || Fl::event() == FL_SHORTCUT)
&& Fl::event_key() == FL_Escape)
@ -102,6 +88,34 @@ static void gui_header_callback(Fl_Widget *w, void *data)
}
}
void Gui::selectLoadSample( int track, int scene )
{
// FIXME: refactor
string path;
Fl_Native_File_Chooser fnfc;
fnfc.title("Pick a file");
fnfc.type(Fl_Native_File_Chooser::BROWSE_FILE);
//fnfc.filter("Wav\t*.wav");
fnfc.directory( getenv("HOME") ); // 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 directory: %s\n", fnfc.filename());
// update path and load it
path = fnfc.filename();
break;
}
if ( strcmp( path.c_str(), "" ) == 0 )
return;
AudioBuffer* ab = diskReader->loadSample( path );
EventLooperLoad e = EventLooperLoad( track, scene, ab );
writeToDspRingbuffer( &e );
}
Gui::Gui() :
window(1110,650),
diskReader( new DiskReader ),

View file

@ -30,8 +30,7 @@ class Gui
DiskWriter* getDiskWriter(){return diskWriter;}
DiskReader* getDiskReader(){return diskReader;}
// for pushing strings to tooltip area
void setTooltip( std::string s );
void selectLoadSample( int track, int clip );
private:
Fl_Double_Window window;

View file

@ -1,52 +0,0 @@
#ifndef LUPPP_WORKER_H
#define LUPPP_WORKER_H
// Library
#include <string>
#include <sndfile.hh>
#include "audiobuffer.hxx"
using namespace std;
namespace Worker
{
/// loads a sample into a new AudioBuffer, returning the buffer
static AudioBuffer* loadSample( string path )
{
SndfileHandle infile( path, SFM_READ );
AudioBuffer* ab = new AudioBuffer();
std::vector<float> buf( infile.frames(), 0.f );
infile.read( &buf[0] , infile.frames() );
// read data from file
ab->setBeats(4);
ab->nonRtSetSample( buf );
cout << "Worker: loadSample() " << path << " size: " << infile.frames() << endl;
if ( infile.frames() > 0 )
return ab;
return 0;
}
static int writeSample( string path, AudioBuffer* ab )
{
SndfileHandle outfile( path, SFM_WRITE, SF_FORMAT_WAV | SF_FORMAT_FLOAT, 1, 44100);
cout << "Worker::writeSample() " << path << " size: " << ab->getData().size() << endl;
outfile.write( &ab->getData()[0], ab->getData().size() );
}
}
#endif // LUPPP_WORKER_H