@@ -1,31 +0,0 @@ | |||
SRCS= \ | |||
Server.C \ | |||
Peak_Server.C \ | |||
Timeline_Server.C \ | |||
main.C \ | |||
Audio_File.C \ | |||
Audio_File_SF.C \ | |||
Peaks.C \ | |||
Loggable.C \ | |||
OBJS=$(SRCS:.C=.o) | |||
.PHONEY: all clean install dist valgrind | |||
all: engine | |||
$(OBJS): Makefile | |||
include ../make.inc | |||
engine: $(OBJS) | |||
$(CXX) $(CXXFLAGS) $(INCLUDES) $(LIBS) $(OBJS) -o $@ | |||
clean: | |||
rm -f $(OBJS) engine makedepend | |||
valgrind: | |||
valgrind ./test | |||
include makedepend |
@@ -1,150 +0,0 @@ | |||
/*******************************************************************************/ | |||
/* Copyright (C) 2008 Jonathan Moore Liles */ | |||
/* */ | |||
/* This program is free software; you can redistribute it and/or modify it */ | |||
/* under the terms of the GNU General Public License as published by the */ | |||
/* Free Software Foundation; either version 2 of the License, or (at your */ | |||
/* option) any later version. */ | |||
/* */ | |||
/* This program is distributed in the hope that it will be useful, but WITHOUT */ | |||
/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ | |||
/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ | |||
/* more details. */ | |||
/* */ | |||
/* You should have received a copy of the GNU General Public License along */ | |||
/* with This program; see the file COPYING. If not,write to the Free Software */ | |||
/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | |||
/*******************************************************************************/ | |||
#include "Peak_Server.H" | |||
#include <stdio.h> | |||
#include <string.h> | |||
#include <sys/socket.h> | |||
/* Peak Server | |||
The Peak Server streams peak data to any Timeline Editors or other | |||
clients that ask for it. | |||
Peak request looks like (in ASCII) | |||
> read_peaks "foo.wav" fpp start end | |||
Where "foo.wav" is the base name. (actual filenames may differ if | |||
the channels of the source are 'broken out') | |||
Response looks like (in binary) | |||
> (int)channels (int)length (float)min max min max min max | |||
> min max min max | |||
Were length specifies the number of Peaks (min/max pairs) (for each | |||
channel) The first channel is transmitted first, and any others | |||
follow. | |||
*/ | |||
#include "Audio_File.H" | |||
#include "Peaks.H" | |||
typedef unsigned long tick_t; | |||
#define PEAK_PORT 6100 | |||
void | |||
Peak_Server::handle_new ( int s ) | |||
{ | |||
printf( "new connection\n" ); | |||
} | |||
void | |||
Peak_Server::handle_hang_up ( int s ) | |||
{ | |||
printf( "hangup\n" ); | |||
} | |||
void | |||
Peak_Server::handle_request ( int s, const char *buf, int l ) | |||
{ | |||
printf( "request: %s", buf ); | |||
char source[512]; | |||
float fpp; | |||
tick_t start, end; | |||
enum { GET_INFO, READ_PEAKS } request; | |||
if ( 1 == sscanf( buf, "get_info \"%[^\"]\"", source ) ) | |||
{ | |||
request = GET_INFO; | |||
} | |||
else if ( 4 == sscanf( buf, "read_peaks \"%[^\"]\" %f %lu %lu", source, &fpp, &start, &end ) ) | |||
{ | |||
request = READ_PEAKS; | |||
} | |||
else | |||
{ | |||
const char *err = "error: malformed request\n"; | |||
fprintf( stderr, err ); | |||
send( s, err, strlen( err ), 0 ); | |||
return; | |||
} | |||
Audio_File *af = Audio_File::from_file( source ); | |||
if ( ! af ) | |||
{ | |||
const char *err = "error: could not open source\n"; | |||
send( s, err, strlen( err ), 0 ); | |||
return; | |||
} | |||
switch ( request ) | |||
{ | |||
case GET_INFO: | |||
{ | |||
char buf[128]; | |||
snprintf( buf, sizeof( buf ), "length=%lu channels=%d\n", af->length(), af->channels() ); | |||
send( s, buf, strlen( buf ), 0 ); | |||
break; | |||
} | |||
case READ_PEAKS: | |||
{ | |||
int data[2]; | |||
int peaks; | |||
data[0] = af->channels(); | |||
data[1] = peaks = (end - start) / fpp; | |||
send( s, &data, sizeof( data ), 0 ); | |||
const Peaks *pk = af->peaks(); | |||
int npeaks = pk->fill_buffer( fpp, start, end ); | |||
int channels = af->channels(); | |||
Peak *pbuf = new Peak[ npeaks * channels ]; | |||
/* deinterlace */ | |||
int k = 0; | |||
for ( int i = 0; i < channels; i++ ) | |||
for ( int j = i; j < npeaks * channels; j += channels ) | |||
pbuf[ k++ ] = pk->peakbuf()[ j ]; | |||
/* transmit */ | |||
send( s, pbuf, sizeof( Peak ) * npeaks * channels, 0 ); | |||
delete pbuf; | |||
break; | |||
} | |||
} | |||
// delete af; | |||
} |
@@ -1,40 +0,0 @@ | |||
/*******************************************************************************/ | |||
/* Copyright (C) 2008 Jonathan Moore Liles */ | |||
/* */ | |||
/* This program is free software; you can redistribute it and/or modify it */ | |||
/* under the terms of the GNU General Public License as published by the */ | |||
/* Free Software Foundation; either version 2 of the License, or (at your */ | |||
/* option) any later version. */ | |||
/* */ | |||
/* This program is distributed in the hope that it will be useful, but WITHOUT */ | |||
/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ | |||
/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ | |||
/* more details. */ | |||
/* */ | |||
/* You should have received a copy of the GNU General Public License along */ | |||
/* with This program; see the file COPYING. If not,write to the Free Software */ | |||
/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | |||
/*******************************************************************************/ | |||
#pragma once | |||
#include "Server.H" | |||
class Peak_Server : public Server | |||
{ | |||
protected: | |||
void handle_new ( int s ); | |||
void handle_hang_up ( int s ); | |||
void handle_request ( int s, const char *s, int l ); | |||
public: | |||
Peak_Server ( int port ) : Server ( port ) | |||
{ | |||
fork( true ); | |||
echo( false ); | |||
} | |||
}; |
@@ -1,185 +0,0 @@ | |||
/*******************************************************************************/ | |||
/* Copyright (C) 2008 Jonathan Moore Liles */ | |||
/* */ | |||
/* This program is free software; you can redistribute it and/or modify it */ | |||
/* under the terms of the GNU General Public License as published by the */ | |||
/* Free Software Foundation; either version 2 of the License, or (at your */ | |||
/* option) any later version. */ | |||
/* */ | |||
/* This program is distributed in the hope that it will be useful, but WITHOUT */ | |||
/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ | |||
/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ | |||
/* more details. */ | |||
/* */ | |||
/* You should have received a copy of the GNU General Public License along */ | |||
/* with This program; see the file COPYING. If not,write to the Free Software */ | |||
/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | |||
/*******************************************************************************/ | |||
#include "Server.H" | |||
#include <netdb.h> | |||
#include <netinet/in.h> | |||
#include <unistd.h> | |||
#include <stdlib.h> | |||
#include <stdio.h> | |||
#include <string.h> | |||
#include <errno.h> | |||
#include <sys/socket.h> | |||
#include <sys/types.h> | |||
#include <sys/select.h> | |||
/* Generic TCP server class */ | |||
/* */ | |||
#define MAX_HOST_NAME 512 | |||
/** open a socket listening on TCP port /port/. Returns -1 in case of error. */ | |||
int | |||
Server::listen_on_port ( int port ) | |||
{ | |||
int s; | |||
char name[ MAX_HOST_NAME + 1 ]; | |||
struct sockaddr_in sa; | |||
struct hostent *hp; | |||
memset( &sa, 0, sizeof( sa ) ); | |||
gethostname( name, MAX_HOST_NAME ); | |||
hp = gethostbyname( name ); | |||
sa.sin_family = hp->h_addrtype; | |||
sa.sin_port = htons( port ); | |||
sa.sin_addr.s_addr = INADDR_ANY; | |||
if ( ( s = socket( AF_INET, SOCK_STREAM, 0 ) ) < 0 ) | |||
{ | |||
printf( "Could not create command socket!" ); | |||
return -1; | |||
} | |||
int yes = 1; | |||
if ( setsockopt( s, SOL_SOCKET, SO_REUSEADDR, (char * )&yes, sizeof( int ) ) < 0 ) | |||
{ | |||
close( s ); | |||
return -1; | |||
} | |||
if ( bind( s, (struct sockaddr *)&sa, sizeof( sa ) ) < 0 ) | |||
{ | |||
printf( "bind: %s", strerror( errno ) ); | |||
close( s ); | |||
return -1; | |||
} | |||
listen( s, 1 ); | |||
return s; | |||
} | |||
Server::Server ( int port ) | |||
{ | |||
_port = port; | |||
_echo = false; | |||
_fork = false; | |||
} | |||
void | |||
Server::run ( void ) | |||
{ | |||
int server; /* server socket */ | |||
if ( ( server = listen_on_port( _port ) ) < 0 ) | |||
/* error */; | |||
fd_set master; | |||
fd_set read_fds; | |||
int maxfd; | |||
FD_ZERO( &master ); | |||
FD_ZERO( &read_fds ); | |||
FD_SET( server, &master ); | |||
maxfd = server; | |||
for ( ;; ) | |||
{ | |||
read_fds = master; | |||
if ( select( maxfd + 1, &read_fds, NULL, NULL, NULL ) == -1 ) | |||
{ | |||
perror( "select()" ); | |||
/* error */ | |||
} | |||
/* service connections */ | |||
/* FIXME: there's a better way to do this than cover *all* fds. */ | |||
for ( int i = 2; i < maxfd + 1; ++i ) | |||
{ | |||
if ( FD_ISSET( i, &read_fds ) ) | |||
{ | |||
if ( i == server ) | |||
{ | |||
struct sockaddr_in ca; | |||
socklen_t al = sizeof( ca ); | |||
int c; | |||
if ( ( c = accept( server, (struct sockaddr *)&ca, &al ) ) < 0 ) | |||
perror( "accept()" ); | |||
FD_SET( c, &master ); | |||
if ( c > maxfd ) | |||
maxfd = c; | |||
handle_new( c ); | |||
// printf( "New connection from %s on socket %d\n", inet_ntoa( ca.sin_addr ), c ); | |||
} | |||
else | |||
{ | |||
char buf[ BUFSIZ ]; | |||
int l; | |||
if ( ( l = recv( i, buf, sizeof( buf ), 0 ) ) <= 0 ) | |||
{ | |||
if ( l == 0 ) | |||
{ | |||
handle_hang_up( i ); | |||
} | |||
else | |||
perror( "recv()" ); | |||
close( i ); | |||
FD_CLR( i, &master ); | |||
} | |||
else | |||
{ | |||
if ( echo() ) | |||
/* echo to others */ | |||
for ( int j = maxfd; j-- ; ) | |||
{ | |||
if ( ! FD_ISSET( j, &master ) ) | |||
continue; | |||
if ( j != server && j != i ) | |||
{ | |||
if ( send( j, buf, l, 0 ) < 0 ) | |||
perror( "send()" ); | |||
} | |||
} | |||
buf[ l ] = '\0'; | |||
handle_request( i, buf, l ); | |||
} | |||
} | |||
} | |||
} | |||
} | |||
} |
@@ -1,47 +0,0 @@ | |||
/*******************************************************************************/ | |||
/* Copyright (C) 2008 Jonathan Moore Liles */ | |||
/* */ | |||
/* This program is free software; you can redistribute it and/or modify it */ | |||
/* under the terms of the GNU General Public License as published by the */ | |||
/* Free Software Foundation; either version 2 of the License, or (at your */ | |||
/* option) any later version. */ | |||
/* */ | |||
/* This program is distributed in the hope that it will be useful, but WITHOUT */ | |||
/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ | |||
/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ | |||
/* more details. */ | |||
/* */ | |||
/* You should have received a copy of the GNU General Public License along */ | |||
/* with This program; see the file COPYING. If not,write to the Free Software */ | |||
/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | |||
/*******************************************************************************/ | |||
#pragma once | |||
class Server | |||
{ | |||
int _port; | |||
bool _echo; | |||
bool _fork; | |||
static int listen_on_port ( int port ); | |||
public: | |||
Server ( int port ); | |||
void run ( void ); | |||
bool echo ( void ) { return _echo; } | |||
bool fork ( void ) { return _fork; } | |||
void echo ( bool b ) { _echo = b; } | |||
void fork ( bool b) { _fork = b; } | |||
protected: | |||
virtual void handle_hang_up ( int s ) = 0; | |||
virtual void handle_new ( int s ) = 0; | |||
virtual void handle_request ( int s, const char *s, int l ) = 0; | |||
}; |
@@ -1,76 +0,0 @@ | |||
/*******************************************************************************/ | |||
/* Copyright (C) 2008 Jonathan Moore Liles */ | |||
/* */ | |||
/* This program is free software; you can redistribute it and/or modify it */ | |||
/* under the terms of the GNU General Public License as published by the */ | |||
/* Free Software Foundation; either version 2 of the License, or (at your */ | |||
/* option) any later version. */ | |||
/* */ | |||
/* This program is distributed in the hope that it will be useful, but WITHOUT */ | |||
/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ | |||
/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ | |||
/* more details. */ | |||
/* */ | |||
/* You should have received a copy of the GNU General Public License along */ | |||
/* with This program; see the file COPYING. If not,write to the Free Software */ | |||
/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | |||
/*******************************************************************************/ | |||
// #include "objects.H" | |||
/* #include <sys/socket.h> */ | |||
/* #include <sys/types.h> */ | |||
/* #include <sys/select.h> */ | |||
#include "Timeline_Server.H" | |||
#include <stdio.h> | |||
#include <string.h> | |||
#include <sys/socket.h> | |||
/* Timeline Server. | |||
The timeline server runs in its own thread and manages communication | |||
between the engine and any connected timeline editors. | |||
Its duties are as follows: | |||
* Listen for connections from Timeline Editors on a TCP port. | |||
* Accept 'do' messages from each connection, echoing the change to | |||
all others. | |||
* Keep global engine state in sync with recieved messages (in a | |||
lock-free manner) | |||
* Write do+undo messages to journal. | |||
* Translate "undo" command into the appropriate 'do' messages. | |||
*/ | |||
#define TIMELINE_PORT 6100 | |||
void | |||
Timeline_Server::handle_new ( int s ) | |||
{ | |||
printf( "new connection\n" ); | |||
} | |||
void | |||
Timeline_Server::handle_hang_up ( int s ) | |||
{ | |||
printf( "hangup\n" ); | |||
} | |||
void | |||
Timeline_Server::handle_request ( int s, const char *buf, int l ) | |||
{ | |||
printf( "request: %s", buf ); | |||
// Loggable::do( buf ); | |||
send( s, "fuckoff\n", strlen( "fuckoff\n" ), 0 ); | |||
} |
@@ -1,40 +0,0 @@ | |||
/*******************************************************************************/ | |||
/* Copyright (C) 2008 Jonathan Moore Liles */ | |||
/* */ | |||
/* This program is free software; you can redistribute it and/or modify it */ | |||
/* under the terms of the GNU General Public License as published by the */ | |||
/* Free Software Foundation; either version 2 of the License, or (at your */ | |||
/* option) any later version. */ | |||
/* */ | |||
/* This program is distributed in the hope that it will be useful, but WITHOUT */ | |||
/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ | |||
/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ | |||
/* more details. */ | |||
/* */ | |||
/* You should have received a copy of the GNU General Public License along */ | |||
/* with This program; see the file COPYING. If not,write to the Free Software */ | |||
/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | |||
/*******************************************************************************/ | |||
#pragma once | |||
#include "Server.H" | |||
class Timeline_Server : public Server | |||
{ | |||
protected: | |||
void handle_new ( int s ); | |||
void handle_hang_up ( int s ); | |||
void handle_request ( int s, const char *s, int l ); | |||
public: | |||
Timeline_Server ( int port ) : Server ( port ) | |||
{ | |||
fork( false ); | |||
echo( true ); | |||
} | |||
}; |
@@ -1,27 +0,0 @@ | |||
/*******************************************************************************/ | |||
/* Copyright (C) 2008 Jonathan Moore Liles */ | |||
/* */ | |||
/* This program is free software; you can redistribute it and/or modify it */ | |||
/* under the terms of the GNU General Public License as published by the */ | |||
/* Free Software Foundation; either version 2 of the License, or (at your */ | |||
/* option) any later version. */ | |||
/* */ | |||
/* This program is distributed in the hope that it will be useful, but WITHOUT */ | |||
/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ | |||
/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ | |||
/* more details. */ | |||
/* */ | |||
/* You should have received a copy of the GNU General Public License along */ | |||
/* with This program; see the file COPYING. If not,write to the Free Software */ | |||
/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | |||
/*******************************************************************************/ | |||
/* default peak file resolution, therefore normally any zoom level less than this will | |||
require reading from the audio files directly */ | |||
const int FRAMES_PER_PEAK = 256; |
@@ -1,77 +0,0 @@ | |||
/*******************************************************************************/ | |||
/* Copyright (C) 2008 Jonathan Moore Liles */ | |||
/* */ | |||
/* This program is free software; you can redistribute it and/or modify it */ | |||
/* under the terms of the GNU General Public License as published by the */ | |||
/* Free Software Foundation; either version 2 of the License, or (at your */ | |||
/* option) any later version. */ | |||
/* */ | |||
/* This program is distributed in the hope that it will be useful, but WITHOUT */ | |||
/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ | |||
/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ | |||
/* more details. */ | |||
/* */ | |||
/* You should have received a copy of the GNU General Public License along */ | |||
/* with This program; see the file COPYING. If not,write to the Free Software */ | |||
/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | |||
/*******************************************************************************/ | |||
#include "const.h" | |||
#include "Audio_File.H" | |||
#include "Peaks.H" | |||
#include "Loggable.H" | |||
#include "Timeline_Server.H" | |||
#include "Peak_Server.H" | |||
/* TODO: | |||
Run server process here. | |||
* Manage session file. | |||
* Keep state for all relevant objects (must mirror that in Timeline) | |||
* Listen for incoming connections. | |||
* Send and recieve 'do' messages to client(s), recording do and undo portions to journal. Serve peaks (maybe in a separate process?) | |||
Peak request looks like: | |||
> read_peaks "foo.wav" fpp start end | |||
Response looks like (in binary floats): | |||
> length min max min max min max | |||
State must be communicated to realtime thread locklessly so that: | |||
Realtime: | |||
* Manage JACK transport. | |||
* Manage JACK outputs. | |||
* Stream regions from disk. | |||
* Manage JACK inputs. | |||
* Stream tracks to disk when recording. | |||
* Stream control points as OSC messages. (RT safe?) | |||
*/ | |||
int | |||
main ( int argc, char **argv ) | |||
{ | |||
if ( ! fork() ) | |||
{ | |||
Peak_Server pks( 6111 ); | |||
pks.run(); | |||
exit( 0 ); | |||
} | |||
Timeline_Server tls( 6110 ); | |||
tls.run(); | |||
} |
@@ -1,183 +0,0 @@ | |||
/*******************************************************************************/ | |||
/* Copyright (C) 2008 Jonathan Moore Liles */ | |||
/* */ | |||
/* This program is free software; you can redistribute it and/or modify it */ | |||
/* under the terms of the GNU General Public License as published by the */ | |||
/* Free Software Foundation; either version 2 of the License, or (at your */ | |||
/* option) any later version. */ | |||
/* */ | |||
/* This program is distributed in the hope that it will be useful, but WITHOUT */ | |||
/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ | |||
/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ | |||
/* more details. */ | |||
/* */ | |||
/* You should have received a copy of the GNU General Public License along */ | |||
/* with This program; see the file COPYING. If not,write to the Free Software */ | |||
/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | |||
/*******************************************************************************/ | |||
/* these are all the objects whose state must be recorded, this | |||
includes tracks, regions, etc. Relevant interfaces must be fully compatible | |||
with those in the Timeline program. */ | |||
#include "Audio_File.H" | |||
#include "Loggable.H" | |||
typedef unsigned long nframes_t; | |||
class Track_Widget | |||
{ | |||
protected: | |||
nframes_t _offset; | |||
nframes_t _start; | |||
nframes_t _end; | |||
bool _selected; | |||
}; | |||
/* macros to simplify serialization code */ | |||
#define START( n ) char **sa = (char **)malloc( sizeof( char * ) * (1 + (n) ) ); int i = 0 | |||
#define PUT( fmt, arg ) asprintf( &sa[ i++ ], (fmt), (arg) ) | |||
#define END() sa[ i ] = NULL; return sa; | |||
#define SWITCH do | |||
#define CASE( arg ) if ( ! strcmp( s, ( arg ) ) ) | |||
#define GET( arg, act ) CASE( arg ) { act ; break; } | |||
class Track : public Loggable | |||
{ | |||
}; | |||
class Region : public Loggable, public Track_Widget | |||
{ | |||
Track *_track; | |||
Audio_File *_clip; /* clip this region represents */ | |||
float _scale; /* amplitude adjustment */ | |||
protected: | |||
const char *class_name ( void ) { return "Region"; } | |||
char ** get ( void ) | |||
{ | |||
START( 7 ); | |||
PUT( ":source \"%s\"", _clip ? _clip->name() : "" ); | |||
PUT( ":track 0x%X", _track ? _track->id() : 0 ); | |||
PUT( ":x %lu", _offset ); | |||
PUT( ":l %lu", _start ); | |||
PUT( ":r %lu", _end ); | |||
PUT( ":selected %d", _selected ); | |||
PUT( ":gain %f", _scale ); | |||
END(); | |||
} | |||
void | |||
set ( char **sa ) | |||
{ | |||
for ( int i = 0; sa[i]; ++i ) | |||
{ | |||
char *s = sa[i]; | |||
char *v = s + strlen( s ) + 1; | |||
SWITCH | |||
{ | |||
GET( ":x", _offset = atol( v ) ); | |||
GET( ":l" , _start = atol( v ) ); | |||
GET( ":r", _end = atol( v ) ); | |||
CASE( ":selected" ) | |||
{ | |||
if ( atoi( v ) ) | |||
select(); | |||
else | |||
deselect(); | |||
break; | |||
} | |||
GET( ":gain", _scale = atof( v ) ); | |||
CASE( ":source" ) | |||
{ | |||
if ( ! ( _clip = Audio_File::from_file( v ) ) ) | |||
printf( "Grave error: could not open source \"%s\"\n", v ); | |||
break; | |||
} | |||
CASE( ":track" ) | |||
{ | |||
int i; | |||
sscanf( v, "%X", &i ); | |||
Track *t = (Track*)Loggable::find( i ); | |||
assert( t ); | |||
t->add( this ); | |||
break; | |||
} | |||
} | |||
free( s ); | |||
} | |||
free( sa ); | |||
} | |||
}; | |||
class Time_Point : public Track_Widget | |||
{ | |||
protected: | |||
char ** get ( void ) | |||
{ | |||
START( 4 ); | |||
PUT( ":track 0x%X", _track ? _track->id() : 0 ); | |||
PUT( ":x %lu", _offset ); | |||
PUT( ":beats_per_bar %d", _time.beats_per_bar ); | |||
PUT( ":beat_type %d", _time.beat_type ); | |||
END(); | |||
} | |||
void | |||
set ( char **sa ) | |||
{ | |||
for ( int i = 0; sa[i]; ++i ) | |||
{ | |||
char *s = sa[i]; | |||
char *v = s + strlen( s ) + 1; | |||
SWITCH | |||
{ | |||
GET( ":x", _offset = atol( v ) ); | |||
GET( ":beats_per_bar", _time.beats_per_bar = atoi( v ) ); | |||
GET( ":beat_type", _time.beat_type = atoi( v ) ); | |||
CASE( ":track" ) | |||
{ | |||
int i; | |||
sscanf( v, "%X", &i ); | |||
Track *t = (Track*)Loggable::find( i ); | |||
assert( t ); | |||
t->add( this ); | |||
break; | |||
} | |||
free( s ); | |||
} | |||
free( sa ); | |||
} | |||
} | |||
}; |
@@ -5,7 +5,6 @@ LIBS := -lsndfile `fltk-config --ldflags` | |||
all: all | |||
%: | |||
@ $(MAKE) -s -C Engine CXXFLAGS="$(CXXFLAGS)" LIBS="$(LIBS)" $@ | |||
@ $(MAKE) -s -C FL CXXFLAGS="$(CXXFLAGS)" LIBS="$(LIBS)" $@ | |||
@ $(MAKE) -s -C Timeline CXXFLAGS="$(CXXFLAGS)" LIBS="$(LIBS)" $@ | |||
@ $(MAKE) -s -C Mixer CXXFLAGS="$(CXXFLAGS)" LIBS="$(LIBS)" $@ |
@@ -50,3 +50,29 @@ done: | |||
return a; | |||
} | |||
bool | |||
Audio_File::read_peaks( float fpp, nframes_t start, nframes_t end, int *peaks, Peak **pbuf, int *channels ) | |||
{ | |||
Peaks pk; | |||
pk.clip( this ); | |||
if ( ! pk.open() ) | |||
return false; | |||
*peaks = pk.fill_buffer( fpp, start, end ); | |||
*channels = this->channels(); | |||
*pbuf = new Peak[ *peaks * *channels ]; | |||
/* deinterlace */ | |||
int k = 0; | |||
for ( int i = 0; i < *channels; i++ ) | |||
for ( int j = i; j < *peaks * *channels; j += *channels ) | |||
(*pbuf)[ k++ ] = pk.peakbuf()[ j ]; | |||
return true; | |||
} |
@@ -67,4 +67,7 @@ public: | |||
virtual nframes_t read ( sample_t *buf, int channel, nframes_t len ) = 0; | |||
virtual nframes_t read ( sample_t *buf, int channel, nframes_t start, nframes_t end ) = 0; | |||
bool read_peaks( float fpp, nframes_t start, nframes_t end, int *peaks, Peak **pbuf, int *channels ); | |||
}; |
@@ -88,7 +88,7 @@ Audio_Track::handle ( int m ) | |||
fl_cursor( FL_CURSOR_WAIT ); | |||
Fl::check(); | |||
Clip *c = Clip::from_file( file ); | |||
Audio_File *c = Audio_File::from_file( file ); | |||
fl_cursor( FL_CURSOR_DEFAULT ); | |||
@@ -1,70 +0,0 @@ | |||
/*******************************************************************************/ | |||
/* Copyright (C) 2008 Jonathan Moore Liles */ | |||
/* */ | |||
/* This program is free software; you can redistribute it and/or modify it */ | |||
/* under the terms of the GNU General Public License as published by the */ | |||
/* Free Software Foundation; either version 2 of the License, or (at your */ | |||
/* option) any later version. */ | |||
/* */ | |||
/* This program is distributed in the hope that it will be useful, but WITHOUT */ | |||
/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ | |||
/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ | |||
/* more details. */ | |||
/* */ | |||
/* You should have received a copy of the GNU General Public License along */ | |||
/* with This program; see the file COPYING. If not,write to the Free Software */ | |||
/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | |||
/*******************************************************************************/ | |||
#pragma once | |||
typedef unsigned long nframes_t; | |||
/* a clip is just a stupid wrapper object for communicating with the peak server */ | |||
#include "Peak_Client.H" | |||
extern Peak_Client peak_client; | |||
class Clip | |||
{ | |||
const char *_filename; | |||
nframes_t _length; /* length of file in samples */ | |||
int _channels; | |||
public: | |||
Clip ( ) | |||
{ | |||
_filename = NULL; | |||
_length = _channels = 0; | |||
} | |||
const char *name ( void ) const { return _filename; } | |||
nframes_t length ( void ) const { return _length; } | |||
int channels ( void ) const { return _channels; } | |||
static Clip * | |||
from_file ( const char * filename ) | |||
{ | |||
Clip *c = new Clip; | |||
c->_filename = filename; | |||
if ( ! peak_client.get_info( filename, &c->_length, &c->_channels ) ) | |||
{ | |||
delete c; | |||
return false; | |||
} | |||
return c; | |||
} | |||
bool | |||
read_peaks ( float fpp, nframes_t start, nframes_t end, | |||
int *peaks, Peak **pbuf, int *channels ) | |||
{ | |||
return peak_client.read_peaks( _filename, fpp, start, end, peaks, pbuf, channels ); | |||
} | |||
}; |
@@ -8,8 +8,10 @@ SRCS= \ | |||
Timeline.C \ | |||
Track_Header.C \ | |||
Track_Widget.C \ | |||
Peak_Client.C \ | |||
../Engine/Loggable.C \ | |||
Peaks.C \ | |||
Audio_File.C \ | |||
Audio_File_SF.C \ | |||
Loggable.C \ | |||
OBJS=$(SRCS:.C=.o) | |||
@@ -1,135 +0,0 @@ | |||
/*******************************************************************************/ | |||
/* Copyright (C) 2008 Jonathan Moore Liles */ | |||
/* */ | |||
/* This program is free software; you can redistribute it and/or modify it */ | |||
/* under the terms of the GNU General Public License as published by the */ | |||
/* Free Software Foundation; either version 2 of the License, or (at your */ | |||
/* option) any later version. */ | |||
/* */ | |||
/* This program is distributed in the hope that it will be useful, but WITHOUT */ | |||
/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ | |||
/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ | |||
/* more details. */ | |||
/* */ | |||
/* You should have received a copy of the GNU General Public License along */ | |||
/* with This program; see the file COPYING. If not,write to the Free Software */ | |||
/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | |||
/*******************************************************************************/ | |||
#include <netdb.h> | |||
#include <netinet/in.h> | |||
#include <unistd.h> | |||
#include <stdlib.h> | |||
#include <stdio.h> | |||
#include <string.h> | |||
#include <errno.h> | |||
#include <sys/socket.h> | |||
#include <sys/types.h> | |||
#include <sys/select.h> | |||
#include "Peak_Client.H" | |||
/* An interface to the peak server */ | |||
#define PEAK_PORT 6111 | |||
int | |||
connect_to_host ( const char *host, int port ) | |||
{ | |||
int s; | |||
struct sockaddr_in sa; | |||
struct hostent *hp; | |||
memset( &sa, 0, sizeof( sa ) ); | |||
hp = gethostbyname( host ); | |||
sa.sin_family = hp->h_addrtype; | |||
sa.sin_port = htons( port ); | |||
sa.sin_addr.s_addr = INADDR_ANY; | |||
if ( ( s = socket( AF_INET, SOCK_STREAM, 0 ) ) < 0 ) | |||
{ | |||
perror( "socket()" ); | |||
return -1; | |||
} | |||
if ( connect( s, (struct sockaddr *)&sa, sizeof( sa ) ) < 0 ) | |||
{ | |||
perror( "connect()" ); | |||
close( s ); | |||
return -1; | |||
} | |||
return s; | |||
} | |||
bool | |||
Peak_Client::connect ( const char *host ) | |||
{ | |||
if ( ( _socket = connect_to_host( host, PEAK_PORT ) ) < 0 ) | |||
return false; | |||
return true; | |||
} | |||
bool | |||
Peak_Client::get_info ( const char *source, nframes_t *len, int *channels ) | |||
{ | |||
/* FIXME: needs to handle errors/reconnect */ | |||
char buf[512]; | |||
snprintf( buf, sizeof( buf ), "get_info \"%s\"\n", source ); | |||
send( _socket, buf, strlen( buf ), 0 ); | |||
recv( _socket, buf, sizeof( buf ), 0 ); | |||
if ( sscanf( buf, "length=%lu channels=%d", len, channels ) != 2 ) | |||
return false; | |||
return true; | |||
} | |||
bool | |||
Peak_Client::read_peaks ( const char *source, float fpp, nframes_t start, nframes_t end, | |||
int *peaks, Peak **pbuf, int *channels ) | |||
{ | |||
/* FIXME: needs to handle errors/reconnect */ | |||
char buf[512]; | |||
snprintf( buf, sizeof( buf ), "read_peaks \"%s\" %f %lu %lu\n", source, fpp, start, end ); | |||
send( _socket, buf, strlen( buf ), 0 ); | |||
if ( recv( _socket, buf, sizeof( int ) * 2, 0 ) != sizeof( int ) * 2 ) | |||
{ | |||
printf( "error!\n" ); | |||
return false; | |||
} | |||
if ( ! strncmp( buf, "error", 5 ) ) | |||
return false; | |||
*channels = ((int*)buf)[0]; | |||
*peaks = ((int*)buf)[1]; | |||
if ( ! ( *peaks && *channels ) ) | |||
/* unknown error */; | |||
printf( "reading %d peaks for %d channels\n", *peaks, *channels ); | |||
*pbuf = new Peak[ *peaks * *channels ]; | |||
for ( int i = 0; i < *channels; ++i ) | |||
recv( _socket, *pbuf + (i * *peaks), *peaks * sizeof( Peak ), MSG_WAITALL ); | |||
printf( "done.\n" ); | |||
return true; | |||
} |
@@ -1,40 +0,0 @@ | |||
/*******************************************************************************/ | |||
/* Copyright (C) 2008 Jonathan Moore Liles */ | |||
/* */ | |||
/* This program is free software; you can redistribute it and/or modify it */ | |||
/* under the terms of the GNU General Public License as published by the */ | |||
/* Free Software Foundation; either version 2 of the License, or (at your */ | |||
/* option) any later version. */ | |||
/* */ | |||
/* This program is distributed in the hope that it will be useful, but WITHOUT */ | |||
/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ | |||
/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ | |||
/* more details. */ | |||
/* */ | |||
/* You should have received a copy of the GNU General Public License along */ | |||
/* with This program; see the file COPYING. If not,write to the Free Software */ | |||
/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | |||
/*******************************************************************************/ | |||
#pragma once | |||
int connect_to_host ( const char *host, int port ); | |||
typedef unsigned long nframes_t; | |||
struct Peak { | |||
float min, max; | |||
}; | |||
class Peak_Client | |||
{ | |||
int _socket; | |||
public: | |||
bool connect ( const char *host ); | |||
bool get_info ( const char *source, nframes_t *len, int *channels ); | |||
bool read_peaks ( const char *source, float fpp, nframes_t start, nframes_t end, int *peaks, Peak **pbuf, int *channels ); | |||
}; |
@@ -35,8 +35,6 @@ | |||
using namespace std; | |||
#include "Peak_Client.H" | |||
extern Timeline *timeline; | |||
Fl_Boxtype Region::_box = FL_UP_BOX; | |||
@@ -110,7 +108,7 @@ Region::Region ( const Region & rhs ) | |||
} | |||
/* */ | |||
Region::Region ( Clip *c ) | |||
Region::Region ( Audio_File *c ) | |||
{ | |||
init(); | |||
_clip = c; | |||
@@ -121,7 +119,7 @@ Region::Region ( Clip *c ) | |||
/* used when DND importing */ | |||
Region::Region ( Clip *c, Track *t, nframes_t o ) | |||
Region::Region ( Audio_File *c, Track *t, nframes_t o ) | |||
{ | |||
init(); | |||
_clip = c; | |||
@@ -18,7 +18,7 @@ | |||
/*******************************************************************************/ | |||
#pragma once | |||
#include "Clip.H" | |||
#include "Audio_File.H" | |||
#include "Track.H" | |||
#include "Timeline.H" | |||
@@ -38,7 +38,7 @@ class Region_Base : public Track_Widget | |||
private: | |||
Clip *_clip; /* clip this region represents */ | |||
Audio_File *_clip; /* clip this region represents */ | |||
float _scale; /* amplitude adjustment */ | |||
@@ -100,7 +100,7 @@ protected: | |||
_scale = atof( v ); | |||
else if ( ! strcmp( s, ":source" ) ) | |||
{ | |||
if ( ! ( _clip = Clip::from_file( v ) ) ) | |||
if ( ! ( _clip = Audio_File::from_file( v ) ) ) | |||
{ | |||
printf( "Grave error: could not open source \"%s\"\n", v ); | |||
} | |||
@@ -194,8 +194,8 @@ public: | |||
Fl_Align align ( void ) const { return (Fl_Align)(FL_ALIGN_LEFT | FL_ALIGN_BOTTOM /*| FL_ALIGN_CLIP*/ | FL_ALIGN_INSIDE); } | |||
Region ( const Region & rhs ); | |||
Region ( Clip *c ); | |||
Region ( Clip *c, Track *t, nframes_t o ); | |||
Region ( Audio_File *c ); | |||
Region ( Audio_File *c, Track *t, nframes_t o ); | |||
int handle ( int m ); | |||
void draw_box( int X, int Y, int W, int H ); | |||
@@ -24,7 +24,7 @@ | |||
#include "Timeline.H" | |||
#include "Peak_Client.H" | |||
#include "Peaks.H" | |||
class Waveform { | |||
@@ -53,10 +53,6 @@ | |||
Timeline *timeline; | |||
#include "Peak_Client.H" | |||
Peak_Client peak_client; | |||
void cb_undo ( Fl_Widget *w, void *v ) | |||
{ | |||
Loggable::undo(); | |||
@@ -74,12 +70,6 @@ main ( int argc, char **argv ) | |||
// Fl::scheme( "gtk+" ); | |||
if ( ! peak_client.connect( "localhost" ) ) | |||
{ | |||
fprintf( stderr, "Could not connect to peak server!\n" ); | |||
return 1; | |||
} | |||
Loggable::open( "history" ); | |||
/* welcome to C++ */ | |||
Loggable::register_create( "Region", &Region::create ); | |||