-Change: Split off UI.
git-svn-id: http://svn.fuzzle.org/mloop/mloop/trunk@7 ba049829-c6ef-42ef-81ac-908dd8d2e907remotes/git-svn@10
parent
f330095902
commit
4a7ee4a61a
177
src/jack.cpp
177
src/jack.cpp
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
16
src/jack.h
16
src/jack.h
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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 */
|
|
@ -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')
|
||||
|
|
Loading…
Reference in New Issue