player/client: port to C
Make sure that all code included in the player and client is pure C. This helps on portability.
This commit is contained in:
parent
dc1ab70976
commit
decf843c04
@ -179,11 +179,7 @@
|
|||||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||||
>
|
>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\sync\data.cpp"
|
RelativePath="..\sync\data.c"
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\sync\network.cpp"
|
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
@ -199,7 +195,7 @@
|
|||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\sync\track.cpp"
|
RelativePath="..\sync\track.c"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
@ -237,6 +233,10 @@
|
|||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
|
RelativePath="..\sync\sync.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
RelativePath=".\syncdocument.h"
|
RelativePath=".\syncdocument.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
|||||||
@ -1,7 +1,10 @@
|
|||||||
#include "syncdocument.h"
|
#include "syncdocument.h"
|
||||||
|
#include <string>
|
||||||
|
#include <tchar.h>
|
||||||
|
|
||||||
SyncDocument::~SyncDocument()
|
SyncDocument::~SyncDocument()
|
||||||
{
|
{
|
||||||
|
sync_data_deinit(this);
|
||||||
clearUndoStack();
|
clearUndoStack();
|
||||||
clearRedoStack();
|
clearRedoStack();
|
||||||
}
|
}
|
||||||
@ -33,7 +36,7 @@ bool SyncDocument::load(const std::string &fileName)
|
|||||||
std::string name = attribs->getNamedItem("name")->Gettext();
|
std::string name = attribs->getNamedItem("name")->Gettext();
|
||||||
|
|
||||||
// look up track-name, create it if it doesn't exist
|
// look up track-name, create it if it doesn't exist
|
||||||
int trackIndex = getTrackIndex(name);
|
int trackIndex = sync_find_track(this, name.c_str());
|
||||||
if (0 > trackIndex) trackIndex = int(createTrack(name));
|
if (0 > trackIndex) trackIndex = int(createTrack(name));
|
||||||
|
|
||||||
MSXML2::IXMLDOMNodeListPtr rowNodes = trackNode->GetchildNodes();
|
MSXML2::IXMLDOMNodeListPtr rowNodes = trackNode->GetchildNodes();
|
||||||
@ -48,19 +51,11 @@ bool SyncDocument::load(const std::string &fileName)
|
|||||||
std::string valueString = rowAttribs->getNamedItem("value")->Gettext();
|
std::string valueString = rowAttribs->getNamedItem("value")->Gettext();
|
||||||
std::string interpolationString = rowAttribs->getNamedItem("interpolation")->Gettext();
|
std::string interpolationString = rowAttribs->getNamedItem("interpolation")->Gettext();
|
||||||
|
|
||||||
sync::Track::KeyFrame keyFrame(
|
track_key k;
|
||||||
float(atof(valueString.c_str())),
|
k.row = atoi(rowString.c_str());
|
||||||
sync::Track::KeyFrame::InterpolationType(
|
k.value = float(atof(valueString.c_str()));
|
||||||
atoi(interpolationString.c_str())
|
k.type = key_type(atoi(interpolationString.c_str()));
|
||||||
)
|
multiCmd->addCommand(new InsertCommand(int(trackIndex), k));
|
||||||
);
|
|
||||||
multiCmd->addCommand(
|
|
||||||
new InsertCommand(
|
|
||||||
int(trackIndex),
|
|
||||||
atoi(rowString.c_str()),
|
|
||||||
keyFrame
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -92,22 +87,19 @@ bool SyncDocument::save(const std::string &fileName)
|
|||||||
_snprintf(temp, 256, "%d", getRows());
|
_snprintf(temp, 256, "%d", getRows());
|
||||||
rootNode->setAttribute(_T("rows"), temp);
|
rootNode->setAttribute(_T("rows"), temp);
|
||||||
|
|
||||||
for (size_t i = 0; i < getTrackCount(); ++i)
|
for (size_t i = 0; i < num_tracks; ++i) {
|
||||||
{
|
const sync_track *t = tracks[i];
|
||||||
const sync::Track &track = getTrack(i);
|
|
||||||
|
|
||||||
MSXML2::IXMLDOMElementPtr trackElem = doc->createElement(_T("track"));
|
MSXML2::IXMLDOMElementPtr trackElem = doc->createElement(_T("track"));
|
||||||
trackElem->setAttribute(_T("name"), track.getName().c_str());
|
trackElem->setAttribute(_T("name"), t->name);
|
||||||
|
|
||||||
rootNode->appendChild(doc->createTextNode(_T("\n\t")));
|
rootNode->appendChild(doc->createTextNode(_T("\n\t")));
|
||||||
rootNode->appendChild(trackElem);
|
rootNode->appendChild(trackElem);
|
||||||
|
|
||||||
sync::Track::KeyFrameContainer::const_iterator it;
|
for (int i = 0; i < (int)t->num_keys; ++i) {
|
||||||
for (it = track.keyFramesBegin(); it != track.keyFramesEnd(); ++it)
|
size_t row = t->keys[i].row;
|
||||||
{
|
float value = t->keys[i].value;
|
||||||
size_t row = it->first;
|
char interpolationType = char(t->keys[i].type);
|
||||||
float value = it->second.value;
|
|
||||||
char interpolationType = char(it->second.interpolationType);
|
|
||||||
|
|
||||||
MSXML2::IXMLDOMElementPtr keyElem = doc->createElement(_T("key"));
|
MSXML2::IXMLDOMElementPtr keyElem = doc->createElement(_T("key"));
|
||||||
|
|
||||||
@ -123,9 +115,11 @@ bool SyncDocument::save(const std::string &fileName)
|
|||||||
trackElem->appendChild(doc->createTextNode(_T("\n\t\t")));
|
trackElem->appendChild(doc->createTextNode(_T("\n\t\t")));
|
||||||
trackElem->appendChild(keyElem);
|
trackElem->appendChild(keyElem);
|
||||||
}
|
}
|
||||||
if (0 != track.getKeyFrameCount()) trackElem->appendChild(doc->createTextNode(_T("\n\t")));
|
if (t->num_keys)
|
||||||
|
trackElem->appendChild(doc->createTextNode(_T("\n\t")));
|
||||||
}
|
}
|
||||||
if (0 != getTrackCount()) rootNode->appendChild(doc->createTextNode(_T("\n")));
|
if (0 != num_tracks)
|
||||||
|
rootNode->appendChild(doc->createTextNode(_T("\n")));
|
||||||
|
|
||||||
doc->save(fileName.c_str());
|
doc->save(fileName.c_str());
|
||||||
|
|
||||||
|
|||||||
@ -10,32 +10,92 @@
|
|||||||
#include <list>
|
#include <list>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
class SyncDocument : public sync::Data
|
class NetworkSocket
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SyncDocument() : sync::Data(), clientPaused(true), rows(128), savePointDelta(0), savePointUnreachable(true) {}
|
NetworkSocket() : socket(INVALID_SOCKET) {}
|
||||||
|
explicit NetworkSocket(SOCKET socket) : socket(socket) {}
|
||||||
|
|
||||||
|
bool connected() const
|
||||||
|
{
|
||||||
|
return INVALID_SOCKET != socket;
|
||||||
|
}
|
||||||
|
|
||||||
|
void disconnect()
|
||||||
|
{
|
||||||
|
closesocket(socket);
|
||||||
|
socket = INVALID_SOCKET;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool recv(char *buffer, size_t length, int flags)
|
||||||
|
{
|
||||||
|
if (!connected())
|
||||||
|
return false;
|
||||||
|
int ret = ::recv(socket, buffer, int(length), flags);
|
||||||
|
if (ret != length) {
|
||||||
|
disconnect();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool send(const char *buffer, size_t length, int flags)
|
||||||
|
{
|
||||||
|
if (!connected())
|
||||||
|
return false;
|
||||||
|
int ret = ::send(socket, buffer, int(length), flags);
|
||||||
|
if (ret != length) {
|
||||||
|
disconnect();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool pollRead()
|
||||||
|
{
|
||||||
|
if (!connected())
|
||||||
|
return false;
|
||||||
|
return !!socket_poll(socket);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
SOCKET socket;
|
||||||
|
};
|
||||||
|
|
||||||
|
class SyncDocument : public sync_data
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SyncDocument() : clientPaused(true), rows(128), savePointDelta(0), savePointUnreachable(true)
|
||||||
|
{
|
||||||
|
this->tracks = NULL;
|
||||||
|
this->num_tracks = 0;
|
||||||
|
}
|
||||||
|
|
||||||
~SyncDocument();
|
~SyncDocument();
|
||||||
|
|
||||||
size_t createTrack(const std::basic_string<TCHAR> &name)
|
size_t createTrack(const std::basic_string<TCHAR> &name)
|
||||||
{
|
{
|
||||||
size_t index = sync::Data::createTrack(name);
|
size_t index = sync_create_track(this, name.c_str());
|
||||||
trackOrder.push_back(index);
|
trackOrder.push_back(index);
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sendSetKeyCommand(int track, int row, const sync::Track::KeyFrame &key)
|
void sendSetKeyCommand(int track, const struct track_key &key)
|
||||||
{
|
{
|
||||||
if (!clientSocket.connected()) return;
|
if (!clientSocket.connected()) return;
|
||||||
if (clientRemap.count(track) == 0) return;
|
if (clientRemap.count(track) == 0) return;
|
||||||
track = int(clientRemap[track]);
|
track = int(clientRemap[track]);
|
||||||
|
|
||||||
|
assert(key.type < KEY_TYPE_COUNT);
|
||||||
|
|
||||||
unsigned char cmd = SET_KEY;
|
unsigned char cmd = SET_KEY;
|
||||||
clientSocket.send((char*)&cmd, 1, 0);
|
clientSocket.send((char*)&cmd, 1, 0);
|
||||||
clientSocket.send((char*)&track, sizeof(int), 0);
|
clientSocket.send((char*)&track, sizeof(int), 0);
|
||||||
clientSocket.send((char*)&row, sizeof(int), 0);
|
clientSocket.send((char*)&key.row, sizeof(int), 0);
|
||||||
clientSocket.send((char*)&key.value, sizeof(float), 0);
|
clientSocket.send((char*)&key.value, sizeof(float), 0);
|
||||||
clientSocket.send((char*)&key.interpolationType, 1, 0);
|
clientSocket.send((char*)&key.type, 1, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sendDeleteKeyCommand(int track, int row)
|
void sendDeleteKeyCommand(int track, int row)
|
||||||
@ -86,29 +146,28 @@ public:
|
|||||||
class InsertCommand : public Command
|
class InsertCommand : public Command
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
InsertCommand(int track, int row, const sync::Track::KeyFrame &key) : track(track), row(row), key(key) {}
|
InsertCommand(int track, const track_key &key) : track(track), key(key) {}
|
||||||
~InsertCommand() {}
|
~InsertCommand() {}
|
||||||
|
|
||||||
void exec(SyncDocument *data)
|
void exec(SyncDocument *data)
|
||||||
{
|
{
|
||||||
sync::Track &t = data->getTrack(this->track);
|
sync_track *t = data->tracks[track];
|
||||||
assert(!t.isKeyFrame(row));
|
assert(!is_key_frame(t, key.row));
|
||||||
t.setKeyFrame(row, key);
|
sync_set_key(t, &key);
|
||||||
data->sendSetKeyCommand(track, row, key); // update clients
|
data->sendSetKeyCommand(track, key); // update clients
|
||||||
}
|
}
|
||||||
|
|
||||||
void undo(SyncDocument *data)
|
void undo(SyncDocument *data)
|
||||||
{
|
{
|
||||||
sync::Track &t = data->getTrack(this->track);
|
sync_track *t = data->tracks[track];
|
||||||
assert(t.isKeyFrame(row));
|
assert(is_key_frame(t, key.row));
|
||||||
t.deleteKeyFrame(row);
|
sync_del_key(t, key.row);
|
||||||
|
data->sendDeleteKeyCommand(track, key.row); // update clients
|
||||||
data->sendDeleteKeyCommand(track, row); // update clients
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int track, row;
|
int track;
|
||||||
sync::Track::KeyFrame key;
|
track_key key;
|
||||||
};
|
};
|
||||||
|
|
||||||
class DeleteCommand : public Command
|
class DeleteCommand : public Command
|
||||||
@ -119,62 +178,55 @@ public:
|
|||||||
|
|
||||||
void exec(SyncDocument *data)
|
void exec(SyncDocument *data)
|
||||||
{
|
{
|
||||||
sync::Track &t = data->getTrack(this->track);
|
sync_track *t = data->tracks[track];
|
||||||
assert(t.isKeyFrame(row));
|
int idx = sync_find_key(t, row);
|
||||||
oldKey = *t.getKeyFrame(row);
|
assert(idx >= 0);
|
||||||
t.deleteKeyFrame(row);
|
oldKey = t->keys[idx];
|
||||||
|
sync_del_key(t, row);
|
||||||
data->sendDeleteKeyCommand(track, row); // update clients
|
data->sendDeleteKeyCommand(track, row); // update clients
|
||||||
}
|
}
|
||||||
|
|
||||||
void undo(SyncDocument *data)
|
void undo(SyncDocument *data)
|
||||||
{
|
{
|
||||||
sync::Track &t = data->getTrack(this->track);
|
sync_track *t = data->tracks[track];
|
||||||
assert(!t.isKeyFrame(row));
|
assert(!is_key_frame(t, row));
|
||||||
t.setKeyFrame(row, oldKey);
|
sync_set_key(t, &oldKey);
|
||||||
|
data->sendSetKeyCommand(track, oldKey); // update clients
|
||||||
data->sendSetKeyCommand(track, row, oldKey); // update clients
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int track, row;
|
int track, row;
|
||||||
sync::Track::KeyFrame oldKey;
|
struct track_key oldKey;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class EditCommand : public Command
|
class EditCommand : public Command
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
EditCommand(int track, int row, const sync::Track::KeyFrame &key) : track(track), row(row), key(key) {}
|
EditCommand(int track, const track_key &key) : track(track), key(key) {}
|
||||||
~EditCommand() {}
|
~EditCommand() {}
|
||||||
|
|
||||||
void exec(SyncDocument *data)
|
void exec(SyncDocument *data)
|
||||||
{
|
{
|
||||||
sync::Track &t = data->getTrack(this->track);
|
sync_track *t = data->tracks[track];
|
||||||
|
int idx = sync_find_key(t, key.row);
|
||||||
// store old key
|
assert(idx >= 0);
|
||||||
assert(t.isKeyFrame(row));
|
oldKey = t->keys[idx];
|
||||||
oldKey = *t.getKeyFrame(row);
|
sync_set_key(t, &key);
|
||||||
|
data->sendSetKeyCommand(track, key); // update clients
|
||||||
// update
|
|
||||||
t.setKeyFrame(row, key);
|
|
||||||
|
|
||||||
data->sendSetKeyCommand(track, row, key); // update clients
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void undo(SyncDocument *data)
|
void undo(SyncDocument *data)
|
||||||
{
|
{
|
||||||
sync::Track &t = data->getTrack(this->track);
|
sync_track *t = data->tracks[track];
|
||||||
|
assert(is_key_frame(t, key.row));
|
||||||
assert(t.isKeyFrame(row));
|
sync_set_key(t, &oldKey);
|
||||||
t.setKeyFrame(row, oldKey);
|
data->sendSetKeyCommand(track, oldKey); // update clients
|
||||||
|
|
||||||
data->sendSetKeyCommand(track, row, oldKey); // update clients
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int track, row;
|
int track;
|
||||||
sync::Track::KeyFrame oldKey, key;
|
track_key oldKey, key;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MultiCommand : public Command
|
class MultiCommand : public Command
|
||||||
@ -273,12 +325,12 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Command *getSetKeyFrameCommand(int track, int row, const sync::Track::KeyFrame &key)
|
Command *getSetKeyFrameCommand(int track, const track_key &key)
|
||||||
{
|
{
|
||||||
sync::Track &t = getTrack(track);
|
sync_track *t = tracks[track];
|
||||||
SyncDocument::Command *cmd;
|
SyncDocument::Command *cmd;
|
||||||
if (t.isKeyFrame(row)) cmd = new EditCommand(track, row, key);
|
if (is_key_frame(t, key.row)) cmd = new EditCommand(track, key);
|
||||||
else cmd = new InsertCommand(track, row, key);
|
else cmd = new InsertCommand(track, key);
|
||||||
return cmd;
|
return cmd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -39,6 +39,7 @@ RecentFiles mruFileList(NULL);
|
|||||||
#define WM_SETROWS (WM_USER+1)
|
#define WM_SETROWS (WM_USER+1)
|
||||||
#define WM_BIASSELECTION (WM_USER+2)
|
#define WM_BIASSELECTION (WM_USER+2)
|
||||||
|
|
||||||
|
#include "../sync/sync.h"
|
||||||
#include "../sync/network.h"
|
#include "../sync/network.h"
|
||||||
|
|
||||||
static LRESULT CALLBACK setRowsDialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
static LRESULT CALLBACK setRowsDialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
@ -168,9 +169,12 @@ std::string fileName;
|
|||||||
void fileNew()
|
void fileNew()
|
||||||
{
|
{
|
||||||
// document.purgeUnusedTracks();
|
// document.purgeUnusedTracks();
|
||||||
for (size_t i = 0; i < document.getTrackCount(); ++i)
|
for (size_t i = 0; i < document.num_tracks; ++i)
|
||||||
{
|
{
|
||||||
document.getTrack(i).truncate();
|
sync_track *t = document.tracks[i];
|
||||||
|
free(t->keys);
|
||||||
|
t->keys = NULL;
|
||||||
|
t->num_keys = 0;
|
||||||
}
|
}
|
||||||
setWindowFileName("Untitled");
|
setWindowFileName("Untitled");
|
||||||
fileName.clear();
|
fileName.clear();
|
||||||
@ -452,8 +456,12 @@ static LRESULT CALLBACK mainWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARA
|
|||||||
case WM_CURRVALDIRTY:
|
case WM_CURRVALDIRTY:
|
||||||
{
|
{
|
||||||
TCHAR temp[256];
|
TCHAR temp[256];
|
||||||
if (document.getTrackCount() > 0) _sntprintf_s(temp, 256, _T("%f"), document.getTrack(document.getTrackIndexFromPos(trackView->getEditTrack())).getValue(float(trackView->getEditRow())));
|
if (document.num_tracks > 0) {
|
||||||
else _sntprintf_s(temp, 256, _T("---"));
|
sync_track *t = document.tracks[document.getTrackIndexFromPos(trackView->getEditTrack())];
|
||||||
|
float row = float(trackView->getEditRow());
|
||||||
|
_sntprintf_s(temp, 256, _T("%f"), sync_get_val(t, row));
|
||||||
|
} else
|
||||||
|
_sntprintf_s(temp, 256, _T("---"));
|
||||||
SendMessage(statusBarWin, SB_SETTEXT, 3, (LPARAM)temp);
|
SendMessage(statusBarWin, SB_SETTEXT, 3, (LPARAM)temp);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -484,13 +492,52 @@ static ATOM registerMainWindowClass(HINSTANCE hInstance)
|
|||||||
return RegisterClassEx(&wc);
|
return RegisterClassEx(&wc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
void die(const char *fmt, ...)
|
||||||
|
{
|
||||||
|
char temp[4096];
|
||||||
|
va_list va;
|
||||||
|
va_start(va, fmt);
|
||||||
|
vfprintf(stderr, fmt, va);
|
||||||
|
vsnprintf(temp, sizeof(temp), fmt, va);
|
||||||
|
va_end(va);
|
||||||
|
|
||||||
|
MessageBox(NULL, temp, mainWindowTitle, MB_OK | MB_ICONERROR);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
SOCKET clientConnect(SOCKET serverSocket, sockaddr_in *host)
|
||||||
|
{
|
||||||
|
sockaddr_in hostTemp;
|
||||||
|
int hostSize = sizeof(sockaddr_in);
|
||||||
|
SOCKET clientSocket = accept(serverSocket, (sockaddr*)&hostTemp, &hostSize);
|
||||||
|
if (INVALID_SOCKET == clientSocket) return INVALID_SOCKET;
|
||||||
|
|
||||||
|
const char *expectedGreeting = client_greet;
|
||||||
|
char recievedGreeting[128];
|
||||||
|
|
||||||
|
recv(clientSocket, recievedGreeting, int(strlen(expectedGreeting)), 0);
|
||||||
|
|
||||||
|
if (strncmp(expectedGreeting, recievedGreeting, strlen(expectedGreeting)) != 0)
|
||||||
|
{
|
||||||
|
closesocket(clientSocket);
|
||||||
|
return INVALID_SOCKET;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *greeting = server_greet;
|
||||||
|
send(clientSocket, greeting, int(strlen(greeting)), 0);
|
||||||
|
|
||||||
|
if (NULL != host) *host = hostTemp;
|
||||||
|
return clientSocket;
|
||||||
|
}
|
||||||
|
|
||||||
int _tmain(int argc, _TCHAR* argv[])
|
int _tmain(int argc, _TCHAR* argv[])
|
||||||
{
|
{
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
|
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
|
||||||
_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_DEBUG);
|
/* _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_DEBUG);
|
||||||
_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG);
|
_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG);
|
||||||
_CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG);
|
_CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG); */
|
||||||
// _CrtSetBreakAlloc(254);
|
// _CrtSetBreakAlloc(254);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -511,16 +558,13 @@ int _tmain(int argc, _TCHAR* argv[])
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (false == initNetwork())
|
if (!init_network())
|
||||||
{
|
die("Failed to init network");
|
||||||
fputs("Failed to init WinSock", stderr);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
SOCKET serverSocket = socket( AF_INET, SOCK_STREAM, 0 );
|
SOCKET serverSocket = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
|
|
||||||
struct sockaddr_in sin;
|
struct sockaddr_in sin;
|
||||||
memset( &sin, 0, sizeof sin );
|
memset(&sin, 0, sizeof sin);
|
||||||
|
|
||||||
sin.sin_family = AF_INET;
|
sin.sin_family = AF_INET;
|
||||||
sin.sin_addr.s_addr = INADDR_ANY;
|
sin.sin_addr.s_addr = INADDR_ANY;
|
||||||
@ -528,22 +572,16 @@ int _tmain(int argc, _TCHAR* argv[])
|
|||||||
|
|
||||||
puts("binding...");
|
puts("binding...");
|
||||||
if (SOCKET_ERROR == bind( serverSocket, (struct sockaddr *)&sin, sizeof(sin)))
|
if (SOCKET_ERROR == bind( serverSocket, (struct sockaddr *)&sin, sizeof(sin)))
|
||||||
{
|
die("Could not start server");
|
||||||
MessageBox(NULL, _T("Could not start server"), mainWindowTitle, MB_OK | MB_ICONERROR | MB_SETFOREGROUND);
|
|
||||||
fputs("Coult not start server", stderr);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
puts("listening...");
|
puts("listening...");
|
||||||
while ( listen( serverSocket, SOMAXCONN ) == SOCKET_ERROR );
|
while (listen(serverSocket, SOMAXCONN) == SOCKET_ERROR)
|
||||||
|
; /* nothing */
|
||||||
|
|
||||||
ATOM mainClass = registerMainWindowClass(hInstance);
|
ATOM mainClass = registerMainWindowClass(hInstance);
|
||||||
ATOM trackViewClass = registerTrackViewWindowClass(hInstance);
|
ATOM trackViewClass = registerTrackViewWindowClass(hInstance);
|
||||||
if (!mainClass || !trackViewClass)
|
if (!mainClass || !trackViewClass)
|
||||||
{
|
die("Window Registration Failed!");
|
||||||
MessageBox(NULL, _T("Window Registration Failed!"), mainWindowTitle, MB_OK | MB_ICONERROR | MB_SETFOREGROUND);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
trackView = new TrackView();
|
trackView = new TrackView();
|
||||||
trackView->setDocument(&document);
|
trackView->setDocument(&document);
|
||||||
@ -559,10 +597,7 @@ int _tmain(int argc, _TCHAR* argv[])
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (NULL == hwnd)
|
if (NULL == hwnd)
|
||||||
{
|
die("Window Creation Failed!");
|
||||||
MessageBox(NULL, _T("Window Creation Failed!"), mainWindowTitle, MB_OK | MB_ICONEXCLAMATION | MB_SETFOREGROUND);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
fileNew();
|
fileNew();
|
||||||
|
|
||||||
@ -634,21 +669,15 @@ int _tmain(int argc, _TCHAR* argv[])
|
|||||||
clientSocket.recv(&trackName[0], str_len, 0);
|
clientSocket.recv(&trackName[0], str_len, 0);
|
||||||
|
|
||||||
// find track
|
// find track
|
||||||
int serverIndex = document.getTrackIndex(trackName);
|
int serverIndex = sync_find_track(&document, trackName.c_str());
|
||||||
if (0 > serverIndex) serverIndex = int(document.createTrack(trackName));
|
if (0 > serverIndex) serverIndex = int(document.createTrack(trackName));
|
||||||
|
|
||||||
// setup remap
|
// setup remap
|
||||||
document.clientRemap[serverIndex] = clientIndex;
|
document.clientRemap[serverIndex] = clientIndex;
|
||||||
|
|
||||||
const sync::Track &track = document.getTrack(serverIndex);
|
const sync_track *t = document.tracks[serverIndex];
|
||||||
|
for (int i = 0; i < (int)t->num_keys; ++i)
|
||||||
sync::Track::KeyFrameContainer::const_iterator it;
|
document.sendSetKeyCommand(int(serverIndex), t->keys[i]);
|
||||||
for (it = track.keyFramesBegin(); it != track.keyFramesEnd(); ++it)
|
|
||||||
{
|
|
||||||
int row = int(it->first);
|
|
||||||
const sync::Track::KeyFrame &key = it->second;
|
|
||||||
document.sendSetKeyCommand(int(serverIndex), row, key);
|
|
||||||
}
|
|
||||||
|
|
||||||
InvalidateRect(trackViewWin, NULL, FALSE);
|
InvalidateRect(trackViewWin, NULL, FALSE);
|
||||||
}
|
}
|
||||||
@ -687,7 +716,7 @@ int _tmain(int argc, _TCHAR* argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
closesocket(serverSocket);
|
closesocket(serverSocket);
|
||||||
closeNetwork();
|
close_network();
|
||||||
|
|
||||||
delete trackView;
|
delete trackView;
|
||||||
trackView = NULL;
|
trackView = NULL;
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include "trackview.h"
|
#include "trackview.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <tchar.h>
|
||||||
|
|
||||||
static const TCHAR *trackViewWindowClassName = _T("TrackView");
|
static const TCHAR *trackViewWindowClassName = _T("TrackView");
|
||||||
|
|
||||||
@ -149,37 +150,31 @@ void TrackView::paintTopMargin(HDC hdc, RECT rcTracks)
|
|||||||
|
|
||||||
SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT));
|
SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT));
|
||||||
|
|
||||||
for (int track = startTrack; track < endTrack; ++track)
|
for (int track = startTrack; track < endTrack; ++track) {
|
||||||
{
|
|
||||||
size_t index = doc->getTrackIndexFromPos(track);
|
size_t index = doc->getTrackIndexFromPos(track);
|
||||||
const sync::Track &t = doc->getTrack(index);
|
const sync_track *t = doc->tracks[index];
|
||||||
|
|
||||||
RECT topMargin;
|
RECT topMargin;
|
||||||
|
|
||||||
topMargin.top = 0;
|
topMargin.top = 0;
|
||||||
topMargin.bottom = topMarginHeight;
|
topMargin.bottom = topMarginHeight;
|
||||||
|
|
||||||
topMargin.left = getScreenX(track);
|
topMargin.left = getScreenX(track);
|
||||||
topMargin.right = topMargin.left + trackWidth;
|
topMargin.right = topMargin.left + trackWidth;
|
||||||
|
|
||||||
if (!RectVisible(hdc, &topMargin)) continue;
|
if (!RectVisible(hdc, &topMargin))
|
||||||
|
continue;
|
||||||
|
|
||||||
RECT fillRect = topMargin;
|
RECT fillRect = topMargin;
|
||||||
|
|
||||||
HBRUSH bgBrush = GetSysColorBrush(COLOR_3DFACE);
|
HBRUSH bgBrush = GetSysColorBrush(COLOR_3DFACE);
|
||||||
if (track == editTrack) bgBrush = editBrush;
|
if (track == editTrack)
|
||||||
|
bgBrush = editBrush;
|
||||||
|
|
||||||
DrawEdge(hdc, &fillRect, BDR_RAISEDINNER | BDR_RAISEDOUTER, BF_ADJUST | BF_LEFT | BF_RIGHT | BF_BOTTOM);
|
DrawEdge(hdc, &fillRect, BDR_RAISEDINNER | BDR_RAISEDOUTER, BF_ADJUST | BF_LEFT | BF_RIGHT | BF_BOTTOM);
|
||||||
FillRect(hdc, &fillRect, bgBrush);
|
FillRect(hdc, &fillRect, bgBrush);
|
||||||
|
|
||||||
const std::basic_string<TCHAR> &trackName = t.getName();
|
|
||||||
|
|
||||||
if (doc->clientRemap.count(doc->getTrackIndexFromPos(track)) == 0) SetTextColor(hdc, GetSysColor(COLOR_GRAYTEXT));
|
if (doc->clientRemap.count(doc->getTrackIndexFromPos(track)) == 0) SetTextColor(hdc, GetSysColor(COLOR_GRAYTEXT));
|
||||||
else SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT));
|
else SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT));
|
||||||
TextOut(hdc,
|
TextOut(hdc, fillRect.left, 0, t->name, int(strlen(t->name)));
|
||||||
fillRect.left, 0,
|
|
||||||
trackName.data(), int(trackName.length())
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RECT topRightMargin;
|
RECT topRightMargin;
|
||||||
@ -252,21 +247,21 @@ void TrackView::paintTracks(HDC hdc, RECT rcTracks)
|
|||||||
int startTrack = scrollPosX / trackWidth;
|
int startTrack = scrollPosX / trackWidth;
|
||||||
int endTrack = min(startTrack + windowTracks + 1, int(getTrackCount()));
|
int endTrack = min(startTrack + windowTracks + 1, int(getTrackCount()));
|
||||||
|
|
||||||
for (int track = startTrack; track < endTrack; ++track)
|
for (int track = startTrack; track < endTrack; ++track) {
|
||||||
{
|
const sync_track *t = doc->tracks[doc->getTrackIndexFromPos(track)];
|
||||||
const sync::Track &t = doc->getTrack(doc->getTrackIndexFromPos(track));
|
for (int row = firstRow; row <= lastRow; ++row) {
|
||||||
|
|
||||||
for (int row = firstRow; row <= lastRow; ++row)
|
|
||||||
{
|
|
||||||
RECT patternDataRect;
|
RECT patternDataRect;
|
||||||
patternDataRect.left = getScreenX(track);
|
patternDataRect.left = getScreenX(track);
|
||||||
patternDataRect.right = patternDataRect.left + trackWidth;
|
patternDataRect.right = patternDataRect.left + trackWidth;
|
||||||
patternDataRect.top = getScreenY(row);
|
patternDataRect.top = getScreenY(row);
|
||||||
patternDataRect.bottom = patternDataRect.top + rowHeight;
|
patternDataRect.bottom = patternDataRect.top + rowHeight;
|
||||||
|
|
||||||
if (!RectVisible(hdc, &patternDataRect)) continue;
|
if (!RectVisible(hdc, &patternDataRect))
|
||||||
|
continue;
|
||||||
|
|
||||||
sync::Track::KeyFrame::InterpolationType interpolationType = t.getInterpolationType(row);
|
int idx = sync_find_key(t, row);
|
||||||
|
int fidx = idx >= 0 ? idx : -idx - 2;
|
||||||
|
key_type interpolationType = (fidx >= 0) ? t->keys[fidx].type : KEY_STEP;
|
||||||
bool selected = (track >= selectLeft && track <= selectRight) && (row >= selectTop && row <= selectBottom);
|
bool selected = (track >= selectLeft && track <= selectRight) && (row >= selectTop && row <= selectBottom);
|
||||||
|
|
||||||
HBRUSH baseBrush = bgBaseBrush;
|
HBRUSH baseBrush = bgBaseBrush;
|
||||||
@ -281,53 +276,45 @@ void TrackView::paintTracks(HDC hdc, RECT rcTracks)
|
|||||||
if (row % 8 == 0) bgBrush = darkBrush;
|
if (row % 8 == 0) bgBrush = darkBrush;
|
||||||
|
|
||||||
RECT fillRect = patternDataRect;
|
RECT fillRect = patternDataRect;
|
||||||
// if (row == editRow && track == editTrack) DrawEdge(hdc, &fillRect, BDR_RAISEDINNER | BDR_SUNKENOUTER, BF_ADJUST | BF_TOP | BF_BOTTOM | BF_LEFT | BF_RIGHT);
|
|
||||||
FillRect( hdc, &fillRect, bgBrush);
|
FillRect( hdc, &fillRect, bgBrush);
|
||||||
if (row % 8 == 0)
|
if (row % 8 == 0) {
|
||||||
{
|
|
||||||
MoveToEx(hdc, patternDataRect.left, patternDataRect.top, (LPPOINT) NULL);
|
MoveToEx(hdc, patternDataRect.left, patternDataRect.top, (LPPOINT) NULL);
|
||||||
if (selected) SelectObject(hdc, rowSelectPen);
|
if (selected) SelectObject(hdc, rowSelectPen);
|
||||||
else SelectObject(hdc, rowPen);
|
else SelectObject(hdc, rowPen);
|
||||||
LineTo(hdc, patternDataRect.right, patternDataRect.top);
|
LineTo(hdc, patternDataRect.right, patternDataRect.top);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (interpolationType)
|
switch (interpolationType) {
|
||||||
{
|
case KEY_STEP:
|
||||||
case sync::Track::KeyFrame::IT_LERP:
|
break;
|
||||||
|
case KEY_LINEAR:
|
||||||
SelectObject(hdc, lerpPen);
|
SelectObject(hdc, lerpPen);
|
||||||
break;
|
break;
|
||||||
case sync::Track::KeyFrame::IT_COSINE:
|
case KEY_SMOOTH:
|
||||||
SelectObject(hdc, cosinePen);
|
SelectObject(hdc, cosinePen);
|
||||||
break;
|
break;
|
||||||
case sync::Track::KeyFrame::IT_RAMP:
|
case KEY_RAMP:
|
||||||
SelectObject(hdc, rampPen);
|
SelectObject(hdc, rampPen);
|
||||||
break;
|
break;
|
||||||
case sync::Track::KeyFrame::IT_STEP:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
if (interpolationType != sync::Track::KeyFrame::IT_STEP)
|
if (interpolationType != KEY_STEP) {
|
||||||
{
|
|
||||||
MoveToEx(hdc, patternDataRect.right - 1, patternDataRect.top, (LPPOINT) NULL);
|
MoveToEx(hdc, patternDataRect.right - 1, patternDataRect.top, (LPPOINT) NULL);
|
||||||
LineTo(hdc, patternDataRect.right - 1, patternDataRect.bottom);
|
LineTo(hdc, patternDataRect.right - 1, patternDataRect.bottom);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool drawEditString = false;
|
bool drawEditString = false;
|
||||||
if (row == editRow && track == editTrack)
|
if (row == editRow && track == editTrack) {
|
||||||
{
|
|
||||||
FrameRect(hdc, &fillRect, (HBRUSH)GetStockObject(BLACK_BRUSH));
|
FrameRect(hdc, &fillRect, (HBRUSH)GetStockObject(BLACK_BRUSH));
|
||||||
// DrawFocusRect(hdc, &fillRect);
|
if (editString.size() > 0)
|
||||||
// Rectangle(hdc, fillRect.left, fillRect.top, fillRect.right, fillRect.bottom);
|
drawEditString = true;
|
||||||
if (editString.size() > 0) drawEditString = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool key = t.isKeyFrame(row);
|
|
||||||
|
|
||||||
/* format the text */
|
/* format the text */
|
||||||
if (drawEditString) _sntprintf_s(temp, 256, editString.c_str());
|
if (drawEditString)
|
||||||
else if (!key) _sntprintf_s(temp, 256, _T(" ---"));
|
_sntprintf_s(temp, 256, editString.c_str());
|
||||||
else
|
else if (idx < 0)
|
||||||
{
|
_sntprintf_s(temp, 256, _T(" ---"));
|
||||||
float val = t.getKeyFrame(row)->value;
|
else {
|
||||||
|
float val = t->keys[idx].value;
|
||||||
_sntprintf_s(temp, 256, _T("% .2f"), val);
|
_sntprintf_s(temp, 256, _T("% .2f"), val);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -372,8 +359,8 @@ void TrackView::paintTracks(HDC hdc, RECT rcTracks)
|
|||||||
|
|
||||||
struct CopyEntry
|
struct CopyEntry
|
||||||
{
|
{
|
||||||
int track, row;
|
int track;
|
||||||
sync::Track::KeyFrame keyFrame;
|
track_key keyFrame;
|
||||||
};
|
};
|
||||||
|
|
||||||
void TrackView::editCopy()
|
void TrackView::editCopy()
|
||||||
@ -404,24 +391,17 @@ void TrackView::editCopy()
|
|||||||
size_t cells = columns * rows;
|
size_t cells = columns * rows;
|
||||||
|
|
||||||
std::vector<struct CopyEntry> copyEntries;
|
std::vector<struct CopyEntry> copyEntries;
|
||||||
for (int track = selectLeft; track <= selectRight; ++track)
|
for (int track = selectLeft; track <= selectRight; ++track) {
|
||||||
{
|
|
||||||
const size_t trackIndex = doc->getTrackIndexFromPos(track);
|
const size_t trackIndex = doc->getTrackIndexFromPos(track);
|
||||||
const sync::Track &t = doc->getTrack(trackIndex);
|
const sync_track *t = doc->tracks[trackIndex];
|
||||||
|
|
||||||
for (int row = selectTop; row <= selectBottom; ++row)
|
|
||||||
{
|
|
||||||
int localRow = row - selectTop;
|
|
||||||
if (t.isKeyFrame(row))
|
|
||||||
{
|
|
||||||
const sync::Track::KeyFrame *keyFrame = t.getKeyFrame(row);
|
|
||||||
assert(NULL != keyFrame);
|
|
||||||
|
|
||||||
|
for (int row = selectTop; row <= selectBottom; ++row) {
|
||||||
|
int idx = sync_find_key(t, row);
|
||||||
|
if (idx >= 0) {
|
||||||
CopyEntry ce;
|
CopyEntry ce;
|
||||||
ce.track = track - selectLeft;
|
ce.track = track - selectLeft;
|
||||||
ce.row = localRow;
|
ce.keyFrame = t->keys[idx];
|
||||||
ce.keyFrame = *keyFrame;
|
ce.keyFrame.row -= selectTop;
|
||||||
|
|
||||||
copyEntries.push_back(ce);
|
copyEntries.push_back(ce);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -490,23 +470,18 @@ void TrackView::editPaste()
|
|||||||
memcpy(&buffer_size, clipbuf + 2 * sizeof(int), sizeof(size_t));
|
memcpy(&buffer_size, clipbuf + 2 * sizeof(int), sizeof(size_t));
|
||||||
|
|
||||||
SyncDocument::MultiCommand *multiCmd = new SyncDocument::MultiCommand();
|
SyncDocument::MultiCommand *multiCmd = new SyncDocument::MultiCommand();
|
||||||
for (int t = 0; t < buffer_width; ++t)
|
for (int i = 0; i < buffer_width; ++i) {
|
||||||
{
|
size_t trackPos = editTrack + i;
|
||||||
size_t trackPos = editTrack + t;
|
|
||||||
if (trackPos >= getTrackCount()) continue;
|
if (trackPos >= getTrackCount()) continue;
|
||||||
|
|
||||||
size_t trackIndex = doc->getTrackIndexFromPos(trackPos);
|
size_t trackIndex = doc->getTrackIndexFromPos(trackPos);
|
||||||
const sync::Track &track = doc->getTrack(trackIndex);
|
const sync_track *t = doc->tracks[trackIndex];
|
||||||
|
for (int j = 0; j < buffer_height; ++j) {
|
||||||
for (int r = 0; r < buffer_height; ++r)
|
int row = editRow + j;
|
||||||
{
|
if (is_key_frame(t, row))
|
||||||
int row = editRow + r;
|
|
||||||
if (track.isKeyFrame(row))
|
|
||||||
{
|
|
||||||
multiCmd->addCommand(new SyncDocument::DeleteCommand(int(trackIndex), row));
|
multiCmd->addCommand(new SyncDocument::DeleteCommand(int(trackIndex), row));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
char *src = clipbuf + 2 * sizeof(int) + sizeof(size_t);
|
char *src = clipbuf + 2 * sizeof(int) + sizeof(size_t);
|
||||||
for (int i = 0; i < buffer_size; ++i)
|
for (int i = 0; i < buffer_size; ++i)
|
||||||
@ -517,17 +492,18 @@ void TrackView::editPaste()
|
|||||||
|
|
||||||
assert(ce.track >= 0);
|
assert(ce.track >= 0);
|
||||||
assert(ce.track < buffer_width);
|
assert(ce.track < buffer_width);
|
||||||
assert(ce.row >= 0);
|
assert(ce.keyFrame.row >= 0);
|
||||||
assert(ce.row < buffer_height);
|
assert(ce.keyFrame.row < buffer_height);
|
||||||
|
|
||||||
size_t trackPos = editTrack + ce.track;
|
size_t trackPos = editTrack + ce.track;
|
||||||
if (trackPos < getTrackCount())
|
if (trackPos < getTrackCount())
|
||||||
{
|
{
|
||||||
size_t trackIndex = doc->getTrackIndexFromPos(trackPos);
|
size_t trackIndex = doc->getTrackIndexFromPos(trackPos);
|
||||||
size_t row = editRow + ce.row;
|
track_key key = ce.keyFrame;
|
||||||
|
key.row += editRow;
|
||||||
|
|
||||||
// since we deleted all keyframes in the edit-box already, we can just insert this one.
|
// since we deleted all keyframes in the edit-box already, we can just insert this one.
|
||||||
SyncDocument::Command *cmd = new SyncDocument::InsertCommand(int(trackIndex), int(row), ce.keyFrame);
|
SyncDocument::Command *cmd = new SyncDocument::InsertCommand(int(trackIndex), key);
|
||||||
multiCmd->addCommand(cmd);
|
multiCmd->addCommand(cmd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -769,14 +745,18 @@ void TrackView::editEnterValue()
|
|||||||
if (int(editString.size()) > 0 && editTrack < int(getTrackCount()))
|
if (int(editString.size()) > 0 && editTrack < int(getTrackCount()))
|
||||||
{
|
{
|
||||||
size_t trackIndex = doc->getTrackIndexFromPos(editTrack);
|
size_t trackIndex = doc->getTrackIndexFromPos(editTrack);
|
||||||
sync::Track &t = doc->getTrack(trackIndex);
|
const sync_track *t = doc->tracks[trackIndex];
|
||||||
|
|
||||||
sync::Track::KeyFrame newKey;
|
track_key newKey;
|
||||||
if (t.isKeyFrame(editRow)) newKey = *t.getKeyFrame(editRow); // copy old key
|
newKey.type = KEY_STEP;
|
||||||
|
newKey.row = editRow;
|
||||||
|
int idx = sync_find_key(t, editRow);
|
||||||
|
if (idx >= 0)
|
||||||
|
newKey = t->keys[idx]; // copy old key
|
||||||
newKey.value = float(_tstof(editString.c_str())); // modify value
|
newKey.value = float(_tstof(editString.c_str())); // modify value
|
||||||
editString.clear();
|
editString.clear();
|
||||||
|
|
||||||
SyncDocument::Command *cmd = doc->getSetKeyFrameCommand(int(trackIndex), editRow, newKey);
|
SyncDocument::Command *cmd = doc->getSetKeyFrameCommand(int(trackIndex), newKey);
|
||||||
doc->exec(cmd);
|
doc->exec(cmd);
|
||||||
|
|
||||||
SendMessage(GetParent(getWin()), WM_CURRVALDIRTY, 0, 0);
|
SendMessage(GetParent(getWin()), WM_CURRVALDIRTY, 0, 0);
|
||||||
@ -790,34 +770,23 @@ void TrackView::editToggleInterpolationType()
|
|||||||
SyncDocument *doc = getDocument();
|
SyncDocument *doc = getDocument();
|
||||||
if (NULL == doc) return;
|
if (NULL == doc) return;
|
||||||
|
|
||||||
if (editTrack < int(getTrackCount()))
|
if (editTrack < int(getTrackCount())) {
|
||||||
{
|
|
||||||
size_t trackIndex = doc->getTrackIndexFromPos(editTrack);
|
size_t trackIndex = doc->getTrackIndexFromPos(editTrack);
|
||||||
sync::Track &t = doc->getTrack(trackIndex);
|
const sync_track *t = doc->tracks[trackIndex];
|
||||||
|
|
||||||
// search backwards from editRow for the keyframe to modify
|
int idx = key_idx_floor(t, editRow);
|
||||||
int row = editRow;
|
if (idx < 0) {
|
||||||
for (; row >= 0; --row) if (t.isKeyFrame(row)) break;
|
|
||||||
|
|
||||||
// a negative row means no key was found
|
|
||||||
if (row < 0)
|
|
||||||
{
|
|
||||||
MessageBeep(-1);
|
MessageBeep(-1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// copy old key to new key
|
// copy and modify
|
||||||
const sync::Track::KeyFrame *oldKey = t.getKeyFrame(row);
|
track_key newKey = t->keys[idx];
|
||||||
assert(NULL != oldKey);
|
newKey.type = (enum key_type)
|
||||||
sync::Track::KeyFrame newKey(*oldKey);
|
((newKey.type + 1) % KEY_TYPE_COUNT);
|
||||||
|
|
||||||
// modify interpolation type
|
|
||||||
newKey.interpolationType = sync::Track::KeyFrame::InterpolationType(
|
|
||||||
(int(newKey.interpolationType) + 1) % sync::Track::KeyFrame::IT_COUNT
|
|
||||||
);
|
|
||||||
|
|
||||||
// apply change to data-set
|
// apply change to data-set
|
||||||
SyncDocument::Command *cmd = doc->getSetKeyFrameCommand(int(trackIndex), row, newKey);
|
SyncDocument::Command *cmd = doc->getSetKeyFrameCommand(int(trackIndex), newKey);
|
||||||
doc->exec(cmd);
|
doc->exec(cmd);
|
||||||
|
|
||||||
// update user interface
|
// update user interface
|
||||||
@ -841,15 +810,12 @@ void TrackView::editDelete()
|
|||||||
assert(selectRight < int(getTrackCount()));
|
assert(selectRight < int(getTrackCount()));
|
||||||
|
|
||||||
SyncDocument::MultiCommand *multiCmd = new SyncDocument::MultiCommand();
|
SyncDocument::MultiCommand *multiCmd = new SyncDocument::MultiCommand();
|
||||||
for (int track = selectLeft; track <= selectRight; ++track)
|
for (int track = selectLeft; track <= selectRight; ++track) {
|
||||||
{
|
|
||||||
size_t trackIndex = doc->getTrackIndexFromPos(track);
|
size_t trackIndex = doc->getTrackIndexFromPos(track);
|
||||||
sync::Track &t = doc->getTrack(trackIndex);
|
const sync_track *t = doc->tracks[trackIndex];
|
||||||
|
|
||||||
for (int row = selectTop; row <= selectBottom; ++row)
|
for (int row = selectTop; row <= selectBottom; ++row) {
|
||||||
{
|
if (is_key_frame(t, row)) {
|
||||||
if (t.isKeyFrame(row))
|
|
||||||
{
|
|
||||||
SyncDocument::Command *cmd = new SyncDocument::DeleteCommand(int(trackIndex), row);
|
SyncDocument::Command *cmd = new SyncDocument::DeleteCommand(int(trackIndex), row);
|
||||||
multiCmd->addCommand(cmd);
|
multiCmd->addCommand(cmd);
|
||||||
}
|
}
|
||||||
@ -887,21 +853,19 @@ void TrackView::editBiasValue(float amount)
|
|||||||
}
|
}
|
||||||
|
|
||||||
SyncDocument::MultiCommand *multiCmd = new SyncDocument::MultiCommand();
|
SyncDocument::MultiCommand *multiCmd = new SyncDocument::MultiCommand();
|
||||||
for (int track = selectLeft; track <= selectRight; ++track)
|
for (int track = selectLeft; track <= selectRight; ++track) {
|
||||||
{
|
|
||||||
assert(track < int(getTrackCount()));
|
assert(track < int(getTrackCount()));
|
||||||
size_t trackIndex = doc->getTrackIndexFromPos(track);
|
size_t trackIndex = doc->getTrackIndexFromPos(track);
|
||||||
sync::Track &t = doc->getTrack(trackIndex);
|
const sync_track *t = doc->tracks[trackIndex];
|
||||||
|
|
||||||
for (int row = selectTop; row <= selectBottom; ++row)
|
for (int row = selectTop; row <= selectBottom; ++row) {
|
||||||
{
|
int idx = sync_find_key(t, row);
|
||||||
if (t.isKeyFrame(row))
|
if (idx >= 0) {
|
||||||
{
|
struct track_key k = t->keys[idx]; // copy old key
|
||||||
sync::Track::KeyFrame newKey = *t.getKeyFrame(row); // copy old key
|
k.value += amount; // modify value
|
||||||
newKey.value += amount; // modify value
|
|
||||||
|
|
||||||
// add sub-command
|
// add sub-command
|
||||||
SyncDocument::Command *cmd = doc->getSetKeyFrameCommand(int(trackIndex), row, newKey);
|
SyncDocument::Command *cmd = doc->getSetKeyFrameCommand(int(trackIndex), k);
|
||||||
multiCmd->addCommand(cmd);
|
multiCmd->addCommand(cmd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,29 +9,70 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include "../sync/device.h"
|
#include <string>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#include "../sync/sync.h"
|
||||||
#include "bass.h"
|
#include "bass.h"
|
||||||
|
|
||||||
class BassTimer : public sync::Timer
|
const float bpm = 150.0f; /* beats per minute */
|
||||||
{
|
const int rpb = 8; /* rows per beat */
|
||||||
public:
|
const double row_rate = (double(bpm) / 60) * rpb;
|
||||||
BassTimer(HSTREAM stream, float bpm, int rowsPerBeat) : stream(stream)
|
|
||||||
{
|
|
||||||
rowRate = (double(bpm) / 60) * rowsPerBeat;
|
|
||||||
}
|
|
||||||
|
|
||||||
// BASS hooks
|
double bass_get_row(HSTREAM h)
|
||||||
void pause() { BASS_ChannelPause(stream); }
|
{
|
||||||
void play() { BASS_ChannelPlay(stream, false); }
|
QWORD pos = BASS_ChannelGetPosition(h, BASS_POS_BYTE);
|
||||||
float getTime() { return float(BASS_ChannelBytes2Seconds(stream, BASS_ChannelGetPosition(stream, BASS_POS_BYTE))); }
|
double time = BASS_ChannelBytes2Seconds(h, pos);
|
||||||
float getRow() { return float(getTime() * rowRate); }
|
return time * row_rate;
|
||||||
void setRow(float row) { BASS_ChannelSetPosition(stream, BASS_ChannelSeconds2Bytes(stream, float(row / rowRate)), BASS_POS_BYTE); }
|
}
|
||||||
bool isPlaying() { return (BASS_ChannelIsActive(stream) == BASS_ACTIVE_PLAYING); }
|
|
||||||
private:
|
#ifndef SYNC_PLAYER
|
||||||
HSTREAM stream;
|
|
||||||
double rowRate;
|
void bass_pause(void *d, int flag)
|
||||||
|
{
|
||||||
|
if (flag)
|
||||||
|
BASS_ChannelPause((HSTREAM)d);
|
||||||
|
else
|
||||||
|
BASS_ChannelPlay((HSTREAM)d, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bass_set_row(void *d, int row)
|
||||||
|
{
|
||||||
|
QWORD pos = BASS_ChannelSeconds2Bytes((HSTREAM)d, row / row_rate);
|
||||||
|
BASS_ChannelSetPosition((HSTREAM)d, pos, BASS_POS_BYTE);
|
||||||
|
}
|
||||||
|
|
||||||
|
int bass_is_playing(void *d)
|
||||||
|
{
|
||||||
|
return BASS_ChannelIsActive((HSTREAM)d) == BASS_ACTIVE_PLAYING;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sync_cb bass_cb = {
|
||||||
|
bass_pause,
|
||||||
|
bass_set_row,
|
||||||
|
bass_is_playing
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif /* !defined(SYNC_PLAYER) */
|
||||||
|
|
||||||
|
void die(const char *fmt, ...)
|
||||||
|
{
|
||||||
|
char temp[4096];
|
||||||
|
va_list va;
|
||||||
|
va_start(va, fmt);
|
||||||
|
vfprintf(stderr, fmt, va);
|
||||||
|
vsnprintf(temp, sizeof(temp), fmt, va);
|
||||||
|
va_end(va);
|
||||||
|
|
||||||
|
#ifdef _CONSOLE
|
||||||
|
fprintf(stderr, "*** error: %s\n", temp);
|
||||||
|
#else
|
||||||
|
MessageBox(NULL, temp, mainWindowTitle, MB_OK | MB_ICONERROR);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
#define WINDOWED 1
|
#define WINDOWED 1
|
||||||
const unsigned int width = 800;
|
const unsigned int width = 800;
|
||||||
const unsigned int height = 600;
|
const unsigned int height = 600;
|
||||||
@ -62,21 +103,21 @@ int main(int argc, char *argv[])
|
|||||||
HSTREAM stream = BASS_StreamCreateFile(false, "tune.ogg", 0, 0, BASS_MP3_SETPOS | ((0 == soundDevice) ? BASS_STREAM_DECODE : 0));
|
HSTREAM stream = BASS_StreamCreateFile(false, "tune.ogg", 0, 0, BASS_MP3_SETPOS | ((0 == soundDevice) ? BASS_STREAM_DECODE : 0));
|
||||||
if (!stream) throw std::string("failed to open tune");
|
if (!stream) throw std::string("failed to open tune");
|
||||||
|
|
||||||
// let's just assume 150 BPM (this holds true for the included tune)
|
sync_device *rocket = sync_create_device("sync");
|
||||||
float bpm = 150.0f;
|
if (!rocket)
|
||||||
|
die("something went wrong - failed to connect to host?");
|
||||||
|
|
||||||
// setup timer and construct sync-device
|
#ifndef SYNC_PLAYER
|
||||||
BassTimer timer(stream, bpm, 8);
|
sync_set_callbacks(rocket, &bass_cb, (void *)stream);
|
||||||
std::auto_ptr<sync::Device> syncDevice = std::auto_ptr<sync::Device>(sync::createDevice("sync", timer));
|
#endif
|
||||||
if (NULL == syncDevice.get()) throw std::string("something went wrong - failed to connect to host?");
|
|
||||||
|
|
||||||
// get tracks
|
// get tracks
|
||||||
sync::Track &clearRTrack = syncDevice->getTrack("clear.r");
|
struct sync_track
|
||||||
sync::Track &clearGTrack = syncDevice->getTrack("clear.g");
|
*clearRTrack = sync_get_track(rocket, "clear.r"),
|
||||||
sync::Track &clearBTrack = syncDevice->getTrack("clear.b");
|
*clearGTrack = sync_get_track(rocket, "clear.g"),
|
||||||
|
*clearBTrack = sync_get_track(rocket, "clear.b"),
|
||||||
sync::Track &camRotTrack = syncDevice->getTrack("cam.rot");
|
*camRotTrack = sync_get_track(rocket, "cam.rot"),
|
||||||
sync::Track &camDistTrack = syncDevice->getTrack("cam.dist");
|
*camDistTrack = sync_get_track(rocket, "cam.dist");
|
||||||
|
|
||||||
LPD3DXMESH cubeMesh = NULL;
|
LPD3DXMESH cubeMesh = NULL;
|
||||||
if (FAILED(D3DXCreateBox(
|
if (FAILED(D3DXCreateBox(
|
||||||
@ -88,19 +129,19 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
// let's roll!
|
// let's roll!
|
||||||
BASS_Start();
|
BASS_Start();
|
||||||
timer.play();
|
BASS_ChannelPlay(stream, false);
|
||||||
|
|
||||||
bool done = false;
|
bool done = false;
|
||||||
while (!done)
|
while (!done)
|
||||||
{
|
{
|
||||||
float row = float(timer.getRow());
|
double row = bass_get_row(stream);
|
||||||
if (!syncDevice->update(row)) done = true;
|
sync_update(rocket, row);
|
||||||
|
|
||||||
// setup clear color
|
// setup clear color
|
||||||
D3DXCOLOR clearColor(
|
D3DXCOLOR clearColor(
|
||||||
clearRTrack.getValue(row),
|
sync_get_val(clearRTrack, row),
|
||||||
clearGTrack.getValue(row),
|
sync_get_val(clearGTrack, row),
|
||||||
clearBTrack.getValue(row),
|
sync_get_val(clearBTrack, row),
|
||||||
0.0
|
0.0
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -111,8 +152,8 @@ int main(int argc, char *argv[])
|
|||||||
/* D3DXMATRIX world;
|
/* D3DXMATRIX world;
|
||||||
device->SetTransform(D3DTS_WORLD, &world); */
|
device->SetTransform(D3DTS_WORLD, &world); */
|
||||||
|
|
||||||
float rot = camRotTrack.getValue(row);
|
float rot = sync_get_val(camRotTrack, row);
|
||||||
float dist = camDistTrack.getValue(row);
|
float dist = sync_get_val(camDistTrack, row);
|
||||||
D3DXVECTOR3 eye(sin(rot) * dist, 0, cos(rot) * dist);
|
D3DXVECTOR3 eye(sin(rot) * dist, 0, cos(rot) * dist);
|
||||||
D3DXVECTOR3 at(0, 0, 0);
|
D3DXVECTOR3 at(0, 0, 0);
|
||||||
D3DXVECTOR3 up(0, 1, 0);
|
D3DXVECTOR3 up(0, 1, 0);
|
||||||
@ -147,25 +188,11 @@ int main(int argc, char *argv[])
|
|||||||
device->Release();
|
device->Release();
|
||||||
d3d->Release();
|
d3d->Release();
|
||||||
DestroyWindow(hwnd);
|
DestroyWindow(hwnd);
|
||||||
}
|
} catch (const std::exception &e) {
|
||||||
catch (const std::exception &e)
|
die(e.what());
|
||||||
{
|
} catch (const std::string &str) {
|
||||||
#ifdef _CONSOLE
|
die(str.c_str());
|
||||||
fprintf(stderr, "*** error: %s\n", e.what());
|
|
||||||
#else
|
|
||||||
MessageBox(NULL, e.what(), NULL, MB_OK | MB_ICONERROR | MB_SETFOREGROUND);
|
|
||||||
#endif
|
|
||||||
ret = -1;
|
|
||||||
}
|
|
||||||
catch (const std::string &str)
|
|
||||||
{
|
|
||||||
#ifdef _CONSOLE
|
|
||||||
fprintf(stderr, "*** error: %s\n", str.c_str());
|
|
||||||
#else
|
|
||||||
MessageBox(NULL, e.what(), NULL, MB_OK | MB_ICONERROR | MB_SETFOREGROUND);
|
|
||||||
#endif
|
|
||||||
ret = -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -41,7 +41,7 @@
|
|||||||
<Tool
|
<Tool
|
||||||
Name="VCCLCompilerTool"
|
Name="VCCLCompilerTool"
|
||||||
Optimization="0"
|
Optimization="0"
|
||||||
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
|
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS"
|
||||||
MinimalRebuild="true"
|
MinimalRebuild="true"
|
||||||
BasicRuntimeChecks="3"
|
BasicRuntimeChecks="3"
|
||||||
RuntimeLibrary="1"
|
RuntimeLibrary="1"
|
||||||
@ -117,7 +117,7 @@
|
|||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCCLCompilerTool"
|
Name="VCCLCompilerTool"
|
||||||
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
|
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS"
|
||||||
RuntimeLibrary="2"
|
RuntimeLibrary="2"
|
||||||
UsePrecompiledHeader="0"
|
UsePrecompiledHeader="0"
|
||||||
WarningLevel="3"
|
WarningLevel="3"
|
||||||
@ -191,7 +191,7 @@
|
|||||||
<Tool
|
<Tool
|
||||||
Name="VCCLCompilerTool"
|
Name="VCCLCompilerTool"
|
||||||
Optimization="0"
|
Optimization="0"
|
||||||
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
|
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS"
|
||||||
MinimalRebuild="true"
|
MinimalRebuild="true"
|
||||||
BasicRuntimeChecks="3"
|
BasicRuntimeChecks="3"
|
||||||
RuntimeLibrary="1"
|
RuntimeLibrary="1"
|
||||||
@ -267,7 +267,7 @@
|
|||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCCLCompilerTool"
|
Name="VCCLCompilerTool"
|
||||||
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
|
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS"
|
||||||
RuntimeLibrary="2"
|
RuntimeLibrary="2"
|
||||||
UsePrecompiledHeader="0"
|
UsePrecompiledHeader="0"
|
||||||
WarningLevel="3"
|
WarningLevel="3"
|
||||||
|
|||||||
9
sync/base.h
Normal file
9
sync/base.h
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#ifndef SYNC_BASE_H
|
||||||
|
#define SYNC_BASE_H
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#define inline __inline
|
||||||
|
#define strdup _strdup
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* SYNC_BASE_H */
|
||||||
34
sync/data.c
Normal file
34
sync/data.c
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
/* Copyright (C) 2007-2008 Erik Faye-Lund and Egbert Teeselink
|
||||||
|
* For conditions of distribution and use, see copyright notice in LICENSE.TXT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "data.h"
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
void sync_data_deinit(struct sync_data *d)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < (int)d->num_tracks; ++i) {
|
||||||
|
free(d->tracks[i]->name);
|
||||||
|
free(d->tracks[i]->keys);
|
||||||
|
free(d->tracks[i]);
|
||||||
|
}
|
||||||
|
free(d->tracks);
|
||||||
|
}
|
||||||
|
|
||||||
|
int sync_create_track(struct sync_data *d, const char *name)
|
||||||
|
{
|
||||||
|
struct sync_track *t;
|
||||||
|
assert(sync_find_track(d, name) < 0);
|
||||||
|
|
||||||
|
t = malloc(sizeof(*t));
|
||||||
|
t->name = strdup(name);
|
||||||
|
t->keys = NULL;
|
||||||
|
t->num_keys = 0;
|
||||||
|
|
||||||
|
d->num_tracks++;
|
||||||
|
d->tracks = realloc(d->tracks, sizeof(d->tracks[0]) * d->num_tracks);
|
||||||
|
d->tracks[d->num_tracks - 1] = t;
|
||||||
|
|
||||||
|
return (int)d->num_tracks - 1;
|
||||||
|
}
|
||||||
@ -1,34 +0,0 @@
|
|||||||
/* Copyright (C) 2007-2008 Erik Faye-Lund and Egbert Teeselink
|
|
||||||
* For conditions of distribution and use, see copyright notice in LICENSE.TXT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "data.h"
|
|
||||||
using sync::Data;
|
|
||||||
|
|
||||||
Data::~Data()
|
|
||||||
{
|
|
||||||
for (size_t i = 0; i < tracks.size(); ++i) delete tracks[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t Data::createTrack(const std::basic_string<TCHAR> &name)
|
|
||||||
{
|
|
||||||
assert(0 > getTrackIndex(name));
|
|
||||||
|
|
||||||
// insert new track
|
|
||||||
tracks.push_back(new sync::Track(name));
|
|
||||||
|
|
||||||
assert(tracks.size() > 0);
|
|
||||||
return tracks.size() - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Data::getTrackIndex(const std::basic_string<TCHAR> &name)
|
|
||||||
{
|
|
||||||
// search for track
|
|
||||||
for (size_t index = 0; index < tracks.size(); ++index)
|
|
||||||
{
|
|
||||||
if (name == tracks[index]->getName()) return int(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
// not found
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
80
sync/data.h
80
sync/data.h
@ -1,61 +1,35 @@
|
|||||||
/* Copyright (C) 2007-2008 Erik Faye-Lund and Egbert Teeselink
|
/* Copyright (C) 2007-2010 Erik Faye-Lund and Egbert Teeselink
|
||||||
* For conditions of distribution and use, see copyright notice in LICENSE.TXT
|
* For conditions of distribution and use, see copyright notice in LICENSE.TXT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#ifndef SYNC_DATA_H
|
||||||
|
#define SYNC_DATA_H
|
||||||
#include <string>
|
|
||||||
#include <map>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include <exception>
|
|
||||||
#include <cmath>
|
|
||||||
#include <cassert>
|
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
#include <tchar.h>
|
|
||||||
#else
|
|
||||||
#define TCHAR char
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "track.h"
|
#include "track.h"
|
||||||
|
|
||||||
namespace sync
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct sync_data {
|
||||||
|
struct sync_track **tracks;
|
||||||
|
size_t num_tracks;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline int sync_find_track(struct sync_data *data, const char *name)
|
||||||
{
|
{
|
||||||
class Data
|
int i;
|
||||||
{
|
for (i = 0; i < (int)data->num_tracks; ++i)
|
||||||
public:
|
if (!strcmp(name, data->tracks[i]->name))
|
||||||
~Data();
|
return i;
|
||||||
|
return -1; /* not found */
|
||||||
int
|
|
||||||
getTrackIndex(const std::basic_string<TCHAR> &name);
|
|
||||||
|
|
||||||
size_t
|
|
||||||
createTrack(const std::basic_string<TCHAR> &name);
|
|
||||||
|
|
||||||
Track &
|
|
||||||
getTrack(size_t track)
|
|
||||||
{
|
|
||||||
assert(track < tracks.size());
|
|
||||||
assert(NULL != tracks[track]);
|
|
||||||
return *tracks[track];
|
|
||||||
}
|
|
||||||
|
|
||||||
const Track &
|
|
||||||
getTrack(size_t track) const
|
|
||||||
{
|
|
||||||
assert(track < tracks.size());
|
|
||||||
assert(NULL != tracks[track]);
|
|
||||||
return *tracks[track];
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t
|
|
||||||
getTrackCount() const
|
|
||||||
{
|
|
||||||
return tracks.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
std::vector<Track*> tracks;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sync_data_deinit(struct sync_data *);
|
||||||
|
int sync_create_track(struct sync_data *, const char *);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* SYNC_DATA_H */
|
||||||
|
|||||||
272
sync/device.c
Normal file
272
sync/device.c
Normal file
@ -0,0 +1,272 @@
|
|||||||
|
/* Copyright (C) 2007-2008 Erik Faye-Lund and Egbert Teeselink
|
||||||
|
* For conditions of distribution and use, see copyright notice in LICENSE.TXT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "device.h"
|
||||||
|
#include "sync.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
const char *sync_track_path(const char *base, const char *name)
|
||||||
|
{
|
||||||
|
static char temp[FILENAME_MAX];
|
||||||
|
strncpy(temp, base, sizeof(temp));
|
||||||
|
strncat(temp, "_", sizeof(temp));
|
||||||
|
strncat(temp, name, sizeof(temp));
|
||||||
|
strncat(temp, ".track", sizeof(temp));
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef SYNC_PLAYER
|
||||||
|
|
||||||
|
#ifndef REMOTE_HOST
|
||||||
|
#define REMOTE_HOST "localhost"
|
||||||
|
#endif
|
||||||
|
#define REMOTE_PORT 1338
|
||||||
|
|
||||||
|
static SOCKET server_connect(const char *host, int nport)
|
||||||
|
{
|
||||||
|
struct hostent *he;
|
||||||
|
struct sockaddr_in addr;
|
||||||
|
char greet[128];
|
||||||
|
SOCKET sock;
|
||||||
|
|
||||||
|
if (!init_network())
|
||||||
|
return INVALID_SOCKET;
|
||||||
|
|
||||||
|
he = gethostbyname(host);
|
||||||
|
if (!he)
|
||||||
|
return INVALID_SOCKET;
|
||||||
|
|
||||||
|
addr.sin_family = AF_INET;
|
||||||
|
addr.sin_port = htons(nport);
|
||||||
|
addr.sin_addr.s_addr = ((struct in_addr *)(he->h_addr_list[0]))->s_addr;
|
||||||
|
|
||||||
|
sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
|
connect(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr_in));
|
||||||
|
send(sock, client_greet, (int)strlen(client_greet), 0);
|
||||||
|
|
||||||
|
recv(sock, greet, (int)strlen(server_greet), 0);
|
||||||
|
if (!strncmp(server_greet, greet, strlen(server_greet)))
|
||||||
|
return sock;
|
||||||
|
|
||||||
|
closesocket(sock);
|
||||||
|
return INVALID_SOCKET;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct sync_device *sync_create_device(const char *base)
|
||||||
|
{
|
||||||
|
struct sync_device *d = malloc(sizeof(*d));
|
||||||
|
if (!d)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
d->base = strdup(base);
|
||||||
|
if (!d->base) {
|
||||||
|
free(d);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
d->data.tracks = NULL;
|
||||||
|
d->data.num_tracks = 0;
|
||||||
|
|
||||||
|
#ifndef SYNC_PLAYER
|
||||||
|
d->cb = d->cb_param = NULL;
|
||||||
|
d->row = -1;
|
||||||
|
d->sock = server_connect(REMOTE_HOST, REMOTE_PORT);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef SYNC_PLAYER
|
||||||
|
|
||||||
|
static int load_track_data(struct sync_track *t, const char *path)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
FILE *fp = fopen(path, "rb");
|
||||||
|
if (!fp)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
fread(&t->num_keys, sizeof(size_t), 1, fp);
|
||||||
|
t->keys = malloc(sizeof(struct track_key) * t->num_keys);
|
||||||
|
|
||||||
|
for (i = 0; i < (int)t->num_keys; ++i) {
|
||||||
|
struct track_key *key = t->keys + i;
|
||||||
|
char type;
|
||||||
|
fread(&key->row, sizeof(size_t), 1, fp);
|
||||||
|
fread(&key->value, sizeof(float), 1, fp);
|
||||||
|
fread(&type, sizeof(char), 1, fp);
|
||||||
|
key->type = (enum key_type)type;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sync_update(struct sync_device *d, double row)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
void sync_set_callbacks(struct sync_device *d, struct sync_cb *cb, void *cb_param)
|
||||||
|
{
|
||||||
|
d->cb = cb;
|
||||||
|
d->cb_param = cb_param;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int save_track(const struct sync_track *t, const char *path)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
FILE *fp = fopen(path, "wb");
|
||||||
|
if (!fp)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
fwrite(&t->num_keys, sizeof(size_t), 1, fp);
|
||||||
|
for (i = 0; i < (int)t->num_keys; ++i) {
|
||||||
|
char type = (char)t->keys[i].type;
|
||||||
|
fwrite(&t->keys[i].row, sizeof(int), 1, fp);
|
||||||
|
fwrite(&t->keys[i].value, sizeof(float), 1, fp);
|
||||||
|
fwrite(&type, sizeof(char), 1, fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void save_tracks(const char *base, struct sync_data *data)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < (int)data->num_tracks; ++i) {
|
||||||
|
const struct sync_track *t = data->tracks[i];
|
||||||
|
save_track(t, sync_track_path(base, t->name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int request_track_data(SOCKET sock, const char *name, int idx)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
unsigned char cmd = GET_TRACK;
|
||||||
|
size_t name_len = strlen(name);
|
||||||
|
|
||||||
|
/* send request data */
|
||||||
|
ret = send(sock, (char *)&cmd, 1, 0);
|
||||||
|
ret += send(sock, (char *)&idx, sizeof(int), 0);
|
||||||
|
ret += send(sock, (char *)&name_len, sizeof(size_t), 0);
|
||||||
|
ret += send(sock, name, (int)name_len, 0);
|
||||||
|
|
||||||
|
return ret != 1 + sizeof(size_t) * 2 + name_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int hanle_set_key_cmd(SOCKET sock, struct sync_data *data)
|
||||||
|
{
|
||||||
|
int ret, track;
|
||||||
|
struct track_key key;
|
||||||
|
unsigned char type;
|
||||||
|
|
||||||
|
ret = recv(sock, (char *)&track, sizeof(int), 0);
|
||||||
|
ret += recv(sock, (char *)&key.row, sizeof(int), 0);
|
||||||
|
ret += recv(sock, (char *)&key.value, sizeof(float), 0);
|
||||||
|
ret += recv(sock, (char *)&type, 1, 0);
|
||||||
|
if (ret != sizeof(int) * 2 + sizeof(float) + 1)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
assert(type < KEY_TYPE_COUNT);
|
||||||
|
assert(track < (int)data->num_tracks);
|
||||||
|
|
||||||
|
key.type = (enum key_type)type;
|
||||||
|
sync_set_key(data->tracks[track], &key);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int hanle_del_key_cmd(SOCKET sock, struct sync_data *data)
|
||||||
|
{
|
||||||
|
int ret, track, row;
|
||||||
|
ret = recv(sock, (char *)&track, sizeof(int), 0);
|
||||||
|
ret += recv(sock, (char *)&row, sizeof(int), 0);
|
||||||
|
if (ret != sizeof(int) * 2)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
assert(track < (int)data->num_tracks);
|
||||||
|
|
||||||
|
sync_del_key(data->tracks[track], row);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sync_update(struct sync_device *d, double row)
|
||||||
|
{
|
||||||
|
/* look for new commands */
|
||||||
|
while (d->sock != INVALID_SOCKET && socket_poll(d->sock)) {
|
||||||
|
unsigned char cmd = 0, flag;
|
||||||
|
int err = 1, row;
|
||||||
|
if (!recv(d->sock, (char *)&cmd, 1, 0)) {
|
||||||
|
d->sock = INVALID_SOCKET;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (cmd)
|
||||||
|
{
|
||||||
|
case SET_KEY:
|
||||||
|
err = hanle_set_key_cmd(d->sock, &d->data);
|
||||||
|
break;
|
||||||
|
case DELETE_KEY:
|
||||||
|
err = hanle_del_key_cmd(d->sock, &d->data);
|
||||||
|
break;
|
||||||
|
case SET_ROW:
|
||||||
|
err = recv(d->sock, (char *)&row, sizeof(int), 0) != sizeof(int);
|
||||||
|
if (!err && d->cb && d->cb->set_row)
|
||||||
|
d->cb->set_row(d->cb_param, row);
|
||||||
|
break;
|
||||||
|
case PAUSE:
|
||||||
|
err = recv(d->sock, (char *)&flag, 1, 0) != 1;
|
||||||
|
if (!err && d->cb && d->cb->pause)
|
||||||
|
d->cb->pause(d->cb_param, flag);
|
||||||
|
break;
|
||||||
|
case SAVE_TRACKS:
|
||||||
|
save_tracks(d->base, &d->data);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "unknown cmd: %02x\n", cmd);
|
||||||
|
}
|
||||||
|
if (err) {
|
||||||
|
d->sock = INVALID_SOCKET;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (d->cb && d->cb->is_playing && d->cb->is_playing(d->cb_param)) {
|
||||||
|
int nrow = (int)floor(row);
|
||||||
|
if (d->row != nrow && d->sock != INVALID_SOCKET) {
|
||||||
|
unsigned char cmd = SET_ROW;
|
||||||
|
int ret = send(d->sock, (char*)&cmd, 1, 0);
|
||||||
|
ret += send(d->sock, (char*)&nrow, sizeof(int), 0);
|
||||||
|
if (ret != sizeof(int) + 1)
|
||||||
|
d->sock = INVALID_SOCKET;
|
||||||
|
else
|
||||||
|
d->row = nrow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct sync_track *sync_get_track(struct sync_device *d, const char *name)
|
||||||
|
{
|
||||||
|
struct sync_track *t;
|
||||||
|
int idx = sync_find_track(&d->data, name);
|
||||||
|
if (idx >= 0)
|
||||||
|
return d->data.tracks[idx];
|
||||||
|
|
||||||
|
idx = sync_create_track(&d->data, name);
|
||||||
|
t = d->data.tracks[idx];
|
||||||
|
|
||||||
|
#if SYNC_PLAYER
|
||||||
|
load_track_data(t, sync_track_path(d->base, name));
|
||||||
|
#else
|
||||||
|
request_track_data(d->sock, name, idx);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return t;
|
||||||
|
}
|
||||||
@ -1,16 +0,0 @@
|
|||||||
/* Copyright (C) 2007-2008 Erik Faye-Lund and Egbert Teeselink
|
|
||||||
* For conditions of distribution and use, see copyright notice in LICENSE.TXT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "device.h"
|
|
||||||
|
|
||||||
using namespace sync;
|
|
||||||
|
|
||||||
std::string Device::getTrackFileName(std::string trackName)
|
|
||||||
{
|
|
||||||
std::string fileName = baseName.c_str();
|
|
||||||
fileName += "_";
|
|
||||||
fileName += trackName;
|
|
||||||
fileName += ".track";
|
|
||||||
return fileName;
|
|
||||||
}
|
|
||||||
@ -2,40 +2,35 @@
|
|||||||
* For conditions of distribution and use, see copyright notice in LICENSE.TXT
|
* For conditions of distribution and use, see copyright notice in LICENSE.TXT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef SYNC_H
|
#ifndef SYNC_DEVICE_H
|
||||||
#define SYNC_H
|
#define SYNC_DEVICE_H
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include "track.h"
|
#include "track.h"
|
||||||
|
#include "data.h"
|
||||||
|
|
||||||
namespace sync
|
#ifndef SYNC_PLAYER
|
||||||
{
|
#include "network.h"
|
||||||
class Timer
|
#endif
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual ~Timer() {};
|
|
||||||
|
|
||||||
virtual void pause() = 0;
|
#ifdef __cplusplus
|
||||||
virtual void play() = 0;
|
extern "C" {
|
||||||
virtual float getRow() = 0;
|
#endif
|
||||||
virtual void setRow(float pos) = 0;
|
|
||||||
virtual bool isPlaying() = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Device
|
struct sync_device {
|
||||||
{
|
const char *base;
|
||||||
public:
|
struct sync_data data;
|
||||||
Device(const std::string &baseName) : baseName(baseName) {}
|
|
||||||
virtual ~Device() {}
|
|
||||||
|
|
||||||
virtual Track &getTrack(const std::string &trackName) = 0;
|
#ifndef SYNC_PLAYER
|
||||||
virtual bool update(float row) = 0;
|
struct sync_cb *cb;
|
||||||
protected:
|
void *cb_param;
|
||||||
std::string getTrackFileName(std::string trackName);
|
int row;
|
||||||
const std::string baseName;
|
SOCKET sock;
|
||||||
};
|
#endif
|
||||||
|
};
|
||||||
|
const char *sync_track_path(const char *base, const char *name);
|
||||||
|
|
||||||
Device *createDevice(const std::string &baseName, Timer &timer);
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* SYNC_H */
|
#endif /* SYNC_DEVICE_H */
|
||||||
|
|||||||
@ -1,212 +0,0 @@
|
|||||||
/* Copyright (C) 2007-2008 Erik Faye-Lund and Egbert Teeselink
|
|
||||||
* For conditions of distribution and use, see copyright notice in LICENSE.TXT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "device.h"
|
|
||||||
#include "data.h"
|
|
||||||
#include "network.h"
|
|
||||||
|
|
||||||
#ifndef REMOTE_HOST
|
|
||||||
#define REMOTE_HOST "localhost"
|
|
||||||
#endif
|
|
||||||
#define REMOTE_PORT 1338
|
|
||||||
|
|
||||||
using namespace sync;
|
|
||||||
|
|
||||||
class ClientDevice : public Device
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ClientDevice(const std::string &baseName, SOCKET serverSocket, Timer &timer) :
|
|
||||||
Device(baseName),
|
|
||||||
timer(timer),
|
|
||||||
serverRow(-1),
|
|
||||||
serverSocket(NetworkSocket(serverSocket))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
~ClientDevice();
|
|
||||||
|
|
||||||
Track &getTrack(const std::string &trackName);
|
|
||||||
bool update(float row);
|
|
||||||
|
|
||||||
private:
|
|
||||||
void saveTracks();
|
|
||||||
|
|
||||||
sync::Data syncData;
|
|
||||||
Timer &timer;
|
|
||||||
|
|
||||||
int serverRow;
|
|
||||||
NetworkSocket serverSocket;
|
|
||||||
};
|
|
||||||
|
|
||||||
ClientDevice::~ClientDevice()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Track &ClientDevice::getTrack(const std::string &trackName)
|
|
||||||
{
|
|
||||||
int index = syncData.getTrackIndex(trackName);
|
|
||||||
if (0 <= index) return syncData.getTrack(size_t(index));
|
|
||||||
|
|
||||||
// send request data
|
|
||||||
unsigned char cmd = GET_TRACK;
|
|
||||||
serverSocket.send((char*)&cmd, 1, 0);
|
|
||||||
size_t clientIndex = syncData.getTrackCount();
|
|
||||||
serverSocket.send((char*)&clientIndex, sizeof(size_t), 0);
|
|
||||||
size_t name_len = trackName.size();
|
|
||||||
serverSocket.send((char*)&name_len, sizeof(size_t), 0);
|
|
||||||
const char *name_str = trackName.c_str();
|
|
||||||
serverSocket.send(name_str, int(name_len), 0);
|
|
||||||
|
|
||||||
// insert new track
|
|
||||||
index = int(syncData.createTrack(trackName));
|
|
||||||
return syncData.getTrack(size_t(index));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ClientDevice::update(float row)
|
|
||||||
{
|
|
||||||
bool done = false;
|
|
||||||
// look for new commands
|
|
||||||
while (serverSocket.pollRead())
|
|
||||||
{
|
|
||||||
unsigned char cmd = 0;
|
|
||||||
if (serverSocket.recv((char*)&cmd, 1, 0))
|
|
||||||
{
|
|
||||||
switch (cmd)
|
|
||||||
{
|
|
||||||
case SET_KEY:
|
|
||||||
{
|
|
||||||
int track = 0, row = 0;
|
|
||||||
float value = 0.0f;
|
|
||||||
unsigned char interp = 0;
|
|
||||||
|
|
||||||
serverSocket.recv((char*)&track, sizeof(int), 0);
|
|
||||||
serverSocket.recv((char*)&row, sizeof(int), 0);
|
|
||||||
serverSocket.recv((char*)&value, sizeof(float), 0);
|
|
||||||
serverSocket.recv((char*)&interp, 1, 0);
|
|
||||||
if (!serverSocket.connected()) return true;
|
|
||||||
|
|
||||||
assert(interp < Track::KeyFrame::IT_COUNT);
|
|
||||||
|
|
||||||
sync::Track &t = syncData.getTrack(track);
|
|
||||||
t.setKeyFrame(row,
|
|
||||||
Track::KeyFrame(
|
|
||||||
value,
|
|
||||||
Track::KeyFrame::InterpolationType(interp)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DELETE_KEY:
|
|
||||||
{
|
|
||||||
int track = 0, row = 0;
|
|
||||||
serverSocket.recv((char*)&track, sizeof(int), 0);
|
|
||||||
serverSocket.recv((char*)&row, sizeof(int), 0);
|
|
||||||
if (!serverSocket.connected()) return true;
|
|
||||||
|
|
||||||
sync::Track &t = syncData.getTrack(track);
|
|
||||||
t.deleteKeyFrame(row);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SET_ROW:
|
|
||||||
{
|
|
||||||
int row;
|
|
||||||
serverSocket.recv((char*)&row, sizeof(int), 0);
|
|
||||||
if (!serverSocket.connected()) return true;
|
|
||||||
timer.setRow(float(row));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PAUSE:
|
|
||||||
{
|
|
||||||
char flag;
|
|
||||||
serverSocket.recv((char*)&flag, 1, 0);
|
|
||||||
if (!serverSocket.connected()) return true;
|
|
||||||
if (flag == 0) timer.play();
|
|
||||||
else timer.pause();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SAVE_TRACKS:
|
|
||||||
saveTracks();
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
assert(false);
|
|
||||||
fprintf(stderr, "unknown cmd: %02x\n", cmd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (timer.isPlaying())
|
|
||||||
{
|
|
||||||
int newServerRow = int(floor(row));
|
|
||||||
if (serverRow != newServerRow && serverSocket.connected())
|
|
||||||
{
|
|
||||||
unsigned char cmd = SET_ROW;
|
|
||||||
serverSocket.send((char*)&cmd, 1, 0);
|
|
||||||
serverSocket.send((char*)&newServerRow, sizeof(int), 0);
|
|
||||||
serverRow = newServerRow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool saveTrack(const sync::Track &track, std::string fileName)
|
|
||||||
{
|
|
||||||
FILE *fp = fopen(fileName.c_str(), "wb");
|
|
||||||
if (NULL == fp) return false;
|
|
||||||
|
|
||||||
size_t keyFrameCount = track.getKeyFrameCount();
|
|
||||||
fwrite(&keyFrameCount, sizeof(size_t), 1, fp);
|
|
||||||
|
|
||||||
sync::Track::KeyFrameContainer::const_iterator it;
|
|
||||||
for (it = track.keyFramesBegin(); it != track.keyFramesEnd(); ++it)
|
|
||||||
{
|
|
||||||
size_t row = it->first;
|
|
||||||
float value = it->second.value;
|
|
||||||
char interpolationType = char(it->second.interpolationType);
|
|
||||||
|
|
||||||
// write key
|
|
||||||
fwrite(&row, sizeof(size_t), 1, fp);
|
|
||||||
fwrite(&value, sizeof(float), 1, fp);
|
|
||||||
fwrite(&interpolationType, sizeof(char), 1, fp);
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(fp);
|
|
||||||
fp = NULL;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClientDevice::saveTracks()
|
|
||||||
{
|
|
||||||
for (size_t i = 0; i < syncData.getTrackCount(); ++i)
|
|
||||||
{
|
|
||||||
const sync::Track &track = syncData.getTrack(i);
|
|
||||||
saveTrack(track, getTrackFileName(track.getName()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Device *sync::createDevice(const std::string &baseName, Timer &timer)
|
|
||||||
{
|
|
||||||
if (false == initNetwork()) return NULL;
|
|
||||||
|
|
||||||
struct hostent *host = gethostbyname(REMOTE_HOST);
|
|
||||||
if (NULL == host) return NULL;
|
|
||||||
printf("IP address: %s\n", inet_ntoa(*(struct in_addr*)host->h_addr_list[0]));
|
|
||||||
|
|
||||||
struct sockaddr_in sain;
|
|
||||||
sain.sin_family = AF_INET;
|
|
||||||
sain.sin_port = htons(REMOTE_PORT);
|
|
||||||
sain.sin_addr.s_addr = ((struct in_addr *)(host->h_addr_list[0]))->s_addr;
|
|
||||||
|
|
||||||
// connect to server
|
|
||||||
SOCKET serverSocket = serverConnect(&sain);
|
|
||||||
if (INVALID_SOCKET == serverSocket) return NULL;
|
|
||||||
|
|
||||||
ClientDevice *device = new ClientDevice(baseName, serverSocket, timer);
|
|
||||||
return device;
|
|
||||||
}
|
|
||||||
@ -1,83 +0,0 @@
|
|||||||
/* Copyright (C) 2007-2008 Erik Faye-Lund and Egbert Teeselink
|
|
||||||
* For conditions of distribution and use, see copyright notice in LICENSE.TXT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "device.h"
|
|
||||||
#include "data.h"
|
|
||||||
#include "network.h"
|
|
||||||
|
|
||||||
using namespace sync;
|
|
||||||
|
|
||||||
class PlayerDevice : public Device
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
PlayerDevice(const std::string &baseName, Timer &timer) :
|
|
||||||
Device(baseName),
|
|
||||||
timer(timer)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
~PlayerDevice();
|
|
||||||
|
|
||||||
Track &getTrack(const std::string &trackName);
|
|
||||||
bool update(float row);
|
|
||||||
|
|
||||||
private:
|
|
||||||
sync::Data syncData;
|
|
||||||
Timer &timer;
|
|
||||||
};
|
|
||||||
|
|
||||||
PlayerDevice::~PlayerDevice() { }
|
|
||||||
|
|
||||||
static bool loadTrack(sync::Track &track, std::string fileName)
|
|
||||||
{
|
|
||||||
FILE *fp = fopen(fileName.c_str(), "rb");
|
|
||||||
if (NULL == fp) return false;
|
|
||||||
|
|
||||||
size_t keyFrameCount;
|
|
||||||
fread(&keyFrameCount, sizeof(size_t), 1, fp);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < keyFrameCount; ++i)
|
|
||||||
{
|
|
||||||
size_t row;
|
|
||||||
float value;
|
|
||||||
char interp;
|
|
||||||
fread(&row, sizeof(size_t), 1, fp);
|
|
||||||
fread(&value, sizeof(float), 1, fp);
|
|
||||||
fread(&interp, sizeof(char), 1, fp);
|
|
||||||
|
|
||||||
track.setKeyFrame(row,
|
|
||||||
Track::KeyFrame(
|
|
||||||
value,
|
|
||||||
Track::KeyFrame::InterpolationType(interp)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(fp);
|
|
||||||
fp = NULL;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Track &PlayerDevice::getTrack(const std::string &trackName)
|
|
||||||
{
|
|
||||||
int trackIndex = syncData.getTrackIndex(trackName);
|
|
||||||
if (0 <= trackIndex) return syncData.getTrack(trackIndex);
|
|
||||||
|
|
||||||
trackIndex = int(syncData.createTrack(trackName));
|
|
||||||
sync::Track &track = syncData.getTrack(trackIndex);
|
|
||||||
loadTrack(track, getTrackFileName(trackName));
|
|
||||||
return track;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PlayerDevice::update(float row)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
Device *sync::createDevice(const std::string &baseName, Timer &timer)
|
|
||||||
{
|
|
||||||
Device *device = new PlayerDevice(baseName, timer);
|
|
||||||
return device;
|
|
||||||
}
|
|
||||||
123
sync/network.cpp
123
sync/network.cpp
@ -1,123 +0,0 @@
|
|||||||
/* Copyright (C) 2007-2008 Erik Faye-Lund and Egbert Teeselink
|
|
||||||
* For conditions of distribution and use, see copyright notice in LICENSE.TXT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "network.h"
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#ifndef WIN32
|
|
||||||
|
|
||||||
#include "../wifi9.h"
|
|
||||||
#include <nds/jtypes.h>
|
|
||||||
#include <dswifi9.h>
|
|
||||||
#include <netdb.h>
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bool initNetwork()
|
|
||||||
{
|
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
WSADATA wsaData;
|
|
||||||
if (0 != WSAStartup(MAKEWORD( 2, 0 ), &wsaData)) return false;
|
|
||||||
if (LOBYTE( wsaData.wVersion ) != 2 || HIBYTE( wsaData.wVersion ) != 0) return false;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// unix sockets need no init
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void closeNetwork()
|
|
||||||
{
|
|
||||||
#ifdef WIN32
|
|
||||||
WSACleanup();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char *clientGreeting = "hello, synctracker!";
|
|
||||||
static const char *serverGreeting = "hello, demo!";
|
|
||||||
|
|
||||||
SOCKET clientConnect(SOCKET serverSocket, sockaddr_in *host)
|
|
||||||
{
|
|
||||||
sockaddr_in hostTemp;
|
|
||||||
int hostSize = sizeof(sockaddr_in);
|
|
||||||
SOCKET clientSocket = accept(serverSocket, (sockaddr*)&hostTemp, &hostSize);
|
|
||||||
if (INVALID_SOCKET == clientSocket) return INVALID_SOCKET;
|
|
||||||
|
|
||||||
const char *expectedGreeting = clientGreeting;
|
|
||||||
char recievedGreeting[128];
|
|
||||||
|
|
||||||
recv(clientSocket, recievedGreeting, int(strlen(expectedGreeting)), 0);
|
|
||||||
|
|
||||||
if (strncmp(expectedGreeting, recievedGreeting, strlen(expectedGreeting)) != 0)
|
|
||||||
{
|
|
||||||
closesocket(clientSocket);
|
|
||||||
return INVALID_SOCKET;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *greeting = serverGreeting;
|
|
||||||
send(clientSocket, greeting, int(strlen(greeting)), 0);
|
|
||||||
|
|
||||||
if (NULL != host) *host = hostTemp;
|
|
||||||
return clientSocket;
|
|
||||||
}
|
|
||||||
|
|
||||||
SOCKET serverConnect(struct sockaddr_in *addr)
|
|
||||||
{
|
|
||||||
SOCKET serverSocket = socket( AF_INET, SOCK_STREAM, 0 );
|
|
||||||
connect( serverSocket,(struct sockaddr *)addr, sizeof(struct sockaddr_in));
|
|
||||||
|
|
||||||
const char *greeting = clientGreeting;
|
|
||||||
send(serverSocket, greeting, int(strlen(greeting)), 0);
|
|
||||||
|
|
||||||
const char *expectedGreeting = serverGreeting;
|
|
||||||
char recievedGreeting[128];
|
|
||||||
|
|
||||||
recv(serverSocket, recievedGreeting, int(strlen(expectedGreeting)), 0);
|
|
||||||
if (strncmp(expectedGreeting, recievedGreeting, strlen(expectedGreeting)) != 0)
|
|
||||||
{
|
|
||||||
closesocket(serverSocket);
|
|
||||||
return INVALID_SOCKET;
|
|
||||||
}
|
|
||||||
|
|
||||||
return serverSocket;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool pollRead(SOCKET socket)
|
|
||||||
{
|
|
||||||
struct timeval timeout = { 0, 0 };
|
|
||||||
fd_set fds;
|
|
||||||
|
|
||||||
FD_ZERO(&fds);
|
|
||||||
FD_SET(socket, &fds);
|
|
||||||
|
|
||||||
// look for new commands
|
|
||||||
return select(0, &fds, NULL, NULL, &timeout) > 0;
|
|
||||||
}
|
|
||||||
#if 0
|
|
||||||
bool recvBlock(SOCKET socket, char *buffer, size_t length, int flags)
|
|
||||||
{
|
|
||||||
size_t pos = 0;
|
|
||||||
while (pos < length)
|
|
||||||
{
|
|
||||||
int ret = recv(socket, &buffer[pos], int(length - pos), flags);
|
|
||||||
if (0 > ret) return false; // error
|
|
||||||
pos += ret;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool sendBlock(SOCKET socket, const char *buffer, size_t length, int flags)
|
|
||||||
{
|
|
||||||
size_t pos = 0;
|
|
||||||
while (pos < length)
|
|
||||||
{
|
|
||||||
int ret = send(socket, &buffer[pos], int(length - pos), flags);
|
|
||||||
if (0 > ret) return false; // error
|
|
||||||
pos += ret;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
130
sync/network.h
130
sync/network.h
@ -1,101 +1,65 @@
|
|||||||
/* Copyright (C) 2007-2008 Erik Faye-Lund and Egbert Teeselink
|
/* Copyright (C) 2007-2010 Erik Faye-Lund and Egbert Teeselink
|
||||||
* For conditions of distribution and use, see copyright notice in LICENSE.TXT
|
* For conditions of distribution and use, see copyright notice in LICENSE.TXT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef NETWORK_H
|
#ifndef SYNC_NETWORK_H
|
||||||
#define NETWORK_H
|
#define SYNC_NETWORK_H
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
|
#include <winsock2.h>
|
||||||
#include <winsock2.h>
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
|
#include <windows.h>
|
||||||
#include <windows.h>
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
#include <sys/socket.h>
|
||||||
#include <sys/socket.h>
|
#include <netinet/in.h>
|
||||||
#include <netinet/in.h>
|
#include <netdb.h>
|
||||||
#include <netdb.h>
|
#define SOCKET int
|
||||||
#define SOCKET int
|
#define INVALID_SOCKET -1
|
||||||
#define INVALID_SOCKET -1
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool initNetwork();
|
#include "base.h"
|
||||||
void closeNetwork();
|
|
||||||
|
|
||||||
// SOCKET clientConnect(SOCKET serverSocket);
|
static const char *client_greet = "hello, synctracker!";
|
||||||
SOCKET clientConnect(SOCKET serverSocket, sockaddr_in *host = NULL);
|
static const char *server_greet = "hello, demo!";
|
||||||
SOCKET serverConnect(struct sockaddr_in *addr);
|
|
||||||
bool pollRead(SOCKET socket);
|
|
||||||
|
|
||||||
class NetworkSocket
|
enum {
|
||||||
{
|
|
||||||
public:
|
|
||||||
NetworkSocket() : socket(INVALID_SOCKET) {}
|
|
||||||
explicit NetworkSocket(SOCKET socket) : socket(socket) {}
|
|
||||||
|
|
||||||
bool connected() const { return INVALID_SOCKET != socket; };
|
|
||||||
void disconnect()
|
|
||||||
{
|
|
||||||
closesocket(socket);
|
|
||||||
socket = INVALID_SOCKET;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool recv(char *buffer, size_t length, int flags)
|
|
||||||
{
|
|
||||||
if (!connected()) return false;
|
|
||||||
int ret = ::recv(socket, buffer, int(length), flags);
|
|
||||||
if (ret != length)
|
|
||||||
{
|
|
||||||
disconnect();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool send(const char *buffer, size_t length, int flags)
|
|
||||||
{
|
|
||||||
if (!connected()) return false;
|
|
||||||
int ret = ::send(socket, buffer, int(length), flags);
|
|
||||||
if (ret != length)
|
|
||||||
{
|
|
||||||
disconnect();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool pollRead()
|
|
||||||
{
|
|
||||||
if (!connected()) return false;
|
|
||||||
return ::pollRead(socket);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
SOCKET socket;
|
|
||||||
};
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
bool recvBlock(SOCKET socket, char *buffer, size_t length, int flags);
|
|
||||||
bool sendBlock(SOCKET socket, const char *buffer, size_t length, int flags);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
enum RemoteCommand {
|
|
||||||
// server -> client
|
|
||||||
SET_KEY = 0,
|
SET_KEY = 0,
|
||||||
DELETE_KEY = 1,
|
DELETE_KEY = 1,
|
||||||
|
|
||||||
// client -> server
|
|
||||||
GET_TRACK = 2,
|
GET_TRACK = 2,
|
||||||
|
|
||||||
// client -> server, server -> client
|
|
||||||
SET_ROW = 3,
|
SET_ROW = 3,
|
||||||
|
|
||||||
// server -> client
|
|
||||||
PAUSE = 4,
|
PAUSE = 4,
|
||||||
|
|
||||||
SAVE_TRACKS = 5
|
SAVE_TRACKS = 5
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* NETWORK_H */
|
static inline int init_network()
|
||||||
|
{
|
||||||
|
#ifdef WIN32
|
||||||
|
WSADATA wsa;
|
||||||
|
if (0 != WSAStartup(MAKEWORD(2, 0), &wsa))
|
||||||
|
return 0;
|
||||||
|
if (LOBYTE(wsa.wVersion) != 2 || HIBYTE(wsa.wVersion) != 0)
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void close_network()
|
||||||
|
{
|
||||||
|
#ifdef WIN32
|
||||||
|
WSACleanup();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int socket_poll(SOCKET socket)
|
||||||
|
{
|
||||||
|
struct timeval to = { 0, 0 };
|
||||||
|
fd_set fds;
|
||||||
|
|
||||||
|
FD_ZERO(&fds);
|
||||||
|
FD_SET(socket, &fds);
|
||||||
|
|
||||||
|
return select(0, &fds, NULL, NULL, &to) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* SYNC_NETWORK_H */
|
||||||
|
|||||||
34
sync/sync.h
Normal file
34
sync/sync.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
/* Copyright (C) 2010 Erik Faye-Lund and Egbert Teeselink
|
||||||
|
* For conditions of distribution and use, see copyright notice in LICENSE.TXT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SYNC_H
|
||||||
|
#define SYNC_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct sync_device;
|
||||||
|
struct sync_track;
|
||||||
|
|
||||||
|
struct sync_device *sync_create_device(const char *);
|
||||||
|
|
||||||
|
#ifndef SYNC_PLAYER
|
||||||
|
struct sync_cb {
|
||||||
|
void (*pause)(void *, int);
|
||||||
|
void (*set_row)(void *, int);
|
||||||
|
int (*is_playing)(void *);
|
||||||
|
};
|
||||||
|
void sync_set_callbacks(struct sync_device *, struct sync_cb *, void *);
|
||||||
|
#endif /* !defined(SYNC_PLAYER) */
|
||||||
|
|
||||||
|
void sync_update(struct sync_device *, double);
|
||||||
|
struct sync_track *sync_get_track(struct sync_device *, const char *);
|
||||||
|
float sync_get_val(const struct sync_track *, double);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* !defined(SYNC_H) */
|
||||||
107
sync/track.c
Normal file
107
sync/track.c
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
/* Copyright (C) 2010 Erik Faye-Lund and Egbert Teeselink
|
||||||
|
* For conditions of distribution and use, see copyright notice in LICENSE.TXT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <math.h>
|
||||||
|
#ifndef M_PI
|
||||||
|
#define M_PI 3.141926
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "sync.h"
|
||||||
|
#include "track.h"
|
||||||
|
#include "base.h"
|
||||||
|
|
||||||
|
static float key_linear(const struct track_key k[2], double row)
|
||||||
|
{
|
||||||
|
double t = (row - k[0].row) / (k[1].row - k[0].row);
|
||||||
|
return (float)(k[0].value + (k[1].value - k[0].value) * t);
|
||||||
|
}
|
||||||
|
|
||||||
|
static float key_smooth(const struct track_key k[2], double row)
|
||||||
|
{
|
||||||
|
double t = (row - k[0].row) / (k[1].row - k[0].row);
|
||||||
|
t = (1.0 - cos(t * M_PI)) * 0.5;
|
||||||
|
return (float)(k[0].value + (k[1].value - k[0].value) * t);
|
||||||
|
}
|
||||||
|
|
||||||
|
static float key_ramp(const struct track_key k[2], double row)
|
||||||
|
{
|
||||||
|
double t = (row - k[0].row) / (k[1].row - k[0].row);
|
||||||
|
t = pow(t, 2.0);
|
||||||
|
return (float)(k[0].value + (k[1].value - k[0].value) * t);
|
||||||
|
}
|
||||||
|
|
||||||
|
float sync_get_val(const struct sync_track *t, double row)
|
||||||
|
{
|
||||||
|
int idx, irow;
|
||||||
|
if (!t->num_keys)
|
||||||
|
return 0.0f;
|
||||||
|
|
||||||
|
irow = (int)floor(row);
|
||||||
|
idx = key_idx_floor(t, irow);
|
||||||
|
if (idx < 0)
|
||||||
|
return t->keys[0].value;
|
||||||
|
if (idx > (int)t->num_keys - 2)
|
||||||
|
return t->keys[t->num_keys - 1].value;
|
||||||
|
|
||||||
|
switch (t->keys[idx].type) {
|
||||||
|
case KEY_STEP:
|
||||||
|
return t->keys[idx].value;
|
||||||
|
case KEY_LINEAR:
|
||||||
|
return key_linear(t->keys + idx, row);
|
||||||
|
case KEY_SMOOTH:
|
||||||
|
return key_smooth(t->keys + idx, row);
|
||||||
|
case KEY_RAMP:
|
||||||
|
return key_ramp(t->keys + idx, row);
|
||||||
|
default:
|
||||||
|
assert(0);
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int sync_find_key(const struct sync_track *t, int row)
|
||||||
|
{
|
||||||
|
int lo = 0, hi = t->num_keys;
|
||||||
|
while (lo < hi) {
|
||||||
|
int mi = (lo + hi) / 2;
|
||||||
|
assert(mi != hi);
|
||||||
|
|
||||||
|
if (t->keys[mi].row < row)
|
||||||
|
lo = mi + 1;
|
||||||
|
else if (t->keys[mi].row > row)
|
||||||
|
hi = mi;
|
||||||
|
else
|
||||||
|
return mi;
|
||||||
|
}
|
||||||
|
return -lo - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef SYNC_PLAYER
|
||||||
|
void sync_set_key(struct sync_track *t, const struct track_key *k)
|
||||||
|
{
|
||||||
|
int idx = sync_find_key(t, k->row);
|
||||||
|
if (idx < 0) {
|
||||||
|
idx = -idx - 1;
|
||||||
|
t->num_keys++;
|
||||||
|
t->keys = realloc(t->keys, sizeof(struct track_key) *
|
||||||
|
t->num_keys);
|
||||||
|
assert(t->keys);
|
||||||
|
memmove(t->keys + idx + 1, t->keys + idx,
|
||||||
|
sizeof(struct track_key) * (t->num_keys - idx - 1));
|
||||||
|
}
|
||||||
|
t->keys[idx] = *k;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sync_del_key(struct sync_track *t, int pos)
|
||||||
|
{
|
||||||
|
int idx = sync_find_key(t, pos);
|
||||||
|
assert(idx >= 0);
|
||||||
|
memmove(t->keys + idx, t->keys + idx + 1,
|
||||||
|
sizeof(struct track_key) * (t->num_keys - idx - 1));
|
||||||
|
assert(t->keys);
|
||||||
|
t->num_keys--;
|
||||||
|
t->keys = realloc(t->keys, t->num_keys * sizeof(struct track_key));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
110
sync/track.cpp
110
sync/track.cpp
@ -1,110 +0,0 @@
|
|||||||
/* Copyright (C) 2007-2008 Erik Faye-Lund and Egbert Teeselink
|
|
||||||
* For conditions of distribution and use, see copyright notice in LICENSE.TXT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define _USE_MATH_DEFINES
|
|
||||||
#include <cmath>
|
|
||||||
|
|
||||||
#include "track.h"
|
|
||||||
#include "data.h"
|
|
||||||
using namespace sync;
|
|
||||||
|
|
||||||
#include <cstddef>
|
|
||||||
|
|
||||||
/*#ifndef M_PI
|
|
||||||
#define M_PI
|
|
||||||
#endif */
|
|
||||||
|
|
||||||
static inline float step(Track::KeyFrameContainer::const_iterator lower, Track::KeyFrameContainer::const_iterator upper, float time)
|
|
||||||
{
|
|
||||||
return lower->second.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline float lerp(Track::KeyFrameContainer::const_iterator lower, Track::KeyFrameContainer::const_iterator upper, float time)
|
|
||||||
{
|
|
||||||
// find local time
|
|
||||||
float t = (time - lower->first) / (upper->first - lower->first);
|
|
||||||
|
|
||||||
// lerp, bitch
|
|
||||||
float delta = upper->second.value - lower->second.value;
|
|
||||||
return lower->second.value + delta * t;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline float cosine(Track::KeyFrameContainer::const_iterator lower, Track::KeyFrameContainer::const_iterator upper, float time)
|
|
||||||
{
|
|
||||||
// find local time
|
|
||||||
float t = (time - lower->first) / (upper->first - lower->first);
|
|
||||||
t = float((1.0 - cos(t * M_PI)) * 0.5);
|
|
||||||
|
|
||||||
// lerp, bitch
|
|
||||||
float delta = upper->second.value - lower->second.value;
|
|
||||||
return lower->second.value + delta * t;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline float ramp(Track::KeyFrameContainer::const_iterator lower, Track::KeyFrameContainer::const_iterator upper, float time)
|
|
||||||
{
|
|
||||||
// find local time
|
|
||||||
float t = (time - lower->first) / (upper->first - lower->first);
|
|
||||||
t = powf(t, 2.0f);
|
|
||||||
|
|
||||||
// lerp, bitch
|
|
||||||
float delta = upper->second.value - lower->second.value;
|
|
||||||
return lower->second.value + delta * t;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*float cosine(float time) const;
|
|
||||||
float ramp(float time) const; */
|
|
||||||
|
|
||||||
float Track::getValue(float time) const
|
|
||||||
{
|
|
||||||
if (keyFrames.size() == 0) return 0.0f;
|
|
||||||
|
|
||||||
// find bounding keyframes
|
|
||||||
int currRow = int(floor(time));
|
|
||||||
KeyFrameContainer::const_iterator upper = keyFrames.upper_bound(currRow);
|
|
||||||
KeyFrameContainer::const_iterator lower = upper;
|
|
||||||
lower--;
|
|
||||||
|
|
||||||
// bounds check
|
|
||||||
if (lower == keyFrames.end()) return upper->second.value;
|
|
||||||
if (upper == keyFrames.end()) return lower->second.value;
|
|
||||||
|
|
||||||
switch (lower->second.interpolationType)
|
|
||||||
{
|
|
||||||
case Track::KeyFrame::IT_STEP: return step( lower, upper, time);
|
|
||||||
case Track::KeyFrame::IT_LERP: return lerp( lower, upper, time);
|
|
||||||
case Track::KeyFrame::IT_COSINE: return cosine(lower, upper, time);
|
|
||||||
case Track::KeyFrame::IT_RAMP: return ramp( lower, upper, time);
|
|
||||||
default:
|
|
||||||
assert(false);
|
|
||||||
return step(lower, upper, time);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Track::isKeyFrame(size_t row) const
|
|
||||||
{
|
|
||||||
return keyFrames.find(row) != keyFrames.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
const Track::KeyFrame *Track::getKeyFrame(size_t row) const
|
|
||||||
{
|
|
||||||
KeyFrameContainer::const_iterator iter = keyFrames.find(row);
|
|
||||||
if (iter == keyFrames.end()) return NULL;
|
|
||||||
return &iter->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Track::deleteKeyFrame(size_t row)
|
|
||||||
{
|
|
||||||
keyFrames.erase(row);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Track::setKeyFrame(size_t row, const KeyFrame &keyFrame)
|
|
||||||
{
|
|
||||||
keyFrames[row] = keyFrame;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Track::truncate()
|
|
||||||
{
|
|
||||||
keyFrames.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
107
sync/track.h
107
sync/track.h
@ -1,76 +1,59 @@
|
|||||||
/* Copyright (C) 2007-2008 Erik Faye-Lund and Egbert Teeselink
|
/* Copyright (C) 2007-2010 Erik Faye-Lund and Egbert Teeselink
|
||||||
* For conditions of distribution and use, see copyright notice in LICENSE.TXT
|
* For conditions of distribution and use, see copyright notice in LICENSE.TXT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef SYNC_TRACK_H
|
#ifndef SYNC_TRACK_H
|
||||||
#define SYNC_TRACK_H
|
#define SYNC_TRACK_H
|
||||||
|
|
||||||
#include <map>
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "base.h"
|
||||||
|
|
||||||
namespace sync
|
#ifdef __cplusplus
|
||||||
{
|
extern "C" {
|
||||||
class Track
|
#endif
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit Track(const std::string &name) : name(name) { }
|
|
||||||
|
|
||||||
struct KeyFrame
|
enum key_type {
|
||||||
{
|
KEY_STEP, /* stay constant */
|
||||||
enum InterpolationType
|
KEY_LINEAR, /* lerp to the next value */
|
||||||
{
|
KEY_SMOOTH, /* smooth curve to the next value */
|
||||||
IT_STEP,
|
KEY_RAMP,
|
||||||
IT_LERP,
|
KEY_TYPE_COUNT
|
||||||
IT_COSINE,
|
};
|
||||||
IT_RAMP,
|
|
||||||
IT_COUNT // max value
|
|
||||||
};
|
|
||||||
|
|
||||||
KeyFrame() : value(0.0f), interpolationType(IT_STEP) {}
|
|
||||||
KeyFrame(float value, InterpolationType interpolationType) :
|
|
||||||
value(value),
|
|
||||||
interpolationType(interpolationType)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
struct track_key {
|
||||||
|
int row;
|
||||||
float value;
|
float value;
|
||||||
InterpolationType interpolationType;
|
enum key_type type;
|
||||||
};
|
};
|
||||||
|
|
||||||
float getValue(float time) const;
|
struct sync_track {
|
||||||
|
char *name;
|
||||||
|
struct track_key *keys;
|
||||||
|
size_t num_keys;
|
||||||
|
};
|
||||||
|
|
||||||
bool isKeyFrame(size_t row) const;
|
int sync_find_key(const struct sync_track *, int);
|
||||||
const KeyFrame *getKeyFrame(size_t row) const;
|
static inline int key_idx_floor(const struct sync_track *t, int row)
|
||||||
|
{
|
||||||
void deleteKeyFrame(size_t row);
|
int idx = sync_find_key(t, row);
|
||||||
void setKeyFrame(size_t row, const KeyFrame &keyFrame);
|
if (idx < 0)
|
||||||
|
idx = -idx - 2;
|
||||||
void truncate();
|
return idx;
|
||||||
|
|
||||||
const std::string &getName() const { return name; }
|
|
||||||
|
|
||||||
typedef std::map<size_t, struct KeyFrame> KeyFrameContainer;
|
|
||||||
KeyFrameContainer::const_iterator keyFramesBegin() const { return keyFrames.begin(); }
|
|
||||||
KeyFrameContainer::const_iterator keyFramesEnd() const { return keyFrames.end(); }
|
|
||||||
size_t getKeyFrameCount() const { return keyFrames.size(); }
|
|
||||||
|
|
||||||
KeyFrame::InterpolationType getInterpolationType(int row) const
|
|
||||||
{
|
|
||||||
KeyFrame::InterpolationType interpolationType = KeyFrame::IT_STEP;
|
|
||||||
{
|
|
||||||
KeyFrameContainer::const_iterator upper = keyFrames.upper_bound(row);
|
|
||||||
KeyFrameContainer::const_iterator lower = upper;
|
|
||||||
if (lower != keyFrames.end())
|
|
||||||
{
|
|
||||||
lower--;
|
|
||||||
if (lower != keyFrames.end()) interpolationType = lower->second.interpolationType;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return interpolationType;
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
KeyFrameContainer keyFrames;
|
|
||||||
std::string name;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // SYNC_TRACK_H
|
#ifndef SYNC_PLAYER
|
||||||
|
void sync_set_key(struct sync_track *, const struct track_key *);
|
||||||
|
void sync_del_key(struct sync_track *, int);
|
||||||
|
static inline int is_key_frame(const struct sync_track *t, size_t row)
|
||||||
|
{
|
||||||
|
return sync_find_key(t, row) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* !defined(SYNC_PLAYER) */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* SYNC_TRACK_H */
|
||||||
|
|||||||
@ -41,7 +41,7 @@
|
|||||||
<Tool
|
<Tool
|
||||||
Name="VCCLCompilerTool"
|
Name="VCCLCompilerTool"
|
||||||
Optimization="0"
|
Optimization="0"
|
||||||
PreprocessorDefinitions="WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE"
|
PreprocessorDefinitions="WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;SYNC_PLAYER"
|
||||||
MinimalRebuild="true"
|
MinimalRebuild="true"
|
||||||
BasicRuntimeChecks="3"
|
BasicRuntimeChecks="3"
|
||||||
RuntimeLibrary="1"
|
RuntimeLibrary="1"
|
||||||
@ -102,7 +102,7 @@
|
|||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCCLCompilerTool"
|
Name="VCCLCompilerTool"
|
||||||
PreprocessorDefinitions="WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE"
|
PreprocessorDefinitions="WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;SYNC_PLAYER"
|
||||||
RuntimeLibrary="2"
|
RuntimeLibrary="2"
|
||||||
UsePrecompiledHeader="0"
|
UsePrecompiledHeader="0"
|
||||||
WarningLevel="3"
|
WarningLevel="3"
|
||||||
@ -161,7 +161,7 @@
|
|||||||
<Tool
|
<Tool
|
||||||
Name="VCCLCompilerTool"
|
Name="VCCLCompilerTool"
|
||||||
Optimization="0"
|
Optimization="0"
|
||||||
PreprocessorDefinitions="WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE"
|
PreprocessorDefinitions="WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE"
|
||||||
MinimalRebuild="true"
|
MinimalRebuild="true"
|
||||||
BasicRuntimeChecks="3"
|
BasicRuntimeChecks="3"
|
||||||
RuntimeLibrary="1"
|
RuntimeLibrary="1"
|
||||||
@ -268,75 +268,15 @@
|
|||||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||||
>
|
>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\sync\data.cpp"
|
RelativePath=".\sync\data.c"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\sync\device.cpp"
|
RelativePath=".\sync\device.c"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\sync\device_client.cpp"
|
RelativePath=".\sync\track.c"
|
||||||
>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug|Win32"
|
|
||||||
ExcludedFromBuild="true"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCLCompilerTool"
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Release|Win32"
|
|
||||||
ExcludedFromBuild="true"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCLCompilerTool"
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\sync\device_player.cpp"
|
|
||||||
>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug Client|Win32"
|
|
||||||
ExcludedFromBuild="true"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCLCompilerTool"
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Release Client|Win32"
|
|
||||||
ExcludedFromBuild="true"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCLCompilerTool"
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\sync\network.cpp"
|
|
||||||
>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug|Win32"
|
|
||||||
ExcludedFromBuild="true"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCLCompilerTool"
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Release|Win32"
|
|
||||||
ExcludedFromBuild="true"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCLCompilerTool"
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\sync\track.cpp"
|
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
</Filter>
|
</Filter>
|
||||||
@ -346,6 +286,10 @@
|
|||||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||||
>
|
>
|
||||||
<File
|
<File
|
||||||
|
RelativePath=".\sync\base.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
RelativePath=".\sync\data.h"
|
RelativePath=".\sync\data.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
@ -358,6 +302,10 @@
|
|||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
|
RelativePath=".\sync\sync.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
RelativePath=".\sync\track.h"
|
RelativePath=".\sync\track.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user