2013-09-03 20:35:43 +02:00
|
|
|
|
|
|
|
#include "diskwriter.hxx"
|
|
|
|
|
2013-09-05 13:29:00 +02:00
|
|
|
#include "config.hxx"
|
|
|
|
|
2013-09-03 23:04:03 +02:00
|
|
|
#include <sstream>
|
|
|
|
#include <fstream>
|
2013-09-03 21:06:11 +02:00
|
|
|
#include <iostream>
|
2013-09-03 23:04:03 +02:00
|
|
|
#include <cstdlib>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
|
2013-09-05 15:28:11 +02:00
|
|
|
#include "gui.hxx"
|
|
|
|
#include "gmastertrack.hxx"
|
|
|
|
|
2013-09-05 19:33:16 +02:00
|
|
|
#include <sndfile.hh>
|
|
|
|
|
2013-09-05 15:28:11 +02:00
|
|
|
extern Gui* gui;
|
2013-09-03 21:06:11 +02:00
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
|
2013-09-03 20:35:43 +02:00
|
|
|
DiskWriter::DiskWriter()
|
|
|
|
{
|
2013-09-18 10:34:49 +02:00
|
|
|
session = cJSON_CreateObject();
|
|
|
|
sample = cJSON_CreateObject();
|
2013-09-18 12:46:25 +02:00
|
|
|
|
|
|
|
sessionPath = getenv("HOME");
|
|
|
|
sessionName = "lupppSession";
|
|
|
|
|
2013-09-03 20:35:43 +02:00
|
|
|
};
|
|
|
|
|
2013-09-03 23:04:03 +02:00
|
|
|
void DiskWriter::initialize(std::string path, std::string name )
|
2013-09-03 20:35:43 +02:00
|
|
|
{
|
2013-09-18 12:46:25 +02:00
|
|
|
sessionPath = path;
|
2013-09-18 10:34:49 +02:00
|
|
|
sessionName = name;
|
2013-09-03 23:04:03 +02:00
|
|
|
}
|
2013-09-03 21:06:11 +02:00
|
|
|
|
2013-09-18 12:46:25 +02:00
|
|
|
std::string DiskWriter::getLastSaveName()
|
|
|
|
{
|
|
|
|
return sessionName;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string DiskWriter::getLastSavePath()
|
|
|
|
{
|
|
|
|
return sessionPath;
|
|
|
|
}
|
|
|
|
|
2013-09-16 11:17:27 +02:00
|
|
|
int DiskWriter::writeAudioBuffer(int track, int scene, AudioBuffer* ab )
|
2013-09-03 23:04:03 +02:00
|
|
|
{
|
2013-09-03 23:26:16 +02:00
|
|
|
// get the filename
|
|
|
|
stringstream filename;
|
|
|
|
filename << "t_" << track << "_s_" << scene << ".wav";
|
|
|
|
|
2013-09-05 13:29:00 +02:00
|
|
|
// store the clip in clipData, we will write the session JSON for it in writeSession
|
|
|
|
clipData.push_back( ClipData( track, scene, filename.str() ) );
|
2013-09-03 21:06:11 +02:00
|
|
|
|
2013-09-03 23:04:03 +02:00
|
|
|
// add the AudioBuffer metadata to the sample JSON node
|
|
|
|
cJSON* sampleClip = cJSON_CreateObject();
|
2013-09-04 23:56:16 +02:00
|
|
|
cJSON_AddItemToObject(sample, filename.str().c_str(), sampleClip );
|
2013-09-03 23:04:03 +02:00
|
|
|
cJSON_AddNumberToObject(sampleClip,"beats", ab->getBeats() );
|
|
|
|
|
2013-09-03 20:35:43 +02:00
|
|
|
// write the AudioBuffer contents to <path>/samples/ as <name>.wav
|
|
|
|
// or alternatively t_<track>_s_<scene>.wav
|
2013-09-05 23:35:48 +02:00
|
|
|
|
|
|
|
// FIXME: trim trailing / sessionPath from session path if its there
|
|
|
|
|
2013-09-03 23:04:03 +02:00
|
|
|
stringstream path;
|
2013-09-18 10:34:49 +02:00
|
|
|
path << sessionPath << "/" << sessionName << "/samples/" << filename.str();
|
2013-09-05 19:33:16 +02:00
|
|
|
|
|
|
|
SndfileHandle outfile( path.str(), SFM_WRITE, SF_FORMAT_WAV | SF_FORMAT_FLOAT, 1, 44100);
|
2013-09-06 00:07:19 +02:00
|
|
|
cout << "Worker::writeSample() " << path.str() << " size: " << ab->getAudioFrames() << endl;
|
|
|
|
|
|
|
|
// FIXME: the size of the buffer is bigger than the audio contained in it:
|
|
|
|
// calculate the length that needs saving using getBeats() * framesPerBeat
|
2013-09-17 13:07:25 +02:00
|
|
|
if ( ab->getAudioFrames() > 0 )
|
|
|
|
outfile.write( &ab->getData()[0], ab->getAudioFrames() );
|
|
|
|
else
|
|
|
|
{
|
|
|
|
LUPPP_WARN("%s","Sample has zero samples");
|
|
|
|
}
|
2013-09-16 11:17:27 +02:00
|
|
|
|
|
|
|
return LUPPP_RETURN_OK;
|
2013-09-03 20:35:43 +02:00
|
|
|
}
|
|
|
|
|
2013-09-05 15:28:11 +02:00
|
|
|
void DiskWriter::writeMaster()
|
|
|
|
{
|
|
|
|
// Master track stuff
|
|
|
|
cJSON* masterTrack = cJSON_CreateObject();
|
|
|
|
cJSON_AddItemToObject(session, "master", masterTrack );
|
|
|
|
GMasterTrack* master = gui->getMasterTrack();
|
|
|
|
|
|
|
|
cJSON_AddNumberToObject( masterTrack, "fader", master->getVolume()->value() );
|
2013-09-11 00:09:45 +02:00
|
|
|
cJSON_AddNumberToObject( masterTrack, "bpm", gui->getMasterTrack()->getBpm() );
|
2013-09-17 14:11:11 +02:00
|
|
|
// TODO add samplerate to session JSON
|
|
|
|
//cJSON_AddNumberToObject( masterTrack, "samplerate", gui->getMasterTrack()->getBpm() );
|
2013-09-05 15:28:11 +02:00
|
|
|
|
|
|
|
// 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 );
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2013-09-18 10:34:49 +02:00
|
|
|
int DiskWriter::writeSession()
|
2013-09-03 20:35:43 +02:00
|
|
|
{
|
2013-09-05 15:05:36 +02:00
|
|
|
// add session metadata
|
|
|
|
cJSON_AddItemToObject ( session, "session", cJSON_CreateString( sessionName.c_str() ));
|
2013-09-05 23:35:48 +02:00
|
|
|
|
2013-09-05 15:05:36 +02:00
|
|
|
cJSON_AddNumberToObject( session, "version_major", 1 );
|
|
|
|
cJSON_AddNumberToObject( session, "version_minor", 0 );
|
|
|
|
cJSON_AddNumberToObject( session, "version_patch", 0 );
|
|
|
|
|
|
|
|
|
2013-09-11 00:09:45 +02:00
|
|
|
writeMaster();
|
2013-09-05 15:05:36 +02:00
|
|
|
|
|
|
|
|
2013-09-05 13:29:00 +02:00
|
|
|
// add JSON "tracks" array
|
2013-09-05 14:01:08 +02:00
|
|
|
cJSON* trackArray = cJSON_CreateArray();
|
2013-09-05 13:29:00 +02:00
|
|
|
cJSON_AddItemToObject(session, "tracks", trackArray );
|
|
|
|
|
|
|
|
// write tracks into JSON tracks array
|
|
|
|
for(int t = 0; t < NTRACKS; t++)
|
|
|
|
{
|
|
|
|
cJSON* track = cJSON_CreateObject();
|
2013-09-05 14:01:08 +02:00
|
|
|
cJSON_AddItemToArray( trackArray, track );
|
2013-09-05 13:29:00 +02:00
|
|
|
|
|
|
|
// add track metadata: volumes, sends etc
|
|
|
|
cJSON_AddNumberToObject( track, "ID", t );
|
2013-09-11 00:57:47 +02:00
|
|
|
cJSON_AddStringToObject( track, "name", gui->getTrack(t)->bg.getLabel() );
|
2013-09-06 01:39:01 +02:00
|
|
|
|
|
|
|
cJSON_AddNumberToObject( track, "fader", gui->getTrack(t)->getVolume()->value() );
|
|
|
|
cJSON_AddNumberToObject( track, "side", gui->getTrack(t)->side.value() );
|
|
|
|
cJSON_AddNumberToObject( track, "post", gui->getTrack(t)->post.value() );
|
|
|
|
cJSON_AddNumberToObject( track, "reverb", gui->getTrack(t)->rev.value() );
|
2013-09-05 13:29:00 +02:00
|
|
|
|
|
|
|
// write clipData vector into clip placeholder
|
|
|
|
cJSON* clips = cJSON_CreateArray();
|
|
|
|
cJSON_AddItemToObject( track, "clips", clips );
|
2013-09-05 14:01:08 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
2013-09-05 13:29:00 +02:00
|
|
|
for(int s = 0; s < NSCENES; s++)
|
|
|
|
{
|
2013-09-05 14:01:08 +02:00
|
|
|
// add empty string to array
|
|
|
|
cJSON* clip = cJSON_CreateString( "" );
|
|
|
|
cJSON_AddItemToArray( clips, clip );
|
|
|
|
|
|
|
|
// replace blank string if clip exists
|
2013-09-05 19:33:16 +02:00
|
|
|
for(unsigned int i = 0; i < clipData.size(); i++)
|
2013-09-05 13:29:00 +02:00
|
|
|
{
|
|
|
|
if ( clipData.at(i).track == t &&
|
|
|
|
clipData.at(i).scene == s )
|
|
|
|
{
|
2013-09-05 14:01:08 +02:00
|
|
|
cJSON* newClip = cJSON_CreateString( clipData.at(i).name.c_str() );
|
|
|
|
cJSON_ReplaceItemInArray( clips, s, newClip );
|
2013-09-05 13:29:00 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-11 00:09:45 +02:00
|
|
|
}
|
2013-09-05 13:29:00 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-09-03 23:04:03 +02:00
|
|
|
// write session.luppp JSON node to <path>/<sessionName>.luppp
|
|
|
|
stringstream sessionDir;
|
2013-09-18 10:34:49 +02:00
|
|
|
sessionDir << sessionPath << "/" << sessionName;
|
2013-09-03 23:04:03 +02:00
|
|
|
int sessionDirError = mkdir( sessionDir.str().c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH );
|
|
|
|
if ( sessionDirError )
|
|
|
|
{
|
|
|
|
// handle by using different filename?
|
|
|
|
}
|
2013-09-03 20:35:43 +02:00
|
|
|
|
2013-09-03 23:04:03 +02:00
|
|
|
stringstream sampleDir;
|
|
|
|
sampleDir << sessionDir.str() << "/samples";
|
|
|
|
int sampleDirError = mkdir( sampleDir.str().c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH );
|
|
|
|
|
|
|
|
stringstream sessionLuppp;
|
2013-09-04 23:32:46 +02:00
|
|
|
sessionLuppp << sessionDir.str() << "/session.luppp";
|
2013-09-03 23:04:03 +02:00
|
|
|
|
|
|
|
//cout << "Session dir: " << sessionDir.str() << "\n" << "Sample dir : " << sampleDir.str() << endl;
|
|
|
|
ofstream sessionFile;
|
|
|
|
sessionFile.open ( sessionLuppp.str().c_str() );
|
|
|
|
sessionFile << cJSON_Print( session );
|
|
|
|
sessionFile.close();
|
|
|
|
|
|
|
|
// write the sample JSON node to <path>/samples/sample.cfg
|
|
|
|
stringstream sampleConfig;
|
|
|
|
sampleConfig << sampleDir.str() << "/sample.cfg";
|
|
|
|
|
|
|
|
ofstream sampleFile;
|
|
|
|
sampleFile.open ( sampleConfig.str().c_str() );
|
|
|
|
sampleFile << cJSON_Print( sample );
|
|
|
|
sampleFile.close();
|
2013-09-03 20:35:43 +02:00
|
|
|
|
2013-09-05 13:29:00 +02:00
|
|
|
// clear the clipData, clean page for next save
|
|
|
|
clipData.clear();
|
2013-09-16 11:17:27 +02:00
|
|
|
|
|
|
|
return LUPPP_RETURN_OK;
|
2013-09-03 20:35:43 +02:00
|
|
|
}
|