2 * valerie_remote.c -- Remote Parser
3 * Copyright (C) 2002-2003 Ushodaya Enterprises Limited
4 * Author: Charles Yates <charles.yates@pandora.be>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 /* System header files */
29 /* Application header files */
30 #include <framework/mlt.h>
31 #include "valerie_remote.h"
32 #include "valerie_socket.h"
33 #include "valerie_tokeniser.h"
34 #include "valerie_util.h"
36 /** Private valerie_remote structure.
44 valerie_socket socket;
45 valerie_socket status;
47 valerie_parser parser;
48 pthread_mutex_t mutex;
51 *valerie_remote, valerie_remote_t;
53 /** Forward declarations.
56 static valerie_response valerie_remote_connect( valerie_remote );
57 static valerie_response valerie_remote_execute( valerie_remote, char * );
58 static valerie_response valerie_remote_receive( valerie_remote, char *, char * );
59 static valerie_response valerie_remote_push( valerie_remote, char *, mlt_service );
60 static void valerie_remote_close( valerie_remote );
61 static int valerie_remote_read_response( valerie_socket, valerie_response );
63 /** DV Parser constructor.
66 valerie_parser valerie_parser_init_remote( char *server, int port )
68 valerie_parser parser = calloc( 1, sizeof( valerie_parser_t ) );
69 valerie_remote remote = calloc( 1, sizeof( valerie_remote_t ) );
73 parser->connect = (parser_connect)valerie_remote_connect;
74 parser->execute = (parser_execute)valerie_remote_execute;
75 parser->push = (parser_push)valerie_remote_push;
76 parser->received = (parser_received)valerie_remote_receive;
77 parser->close = (parser_close)valerie_remote_close;
78 parser->real = remote;
82 remote->parser = parser;
83 remote->server = strdup( server );
85 pthread_mutex_init( &remote->mutex, NULL );
91 /** Thread for receiving and distributing the status information.
94 static void *valerie_remote_status_thread( void *arg )
96 valerie_remote remote = arg;
100 valerie_tokeniser tokeniser = valerie_tokeniser_init( );
101 valerie_notifier notifier = valerie_parser_get_notifier( remote->parser );
102 valerie_status_t status;
105 valerie_socket_write_data( remote->status, "STATUS\r\n", 8 );
107 while ( !remote->terminated &&
108 ( length = valerie_socket_read_data( remote->status, temp + offset, sizeof( temp ) ) ) >= 0 )
110 if ( strchr( temp, '\n' ) == NULL )
116 valerie_tokeniser_parse_new( tokeniser, temp, "\n" );
117 for ( index = 0; index < valerie_tokeniser_count( tokeniser ); index ++ )
119 char *line = valerie_tokeniser_get_string( tokeniser, index );
120 if ( line[ strlen( line ) - 1 ] == '\r' )
122 valerie_util_chomp( line );
123 valerie_status_parse( &status, line );
124 valerie_notifier_put( notifier, &status );
128 strcpy( temp, line );
129 offset = strlen( temp );
134 valerie_notifier_disconnected( notifier );
135 valerie_tokeniser_close( tokeniser );
136 remote->terminated = 1;
141 /** Forward reference.
144 static void valerie_remote_disconnect( valerie_remote remote );
146 /** Connect to the server.
149 static valerie_response valerie_remote_connect( valerie_remote remote )
151 valerie_response response = NULL;
153 valerie_remote_disconnect( remote );
155 if ( !remote->connected )
157 signal( SIGPIPE, SIG_IGN );
159 remote->socket = valerie_socket_init( remote->server, remote->port );
160 remote->status = valerie_socket_init( remote->server, remote->port );
162 if ( valerie_socket_connect( remote->socket ) == 0 )
164 response = valerie_response_init( );
165 valerie_remote_read_response( remote->socket, response );
168 if ( response != NULL && valerie_socket_connect( remote->status ) == 0 )
170 valerie_response status_response = valerie_response_init( );
171 valerie_remote_read_response( remote->status, status_response );
172 if ( valerie_response_get_error_code( status_response ) == 100 )
173 pthread_create( &remote->thread, NULL, valerie_remote_status_thread, remote );
174 valerie_response_close( status_response );
175 remote->connected = 1;
182 /** Execute the command.
185 static valerie_response valerie_remote_execute( valerie_remote remote, char *command )
187 valerie_response response = NULL;
188 pthread_mutex_lock( &remote->mutex );
189 if ( valerie_socket_write_data( remote->socket, command, strlen( command ) ) == strlen( command ) )
191 response = valerie_response_init( );
192 valerie_socket_write_data( remote->socket, "\r\n", 2 );
193 valerie_remote_read_response( remote->socket, response );
195 pthread_mutex_unlock( &remote->mutex );
199 /** Push a westley document to the server.
202 static valerie_response valerie_remote_receive( valerie_remote remote, char *command, char *buffer )
204 valerie_response response = NULL;
205 pthread_mutex_lock( &remote->mutex );
206 if ( valerie_socket_write_data( remote->socket, command, strlen( command ) ) == strlen( command ) )
209 int length = strlen( buffer );
210 response = valerie_response_init( );
211 valerie_socket_write_data( remote->socket, "\r\n", 2 );
212 sprintf( temp, "%d", length );
213 valerie_socket_write_data( remote->socket, temp, strlen( temp ) );
214 valerie_socket_write_data( remote->socket, "\r\n", 2 );
215 valerie_socket_write_data( remote->socket, buffer, length );
216 valerie_socket_write_data( remote->socket, "\r\n", 2 );
217 valerie_remote_read_response( remote->socket, response );
219 pthread_mutex_unlock( &remote->mutex );
223 /** Push a producer to the server.
226 static valerie_response valerie_remote_push( valerie_remote remote, char *command, mlt_service service )
228 valerie_response response = NULL;
229 if ( service != NULL )
231 mlt_consumer consumer = mlt_factory_consumer( "westley", "buffer" );
232 mlt_properties properties = mlt_consumer_properties( consumer );
234 mlt_consumer_connect( consumer, service );
235 mlt_consumer_start( consumer );
236 buffer = mlt_properties_get( properties, "buffer" );
237 response = valerie_remote_receive( remote, command, buffer );
238 mlt_consumer_close( consumer );
246 static void valerie_remote_disconnect( valerie_remote remote )
248 if ( remote != NULL && remote->terminated )
250 if ( remote->connected )
251 pthread_join( remote->thread, NULL );
252 valerie_socket_close( remote->status );
253 valerie_socket_close( remote->socket );
254 remote->connected = 0;
255 remote->terminated = 0;
259 /** Close the parser.
262 static void valerie_remote_close( valerie_remote remote )
264 if ( remote != NULL )
266 remote->terminated = 1;
267 valerie_remote_disconnect( remote );
268 pthread_mutex_destroy( &remote->mutex );
269 free( remote->server );
277 static int valerie_remote_read_response( valerie_socket socket, valerie_response response )
283 while ( !terminated && ( length = valerie_socket_read_data( socket, temp, 10240 ) ) >= 0 )
286 temp[ length ] = '\0';
287 valerie_response_write( response, temp, length );
288 position = valerie_response_count( response ) - 1;
289 if ( position < 0 || temp[ strlen( temp ) - 1 ] != '\n' )
291 switch( valerie_response_get_error_code( response ) )
295 terminated = !strcmp( valerie_response_get_line( response, position ), "" );
298 terminated = valerie_response_count( response ) >= 2;