-Updated Save to work with LooperClip, added Save::done() static function for counting finished saves, and knowing when to flush metadata to disk.

This commit is contained in:
Harry van Haaren 2013-09-03 20:06:11 +01:00
parent 07a6aa7d6d
commit 05984fbc9b
13 changed files with 107 additions and 46 deletions

View file

@ -15,6 +15,8 @@
// Logic : Warning NON RT!
#define DEBUG_LOGIC 1
// Saving state
#define DEBUG_SAVE 1
/// General Options
#define NTRACKS 8

View file

@ -1,13 +1,28 @@
#include "diskwriter.hxx"
#include <iostream>
using namespace std;
DiskWriter::DiskWriter()
{
session = cJSON_CreateObject();
audioConfig = cJSON_CreateObject();
};
void DiskWriter::writeAudioBuffer(int track, int scene, AudioBuffer* ab )
{
// add the track / scene / name combo to audioConfig JSON node
// add the track / scene / name combo to session JSON node
cJSON* clip = cJSON_CreateObject();
cJSON_AddItemToObject(session, "clip", clip );
cJSON_AddNumberToObject(clip,"track", track);
cJSON_AddNumberToObject(clip,"scene", scene);
cJSON_AddStringToObject(clip,"file", "filenameHere.wav");
// write the AudioBuffer contents to <path>/samples/ as <name>.wav
// or alternatively t_<track>_s_<scene>.wav
@ -20,6 +35,13 @@ void DiskWriter::writeSession( std::string path, std::string sessionName )
// write session.luppp JSON node to <path>/<sessionName>.luppp
cJSON_AddItemToObject ( session, "session", cJSON_CreateString( sessionName.c_str() ));
cJSON_AddNumberToObject( session, "version_major", 1 );
cJSON_AddNumberToObject( session, "version_minor", 0 );
cJSON_AddNumberToObject( session, "version_patch", 0 );
cJSON_AddNumberToObject( session, "bpm", 120 );
char* out = cJSON_Print( session );
cout << out << endl;
}

View file

