-Change: Split off UI.

git-svn-id: http://svn.fuzzle.org/mloop/mloop/trunk@7 ba049829-c6ef-42ef-81ac-908dd8d2e907
remotes/git-svn@10
petern 2009-07-22 05:37:49 +00:00
parent f330095902
commit 4a7ee4a61a
6 changed files with 201 additions and 129 deletions

View File

@ -3,9 +3,6 @@
#include <stdio.h>
#include <unistd.h>
#include <limits.h>
#include <string.h>
#include <sys/select.h>
#include <termios.h>
#include <jack/jack.h>
#include <jack/midiport.h>
#include "jack.h"
@ -41,6 +38,8 @@ bool Jack::Connect()
m_connected = true;
m_sample_rate = jack_get_sample_rate(m_client);
jack_on_shutdown(m_client, &ShutdownCallbackHandler, this);
jack_set_process_callback(m_client, &ProcessCallbackHandler, this);
@ -132,129 +131,63 @@ int Jack::ProcessCallback(jack_nframes_t nframes)
return 0;
}
struct termios orig_termios;
void reset_terminal_mode()
void Jack::ToggleRecording(int loop)
{
tcsetattr(0, TCSANOW, &orig_termios);
}
void set_conio_terminal_mode()
{
struct termios new_termios;
/* take two copies - one for now, one for later */
tcgetattr(0, &orig_termios);
memcpy(&new_termios, &orig_termios, sizeof(new_termios));
/* register cleanup handler, and set the new terminal mode */
atexit(reset_terminal_mode);
cfmakeraw(&new_termios);
tcsetattr(0, TCSANOW, &new_termios);
}
int kbhit()
{
struct timeval tv = { 0L, 0L };
fd_set fds;
FD_SET(0, &fds);
return select(1, &fds, NULL, NULL, &tv);
}
int getch()
{
int r;
unsigned char c;
if ((r = read(0, &c, sizeof(c))) < 0) {
return r;
if (m_recording) {
m_recording = false;
m_loops[m_recording_loop].SetLength(m_recording_time);
m_loops[m_recording_loop].EndFromNoteCache(m_notecache);
} else {
return c;
m_recording_loop = loop;
m_loops[m_recording_loop].StartFromNoteCache(m_notecache);
m_recording_time = 0;
m_recording = true;
}
}
void Jack::Run()
void Jack::StartLoop(int loop, bool repeat)
{
set_conio_terminal_mode();
jack_nframes_t recording_time;
jack_midi_event_t ev;
ev.time = UINT_MAX;
m_recording = false;
for (;;) {
usleep(10000);
if (ev.time == UINT_MAX) {
if (m_buffer->Size() >= sizeof recording_time + sizeof ev.time + sizeof ev.size) {
m_buffer->Read((uint8_t *)&recording_time, sizeof recording_time);
m_buffer->Read((uint8_t *)&ev.time, sizeof ev.time);
m_buffer->Read((uint8_t *)&ev.size, sizeof ev.size);
}
} else {
if (m_buffer->Size() >= ev.size) {
ev.buffer = (jack_midi_data_t *)malloc(ev.size);
m_buffer->Read((uint8_t *)ev.buffer, ev.size);
}
if (m_recording) {
printf("Recording event for loop %d\n", m_recording_loop);
m_loops[m_recording_loop].AddEvent(recording_time, &ev);
}
ev.time = UINT_MAX;
}
if (kbhit()) {
char c = getch();
switch (c) {
case 3:
case 'q': return;
case 'r':
if (m_recording) {
m_recording = false;
m_loops[m_recording_loop].SetLength(m_recording_time);
m_loops[m_recording_loop].EndFromNoteCache(m_notecache);
printf("Finished recording loop %d\n", m_recording_loop);
} else {
m_loops[m_recording_loop].StartFromNoteCache(m_notecache);
m_recording_time = 0;
m_recording = true;
printf("Started recording loop %d\n", m_recording_loop);
}
break;
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if (!m_recording) {
m_recording_loop = c - '1';
printf("Selected recording loop %d\n", m_recording_loop);
}
break;
case 'z':
case 'x':
printf("Starting loop %d (%s)\n", m_recording_loop, c == 'x' ? "loop" : "once");
m_loops[m_recording_loop].Start(c == 'x');
break;
case 'c':
printf("Stopping loop %d\n", m_recording_loop);
m_loops[m_recording_loop].Stop();
break;
case 'e':
printf("Erasing loop %d\n", m_recording_loop);
m_loops[m_recording_loop].Empty();
break;
}
}
}
m_loops[loop].Start(repeat);
}
void Jack::StopLoop(int loop)
{
m_loops[loop].Stop();
}
void Jack::EraseLoop(int loop)
{
m_loops[loop].Empty();
}
bool Jack::Run()
{
static jack_nframes_t recording_time;
static jack_midi_event_t ev;
static bool first = true;
if (first) {
ev.time = UINT_MAX;
first = false;
}
if (ev.time == UINT_MAX) {
if (m_buffer->Size() >= sizeof recording_time + sizeof ev.time + sizeof ev.size) {
m_buffer->Read((uint8_t *)&recording_time, sizeof recording_time);
m_buffer->Read((uint8_t *)&ev.time, sizeof ev.time);
m_buffer->Read((uint8_t *)&ev.size, sizeof ev.size);
}
} else {
if (m_buffer->Size() >= ev.size) {
ev.buffer = (jack_midi_data_t *)malloc(ev.size);
m_buffer->Read((uint8_t *)ev.buffer, ev.size);
}
if (m_recording) {
m_loops[m_recording_loop].AddEvent(recording_time, &ev);
}
ev.time = UINT_MAX;
}
return false;
}

View File

@ -8,7 +8,7 @@
#include "ringbuffer.h"
#include "notecache.h"
#define NUM_LOOPS 9
#define NUM_LOOPS 10
class Jack {
private:
@ -18,6 +18,8 @@ private:
jack_port_t *m_output;
jack_port_t *m_control;
jack_nframes_t m_sample_rate;
Loop m_loops[NUM_LOOPS];
RingBuffer *m_buffer;
@ -45,7 +47,17 @@ public:
bool Connect();
void Disconnect();
void Run();
bool Run();
void ToggleRecording(int loop);
void StartLoop(int loop, bool repeat);
void StopLoop(int loop);
void EraseLoop(int loop);
bool Recording() const
{
return m_recording;
}
};
#endif /* JACK_H */

View File

@ -1,15 +1,23 @@
/* $Id$ */
#include <unistd.h>
#include "jack.h"
#include "ui.h"
int main(int argc, char **argv)
{
Jack *j = new Jack();
Jack j;
UI u;
j->Connect();
j->Run();
j.Connect();
delete j;
while (true) {
if (j.Run()) break;
if (u.Run(j)) break;
usleep(10000);
}
j.Disconnect();
return 0;
}

105
src/ui.cpp 100644
View File

@ -0,0 +1,105 @@
/* $Id$ */
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/select.h>
#include <termios.h>
#include "jack.h"
#include "ui.h"
struct termios orig_termios;
void reset_terminal_mode()
{
tcsetattr(0, TCSANOW, &orig_termios);
}
void set_conio_terminal_mode()
{
struct termios new_termios;
/* take two copies - one for now, one for later */
tcgetattr(0, &orig_termios);
memcpy(&new_termios, &orig_termios, sizeof(new_termios));
/* register cleanup handler, and set the new terminal mode */
atexit(reset_terminal_mode);
cfmakeraw(&new_termios);
tcsetattr(0, TCSANOW, &new_termios);
}
int kbhit()
{
struct timeval tv = { 0L, 0L };
fd_set fds;
FD_SET(0, &fds);
return select(1, &fds, NULL, NULL, &tv);
}
int getch()
{
int r;
unsigned char c;
if ((r = read(0, &c, sizeof(c))) < 0) {
return r;
} else {
return c;
}
}
bool UI::Run(Jack &j)
{
static bool first = true;
if (first) {
set_conio_terminal_mode();
first = false;
m_loop = 0;
}
if (!kbhit()) return false;
char c = getch();
switch (c) {
case 3:
case 'q': return true;
case 'r':
j.ToggleRecording(m_loop);
printf("%s recording loop\n", j.Recording() ? "Started" : "Finished");
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
m_loop = (c - '0');
printf("Selected loop %d\n", m_loop);
break;
case 'z':
case 'x':
printf("Starting loop %d (%s)\n", m_loop, c == 'x' ? "loop" : "once");
j.StartLoop(m_loop, c == 'x');
break;
case 'c':
printf("Stopping loop %d\n", m_loop);
j.StopLoop(m_loop);
break;
case 'e':
printf("Erasing loop %d\n", m_loop);
j.EraseLoop(m_loop);
break;
}
return false;
}

14
src/ui.h 100644
View File

@ -0,0 +1,14 @@
/* $Id$ */
#ifndef UI_H
#define UI_H
class UI {
private:
int m_loop;
public:
bool Run(Jack &j);
};
#endif /* UI_H */

View File

@ -7,6 +7,6 @@ def configure(conf):
def build(bld):
bld.new_task_gen(
features = 'cxx cprogram',
source = 'jack.cpp loop.cpp mloop.cpp',
source = 'jack.cpp loop.cpp mloop.cpp ui.cpp',
target = 'mloop',
uselib = 'JACK')