]> git.sesse.net Git - mlt/blob - src/valerie/valerie_remote.c
Big modification - switch to macros for parent class access
[mlt] / src / valerie / valerie_remote.c
1 /*
2  * valerie_remote.c -- Remote Parser
3  * Copyright (C) 2002-2003 Ushodaya Enterprises Limited
4  * Author: Charles Yates <charles.yates@pandora.be>
5  *
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.
10  *
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.
15  *
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
19  */
20
21 /* System header files */
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <signal.h>
26 #include <errno.h>
27 #include <pthread.h>
28
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"
35
36 /** Private valerie_remote structure.
37 */
38
39 typedef struct
40 {
41         int terminated;
42         char *server;
43         int port;
44         valerie_socket socket;
45         valerie_socket status;
46         pthread_t thread;
47         valerie_parser parser;
48         pthread_mutex_t mutex;
49         int connected;
50 }
51 *valerie_remote, valerie_remote_t;
52
53 /** Forward declarations.
54 */
55
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 );
62
63 /** DV Parser constructor.
64 */
65
66 valerie_parser valerie_parser_init_remote( char *server, int port )
67 {
68         valerie_parser parser = calloc( 1, sizeof( valerie_parser_t ) );
69         valerie_remote remote = calloc( 1, sizeof( valerie_remote_t ) );
70
71         if ( parser != NULL )
72         {
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;
79
80                 if ( remote != NULL )
81                 {
82                         remote->parser = parser;
83                         remote->server = strdup( server );
84                         remote->port = port;
85                         pthread_mutex_init( &remote->mutex, NULL );
86                 }
87         }
88         return parser;
89 }
90
91 /** Thread for receiving and distributing the status information.
92 */
93
94 static void *valerie_remote_status_thread( void *arg )
95 {
96         valerie_remote remote = arg;
97         char temp[ 10240 ];
98         int length = 0;
99         int offset = 0;
100         valerie_tokeniser tokeniser = valerie_tokeniser_init( );
101         valerie_notifier notifier = valerie_parser_get_notifier( remote->parser );
102         valerie_status_t status;
103         int index = 0;
104
105         valerie_socket_write_data( remote->status, "STATUS\r\n", 8 );
106
107         while ( !remote->terminated && 
108                         ( length = valerie_socket_read_data( remote->status, temp + offset, sizeof( temp ) ) ) >= 0 )
109         {
110                 if ( strchr( temp, '\n' ) == NULL )
111                 {
112                         offset = length;
113                         continue;
114                 }
115                 offset = 0;
116                 valerie_tokeniser_parse_new( tokeniser, temp, "\n" );
117                 for ( index = 0; index < valerie_tokeniser_count( tokeniser ); index ++ )
118                 {
119                         char *line = valerie_tokeniser_get_string( tokeniser, index );
120                         if ( line[ strlen( line ) - 1 ] == '\r' )
121                         {
122                                 valerie_util_chomp( line );
123                                 valerie_status_parse( &status, line );
124                                 valerie_notifier_put( notifier, &status );
125                         }
126                         else
127                         {
128                                 strcpy( temp, line );
129                                 offset = strlen( temp );
130                         }
131                 }
132         }
133
134         valerie_notifier_disconnected( notifier );
135         valerie_tokeniser_close( tokeniser );
136         remote->terminated = 1;
137
138         return NULL;
139 }
140
141 /** Forward reference.
142 */
143
144 static void valerie_remote_disconnect( valerie_remote remote );
145
146 /** Connect to the server.
147 */
148
149 static valerie_response valerie_remote_connect( valerie_remote remote )
150 {
151         valerie_response response = NULL;
152
153         valerie_remote_disconnect( remote );
154
155         if ( !remote->connected )
156         {
157                 signal( SIGPIPE, SIG_IGN );
158
159                 remote->socket = valerie_socket_init( remote->server, remote->port );
160                 remote->status = valerie_socket_init( remote->server, remote->port );
161
162                 if ( valerie_socket_connect( remote->socket ) == 0 )
163                 {
164                         response = valerie_response_init( );
165                         valerie_remote_read_response( remote->socket, response );
166                 }
167
168                 if ( response != NULL && valerie_socket_connect( remote->status ) == 0 )
169                 {
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;
176                 }
177         }
178
179         return response;
180 }
181
182 /** Execute the command.
183 */
184
185 static valerie_response valerie_remote_execute( valerie_remote remote, char *command )
186 {
187         valerie_response response = NULL;
188         pthread_mutex_lock( &remote->mutex );
189         if ( valerie_socket_write_data( remote->socket, command, strlen( command ) ) == strlen( command ) )
190         {
191                 response = valerie_response_init( );
192                 valerie_socket_write_data( remote->socket, "\r\n", 2 );
193                 valerie_remote_read_response( remote->socket, response );
194         }
195         pthread_mutex_unlock( &remote->mutex );
196         return response;
197 }
198
199 /** Push a westley document to the server.
200 */
201
202 static valerie_response valerie_remote_receive( valerie_remote remote, char *command, char *buffer )
203 {
204         valerie_response response = NULL;
205         pthread_mutex_lock( &remote->mutex );
206         if ( valerie_socket_write_data( remote->socket, command, strlen( command ) ) == strlen( command ) )
207         {
208                 char temp[ 20 ];
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 );
218         }
219         pthread_mutex_unlock( &remote->mutex );
220         return response;
221 }
222
223 /** Push a producer to the server.
224 */
225
226 static valerie_response valerie_remote_push( valerie_remote remote, char *command, mlt_service service )
227 {
228         valerie_response response = NULL;
229         if ( service != NULL )
230         {
231                 mlt_consumer consumer = mlt_factory_consumer( "westley", "buffer" );
232                 mlt_properties properties = MLT_CONSUMER_PROPERTIES( consumer );
233                 char *buffer = NULL;
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 );
239         }
240         return response;
241 }
242
243 /** Disconnect.
244 */
245
246 static void valerie_remote_disconnect( valerie_remote remote )
247 {
248         if ( remote != NULL && remote->terminated )
249         {
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;
256         }
257 }
258
259 /** Close the parser.
260 */
261
262 static void valerie_remote_close( valerie_remote remote )
263 {
264         if ( remote != NULL )
265         {
266                 remote->terminated = 1;
267                 valerie_remote_disconnect( remote );
268                 pthread_mutex_destroy( &remote->mutex );
269                 free( remote->server );
270                 free( remote );
271         }
272 }
273
274 /** Read response. 
275 */
276
277 static int valerie_remote_read_response( valerie_socket socket, valerie_response response )
278 {
279         char temp[ 10240 ];
280         int length;
281         int terminated = 0;
282
283         while ( !terminated && ( length = valerie_socket_read_data( socket, temp, 10240 ) ) >= 0 )
284         {
285                 int position = 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' )
290                         continue;
291                 switch( valerie_response_get_error_code( response ) )
292                 {
293                         case 201:
294                         case 500:
295                                 terminated = !strcmp( valerie_response_get_line( response, position ), "" );
296                                 break;
297                         case 202:
298                                 terminated = valerie_response_count( response ) >= 2;
299                                 break;
300                         default:
301                                 terminated = 1;
302                                 break;
303                 }
304         }
305
306         return 0;
307 }