@ -4,6 +4,8 @@
#include <string>
#include "cjson/cJSON.h"
class AudioBuffer;
/** DiskWriter
@ -22,7 +24,8 @@ class DiskWriter
void writeSession( std::string path, std::string sessionName );
private:
cJSON* session;
cJSON* audioConfig;
};
#endif // LUPPP_DISK_WRITER_H

View file

@ -31,6 +31,7 @@ namespace Event
RECORD,
SAVE, // save action
SAVE_FINISH,// save action finished, flush metadata to disk
SAVE_BUFFER,// save an individual AudioBuffer* to disk
REQUEST_SAVE_BUFFER, // gets an audioBuffer of a certain size
@ -116,6 +117,15 @@ class EventSave : public EventBase
EventSave(){};
};
class EventSaveFinish : public EventBase
{
public:
int type() { return int(SAVE_FINISH); }
uint32_t size() { return sizeof(EventSaveFinish); }
EventSaveFinish(){};
};
class EventGridEvent : public EventBase
{
public:

View file

@ -99,11 +99,20 @@ void handleGuiEvents()
if ( availableRead >= sizeof(EventSaveBuffer) ) {
EventSaveBuffer ev;
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventSaveBuffer) );
// stream buffer to disk, add to JSON
#ifdef DEBUG_SAVE
cout << "EventSaveBuffer: " << ev.track << " " << ev.scene << " " << ev.ab->getID() << endl;
#endif
gui->getDiskWriter()->writeAudioBuffer( ev.track, ev.scene, ev.ab );
} break; }
case Event::SAVE_FINISH: {
if ( availableRead >= sizeof(EventSaveFinish) ) {
EventSaveFinish ev;
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventSaveFinish) );
#ifdef DEBUG_SAVE
cout << "EventSaveFinish!" << endl;
#endif
gui->getDiskWriter()->writeSession("path", "sessionName");
} break; }

View file

@ -49,7 +49,8 @@ static void gui_static_read_rb(void* inst)
}
Gui::Gui() :
window(1110,650)
window(1110,650),
diskWriter( new DiskWriter )
{
window.color(FL_BLACK);
window.label("Luppp");
@ -91,8 +92,6 @@ int Gui::show()
gui_static_read_rb( this );
Worker::save("dummyPath", "dummyName");
return Fl::run();
}

View file

@ -9,6 +9,7 @@
#include "config.hxx"
#include "gtrack.hxx"
#include "gunittrack.hxx"
#include "diskwriter.hxx"
#include "gmastertrack.hxx"
#include <vector>
@ -24,6 +25,8 @@ class Gui
GTrack* getTrack(int id);
GMasterTrack* getMasterTrack(){return master;}
DiskWriter* getDiskWriter(){return diskWriter;}
// for pushing strings to tooltip area
void setTooltip( std::string s );
@ -31,6 +34,8 @@ class Gui
Fl_Double_Window window;
Fl_Box* box;
DiskWriter* diskWriter;
GMasterTrack* master;
vector<GTrack*> tracks;

View file

@ -44,7 +44,10 @@ void LooperClip::save()
EventRequestSaveBuffer e2( track, scene, _buffer->getData().size() );
writeToGuiRingbuffer( &e2 );
}
else
{
SaveAble::done();
}
}
/// loads a sample: eg from disk, unloading current sample if necessary
@ -104,6 +107,8 @@ void LooperClip::recieveSaveBuffer( AudioBuffer* saveBuffer )
EventSaveBuffer e ( track, scene, saveBuffer );
writeToGuiRingbuffer( &e );
SaveAble::done();
}

View file

@ -2,6 +2,8 @@
#include "save.hxx"
#include <iostream>
#include "../event.hxx"
#include "../eventhandler.hxx"
using namespace std;
@ -23,4 +25,17 @@ void Save::save()
{
saveables.at(i)->save();
}
// now each SaveAble has reqested save state, but not yet *saved* its state.
// we need a way to determine if the saves are flushed.
}
void Save::finish()
{
// trigger the GUI to write the metadata to disk, as each component of the
// engine is done saving
EventSaveFinish e;
writeToGuiRingbuffer( &e );
}

View file

@ -17,8 +17,16 @@ class Save
void save();
/// called when each part is finished, and we can flush the metadata to disk
void finish();
void registerSaveable(SaveAble* s);
int getNumSaveables()
{
return saveables.size();
}
private:
std::vector<SaveAble*> saveables;
};

View file

@ -6,9 +6,21 @@
extern Jack* jack;
int SaveAble::savesDone = 0;
SaveAble::SaveAble()
{
jack->getSave()->registerSaveable( this );
}
void SaveAble::save(){};
void SaveAble::done()
{
savesDone++;
if ( savesDone == jack->getSave()->getNumSaveables() )
{
jack->getSave()->finish();
}
}

View file

@ -18,6 +18,13 @@ class SaveAble
/// 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*
/// its save action. Once each Saveable is done, the final save is OK-ed.
static void done();
private:
static int savesDone;
};
#endif // LUPPP_SAVEABLE_H

View file

@ -9,47 +9,11 @@
#include "audiobuffer.hxx"
#include "cjson/cJSON.h"
using namespace std;
namespace Worker
{
static void save(std::string path, std::string sessionName)
{
cJSON *root = cJSON_CreateObject();
cJSON_AddItemToObject(root, "session", cJSON_CreateString( sessionName.c_str() ));
cJSON_AddNumberToObject( root, "version_major", 1 );
cJSON_AddNumberToObject( root, "version_minor", 0 );
cJSON_AddNumberToObject( root, "version_patch", 0 );
cJSON_AddNumberToObject( root, "bpm", 120 );
for(int t = 0; t < NTRACKS; t++ )
{
cJSON* track = cJSON_CreateObject();
cJSON_AddItemToObject(root, "track", track );
cJSON_AddNumberToObject(track,"ID", t);
for(int s = 0; s < NSCENES; s++ )
{
cJSON* clip = cJSON_CreateObject();
cJSON_AddItemToObject(track, "clip", clip );
cJSON_AddNumberToObject(clip,"ID", s);
cJSON_AddStringToObject(clip,"file", "filenameHere.wav");
}
}
char* out = cJSON_Print(root);
//cout << out << endl;
}
/// loads a sample into a new AudioBuffer, returning the buffer
static AudioBuffer* loadSample( string path )
{