From 93ce31ea03d23ab8c258db8c1a1da2f2199962fe Mon Sep 17 00:00:00 2001 From: Jonathan Moore Liles Date: Tue, 25 Mar 2008 02:08:13 -0500 Subject: [PATCH] Work on server aspect of Engine. --- Engine/Makefile | 30 +++++++ Engine/Peak_Server.C | 32 +++++++ Engine/Server.C | 177 +++++++++++++++++++++++++++++++++++++++ Engine/Server.H | 37 ++++++++ Engine/Timeline_Server.C | 71 ++++++++++++++++ Engine/Timeline_Server.H | 38 +++++++++ Engine/main.C | 66 +++++++++++++++ Makefile | 1 + 8 files changed, 452 insertions(+) create mode 100644 Engine/Makefile create mode 100644 Engine/Peak_Server.C create mode 100644 Engine/Server.C create mode 100644 Engine/Server.H create mode 100644 Engine/Timeline_Server.C create mode 100644 Engine/Timeline_Server.H create mode 100644 Engine/main.C diff --git a/Engine/Makefile b/Engine/Makefile new file mode 100644 index 0000000..bdac3e5 --- /dev/null +++ b/Engine/Makefile @@ -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 diff --git a/Engine/Peak_Server.C b/Engine/Peak_Server.C new file mode 100644 index 0000000..436a719 --- /dev/null +++ b/Engine/Peak_Server.C @@ -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 + + */ diff --git a/Engine/Server.C b/Engine/Server.C new file mode 100644 index 0000000..1cda3bd --- /dev/null +++ b/Engine/Server.C @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* 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 ); + } + } + } + } + } +} diff --git a/Engine/Server.H b/Engine/Server.H new file mode 100644 index 0000000..77b1e08 --- /dev/null +++ b/Engine/Server.H @@ -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; +}; diff --git a/Engine/Timeline_Server.C b/Engine/Timeline_Server.C new file mode 100644 index 0000000..fa78f63 --- /dev/null +++ b/Engine/Timeline_Server.C @@ -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 */ +/* #include */ +/* #include */ + +#include "Timeline_Server.H" + +#include + +/* 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 ); +} diff --git a/Engine/Timeline_Server.H b/Engine/Timeline_Server.H new file mode 100644 index 0000000..1865f86 --- /dev/null +++ b/Engine/Timeline_Server.H @@ -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 ) + { + } +}; diff --git a/Engine/main.C b/Engine/main.C new file mode 100644 index 0000000..854654b --- /dev/null +++ b/Engine/main.C @@ -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(); +} diff --git a/Makefile b/Makefile index 8e20835..5ea1d62 100644 --- a/Makefile +++ b/Makefile @@ -5,6 +5,7 @@ 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)" $@