| @@ -0,0 +1,30 @@ | |||||
| SRCS= \ | |||||
| 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 | |||||
| @@ -0,0 +1,32 @@ | |||||
| /*******************************************************************************/ | |||||
| /* 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. */ | |||||
| /*******************************************************************************/ | |||||
| /* Peak Server | |||||
| The peak server streams peak data to any timeline editors or other clients that ask for it. | |||||
| Peak request looks like: | |||||
| > read_peaks "foo.wav" fpp start end | |||||
| Response looks like (in binary floats): | |||||
| > length min max min max min max | |||||
| */ | |||||
| @@ -0,0 +1,177 @@ | |||||
| /*******************************************************************************/ | |||||
| /* 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; | |||||
| } | |||||
| 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 | |||||
| { | |||||
| /* 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( buf, l ); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,37 @@ | |||||
| /*******************************************************************************/ | |||||
| /* 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. */ | |||||
| /*******************************************************************************/ | |||||
| class Server | |||||
| { | |||||
| int _port; | |||||
| static int listen_on_port ( int port ); | |||||
| public: | |||||
| Server ( int port ); | |||||
| void run ( void ); | |||||
| protected: | |||||
| virtual void handle_hang_up ( int s ) = 0; | |||||
| virtual void handle_new ( int s ) = 0; | |||||
| virtual void handle_request ( const char *s, int l ) = 0; | |||||
| }; | |||||
| @@ -0,0 +1,71 @@ | |||||
| /*******************************************************************************/ | |||||
| /* 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> | |||||
| /* 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 ( const char *s, int l ) | |||||
| { | |||||
| printf( "request: %s", s ); | |||||
| } | |||||
| @@ -0,0 +1,38 @@ | |||||
| /*******************************************************************************/ | |||||
| /* 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 ( const char *s, int l ); | |||||
| public: | |||||
| Timeline_Server ( int port ) : Server ( port ) | |||||
| { | |||||
| } | |||||
| }; | |||||
| @@ -0,0 +1,66 @@ | |||||
| /*******************************************************************************/ | |||||
| /* 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" | |||||
| /* 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 ) | |||||
| { | |||||
| Timeline_Server tls( 6110 ); | |||||
| tls.run(); | |||||
| } | |||||
| @@ -5,6 +5,7 @@ LIBS := -lsndfile `fltk-config --ldflags` | |||||
| all: all | all: all | ||||
| %: | %: | ||||
| @ $(MAKE) -s -C Engine CXXFLAGS="$(CXXFLAGS)" LIBS="$(LIBS)" $@ | |||||
| @ $(MAKE) -s -C FL CXXFLAGS="$(CXXFLAGS)" LIBS="$(LIBS)" $@ | @ $(MAKE) -s -C FL CXXFLAGS="$(CXXFLAGS)" LIBS="$(LIBS)" $@ | ||||
| @ $(MAKE) -s -C Timeline CXXFLAGS="$(CXXFLAGS)" LIBS="$(LIBS)" $@ | @ $(MAKE) -s -C Timeline CXXFLAGS="$(CXXFLAGS)" LIBS="$(LIBS)" $@ | ||||
| @ $(MAKE) -s -C Mixer CXXFLAGS="$(CXXFLAGS)" LIBS="$(LIBS)" $@ | @ $(MAKE) -s -C Mixer CXXFLAGS="$(CXXFLAGS)" LIBS="$(LIBS)" $@ | ||||