c76112d8e015e1f593371510c82f60ab0a06fd32
[melted] / src / valerie / valerie.c
1 /*
2 * valerie.c -- High Level Client API for miracle
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 <stdarg.h>
26
27 /* Application header files */
28 #include "valerie.h"
29 #include "valerie_tokeniser.h"
30 #include "valerie_util.h"
31
32 /** Initialise the valerie structure.
33 */
34
35 valerie valerie_init( valerie_parser parser )
36 {
37 valerie this = malloc( sizeof( valerie_t ) );
38 if ( this != NULL )
39 {
40 memset( this, 0, sizeof( valerie_t ) );
41 this->parser = parser;
42 }
43 return this;
44 }
45
46 /** Set the response structure associated to the last command.
47 */
48
49 static void valerie_set_last_response( valerie this, valerie_response response )
50 {
51 if ( this != NULL )
52 {
53 if ( this->last_response != NULL )
54 valerie_response_close( this->last_response );
55 this->last_response = response;
56 }
57 }
58
59 /** Connect to the parser.
60 */
61
62 valerie_error_code valerie_connect( valerie this )
63 {
64 valerie_error_code error = valerie_server_unavailable;
65 valerie_response response = valerie_parser_connect( this->parser );
66 if ( response != NULL )
67 {
68 valerie_set_last_response( this, response );
69 if ( valerie_response_get_error_code( response ) == 100 )
70 error = valerie_ok;
71 }
72 return error;
73 }
74
75 /** Interpret a non-context sensitive error code.
76 */
77
78 static valerie_error_code valerie_get_error_code( valerie this, valerie_response response )
79 {
80 valerie_error_code error = valerie_server_unavailable;
81 switch( valerie_response_get_error_code( response ) )
82 {
83 case -1:
84 error = valerie_server_unavailable;
85 break;
86 case -2:
87 error = valerie_no_response;
88 break;
89 case 200:
90 case 201:
91 case 202:
92 error = valerie_ok;
93 break;
94 case 400:
95 error = valerie_invalid_command;
96 break;
97 case 401:
98 error = valerie_server_timeout;
99 break;
100 case 402:
101 error = valerie_missing_argument;
102 break;
103 case 403:
104 error = valerie_unit_unavailable;
105 break;
106 case 404:
107 error = valerie_invalid_file;
108 break;
109 default:
110 case 500:
111 error = valerie_unknown_error;
112 break;
113 }
114 return error;
115 }
116
117 /** Execute a command.
118 */
119
120 valerie_error_code valerie_execute( valerie this, size_t size, char *format, ... )
121 {
122 valerie_error_code error = valerie_server_unavailable;
123 char *command = malloc( size );
124 if ( this != NULL && command != NULL )
125 {
126 va_list list;
127 va_start( list, format );
128 if ( vsnprintf( command, size, format, list ) != 0 )
129 {
130 valerie_response response = valerie_parser_execute( this->parser, command );
131 valerie_set_last_response( this, response );
132 error = valerie_get_error_code( this, response );
133 }
134 else
135 {
136 error = valerie_invalid_command;
137 }
138 va_end( list );
139 }
140 else
141 {
142 error = valerie_malloc_failed;
143 }
144 free( command );
145 return error;
146 }
147
148 /** Execute a command.
149 */
150
151 valerie_error_code valerie_receive( valerie this, char *doc, size_t size, char *format, ... )
152 {
153 valerie_error_code error = valerie_server_unavailable;
154 char *command = malloc( size );
155 if ( this != NULL && command != NULL )
156 {
157 va_list list;
158 va_start( list, format );
159 if ( vsnprintf( command, size, format, list ) != 0 )
160 {
161 valerie_response response = valerie_parser_received( this->parser, command, doc );
162 valerie_set_last_response( this, response );
163 error = valerie_get_error_code( this, response );
164 }
165 else
166 {
167 error = valerie_invalid_command;
168 }
169 va_end( list );
170 }
171 else
172 {
173 error = valerie_malloc_failed;
174 }
175 free( command );
176 return error;
177 }
178
179 /** Execute a command.
180 */
181
182 valerie_error_code valerie_push( valerie this, mlt_service service, size_t size, char *format, ... )
183 {
184 valerie_error_code error = valerie_server_unavailable;
185 char *command = malloc( size );
186 if ( this != NULL && command != NULL )
187 {
188 va_list list;
189 va_start( list, format );
190 if ( vsnprintf( command, size, format, list ) != 0 )
191 {
192 valerie_response response = valerie_parser_push( this->parser, command, service );
193 valerie_set_last_response( this, response );
194 error = valerie_get_error_code( this, response );
195 }
196 else
197 {
198 error = valerie_invalid_command;
199 }
200 va_end( list );
201 }
202 else
203 {
204 error = valerie_malloc_failed;
205 }
206 free( command );
207 return error;
208 }
209
210 /** Set a global property.
211 */
212
213 valerie_error_code valerie_set( valerie this, char *property, char *value )
214 {
215 return valerie_execute( this, 1024, "SET %s=%s", property, value );
216 }
217
218 /** Get a global property.
219 */
220
221 valerie_error_code valerie_get( valerie this, char *property, char *value, int length )
222 {
223 valerie_error_code error = valerie_execute( this, 1024, "GET %s", property );
224 if ( error == valerie_ok )
225 {
226 valerie_response response = valerie_get_last_response( this );
227 strncpy( value, valerie_response_get_line( response, 1 ), length );
228 }
229 return error;
230 }
231
232 /** Run a script.
233 */
234
235 valerie_error_code valerie_run( valerie this, char *file )
236 {
237 return valerie_execute( this, 10240, "RUN \"%s\"", file );
238 }
239
240 /** Add a unit.
241 */
242
243 valerie_error_code valerie_unit_add( valerie this, char *guid, int *unit )
244 {
245 valerie_error_code error = valerie_execute( this, 1024, "UADD %s", guid );
246 if ( error == valerie_ok )
247 {
248 int length = valerie_response_count( this->last_response );
249 char *line = valerie_response_get_line( this->last_response, length - 1 );
250 if ( line == NULL || sscanf( line, "U%d", unit ) != 1 )
251 error = valerie_unit_creation_failed;
252 }
253 else
254 {
255 if ( error == valerie_unknown_error )
256 error = valerie_unit_creation_failed;
257 }
258 return error;
259 }
260
261 /** Load a file on the specified unit.
262 */
263
264 valerie_error_code valerie_unit_load( valerie this, int unit, char *file )
265 {
266 return valerie_execute( this, 10240, "LOAD U%d \"%s\"", unit, file );
267 }
268
269 static void valerie_interpret_clip_offset( char *output, valerie_clip_offset offset, int clip )
270 {
271 switch( offset )
272 {
273 case valerie_absolute:
274 sprintf( output, "%d", clip );
275 break;
276 case valerie_relative:
277 if ( clip < 0 )
278 sprintf( output, "%d", clip );
279 else
280 sprintf( output, "+%d", clip );
281 break;
282 }
283 }
284
285 /** Load a file on the specified unit with the specified in/out points.
286 */
287
288 valerie_error_code valerie_unit_load_clipped( valerie this, int unit, char *file, int32_t in, int32_t out )
289 {
290 return valerie_execute( this, 10240, "LOAD U%d \"%s\" %d %d", unit, file, in, out );
291 }
292
293 /** Load a file on the specified unit at the end of the current pump.
294 */
295
296 valerie_error_code valerie_unit_load_back( valerie this, int unit, char *file )
297 {
298 return valerie_execute( this, 10240, "LOAD U%d \"!%s\"", unit, file );
299 }
300
301 /** Load a file on the specified unit at the end of the pump with the specified in/out points.
302 */
303
304 valerie_error_code valerie_unit_load_back_clipped( valerie this, int unit, char *file, int32_t in, int32_t out )
305 {
306 return valerie_execute( this, 10240, "LOAD U%d \"!%s\" %d %d", unit, file, in, out );
307 }
308
309 /** Append a file on the specified unit.
310 */
311
312 valerie_error_code valerie_unit_append( valerie this, int unit, char *file, int32_t in, int32_t out )
313 {
314 return valerie_execute( this, 10240, "APND U%d \"%s\" %d %d", unit, file, in, out );
315 }
316
317 /** Push a service on to a unit.
318 */
319
320 valerie_error_code valerie_unit_receive( valerie this, int unit, char *command, char *doc )
321 {
322 return valerie_receive( this, doc, 10240, "PUSH U%d %s", unit, command );
323 }
324
325 /** Push a service on to a unit.
326 */
327
328 valerie_error_code valerie_unit_push( valerie this, int unit, char *command, mlt_service service )
329 {
330 return valerie_push( this, service, 10240, "PUSH U%d %s", unit, command );
331 }
332
333 /** Clean the unit - this function removes all but the currently playing clip.
334 */
335
336 valerie_error_code valerie_unit_clean( valerie this, int unit )
337 {
338 return valerie_execute( this, 1024, "CLEAN U%d", unit );
339 }
340
341 /** Clear the unit - this function removes all clips.
342 */
343
344 valerie_error_code valerie_unit_clear( valerie this, int unit )
345 {
346 return valerie_execute( this, 1024, "CLEAR U%d", unit );
347 }
348
349 /** Move clips on the units playlist.
350 */
351
352 valerie_error_code valerie_unit_clip_move( valerie this, int unit, valerie_clip_offset src_offset, int src, valerie_clip_offset dest_offset, int dest )
353 {
354 char temp1[ 100 ];
355 char temp2[ 100 ];
356 valerie_interpret_clip_offset( temp1, src_offset, src );
357 valerie_interpret_clip_offset( temp2, dest_offset, dest );
358 return valerie_execute( this, 1024, "MOVE U%d %s %s", unit, temp1, temp2 );
359 }
360
361 /** Remove clip at the specified position.
362 */
363
364 valerie_error_code valerie_unit_clip_remove( valerie this, int unit, valerie_clip_offset offset, int clip )
365 {
366 char temp[ 100 ];
367 valerie_interpret_clip_offset( temp, offset, clip );
368 return valerie_execute( this, 1024, "REMOVE U%d %s", unit, temp );
369 }
370
371 /** Remove the currently playing clip.
372 */
373
374 valerie_error_code valerie_unit_remove_current_clip( valerie this, int unit )
375 {
376 return valerie_execute( this, 1024, "REMOVE U%d", unit );
377 }
378
379 /** Insert clip at the specified position.
380 */
381
382 valerie_error_code valerie_unit_clip_insert( valerie this, int unit, valerie_clip_offset offset, int clip, char *file, int32_t in, int32_t out )
383 {
384 char temp[ 100 ];
385 valerie_interpret_clip_offset( temp, offset, clip );
386 return valerie_execute( this, 1024, "INSERT U%d \"%s\" %s %d %d", unit, file, temp, in, out );
387 }
388
389 /** Play the unit at normal speed.
390 */
391
392 valerie_error_code valerie_unit_play( valerie this, int unit )
393 {
394 return valerie_execute( this, 1024, "PLAY U%d 1000", unit );
395 }
396
397 /** Play the unit at specified speed.
398 */
399
400 valerie_error_code valerie_unit_play_at_speed( valerie this, int unit, int speed )
401 {
402 return valerie_execute( this, 10240, "PLAY U%d %d", unit, speed );
403 }
404
405 /** Stop playback on the specified unit.
406 */
407
408 valerie_error_code valerie_unit_stop( valerie this, int unit )
409 {
410 return valerie_execute( this, 1024, "STOP U%d", unit );
411 }
412
413 /** Pause playback on the specified unit.
414 */
415
416 valerie_error_code valerie_unit_pause( valerie this, int unit )
417 {
418 return valerie_execute( this, 1024, "PAUSE U%d", unit );
419 }
420
421 /** Rewind the specified unit.
422 */
423
424 valerie_error_code valerie_unit_rewind( valerie this, int unit )
425 {
426 return valerie_execute( this, 1024, "REW U%d", unit );
427 }
428
429 /** Fast forward the specified unit.
430 */
431
432 valerie_error_code valerie_unit_fast_forward( valerie this, int unit )
433 {
434 return valerie_execute( this, 1024, "FF U%d", unit );
435 }
436
437 /** Step by the number of frames on the specified unit.
438 */
439
440 valerie_error_code valerie_unit_step( valerie this, int unit, int32_t step )
441 {
442 return valerie_execute( this, 1024, "STEP U%d %d", unit, step );
443 }
444
445 /** Goto the specified frame on the specified unit.
446 */
447
448 valerie_error_code valerie_unit_goto( valerie this, int unit, int32_t position )
449 {
450 return valerie_execute( this, 1024, "GOTO U%d %d", unit, position );
451 }
452
453 /** Goto the specified frame in the clip on the specified unit.
454 */
455
456 valerie_error_code valerie_unit_clip_goto( valerie this, int unit, valerie_clip_offset offset, int clip, int32_t position )
457 {
458 char temp[ 100 ];
459 valerie_interpret_clip_offset( temp, offset, clip );
460 return valerie_execute( this, 1024, "GOTO U%d %d %s", unit, position, temp );
461 }
462
463 /** Set the in point of the loaded file on the specified unit.
464 */
465
466 valerie_error_code valerie_unit_set_in( valerie this, int unit, int32_t in )
467 {
468 return valerie_execute( this, 1024, "SIN U%d %d", unit, in );
469 }
470
471 /** Set the in point of the clip on the specified unit.
472 */
473
474 valerie_error_code valerie_unit_clip_set_in( valerie this, int unit, valerie_clip_offset offset, int clip, int32_t in )
475 {
476 char temp[ 100 ];
477 valerie_interpret_clip_offset( temp, offset, clip );
478 return valerie_execute( this, 1024, "SIN U%d %d %s", unit, in, temp );
479 }
480
481 /** Set the out point of the loaded file on the specified unit.
482 */
483
484 valerie_error_code valerie_unit_set_out( valerie this, int unit, int32_t out )
485 {
486 return valerie_execute( this, 1024, "SOUT U%d %d", unit, out );
487 }
488
489 /** Set the out point of the clip on the specified unit.
490 */
491
492 valerie_error_code valerie_unit_clip_set_out( valerie this, int unit, valerie_clip_offset offset, int clip, int32_t in )
493 {
494 char temp[ 100 ];
495 valerie_interpret_clip_offset( temp, offset, clip );
496 return valerie_execute( this, 1024, "SOUT U%d %d %s", unit, in, temp );
497 }
498
499 /** Clear the in point of the loaded file on the specified unit.
500 */
501
502 valerie_error_code valerie_unit_clear_in( valerie this, int unit )
503 {
504 return valerie_execute( this, 1024, "SIN U%d -1", unit );
505 }
506
507 /** Clear the out point of the loaded file on the specified unit.
508 */
509
510 valerie_error_code valerie_unit_clear_out( valerie this, int unit )
511 {
512 return valerie_execute( this, 1024, "SOUT U%d -1", unit );
513 }
514
515 /** Clear the in and out points on the loaded file on the specified unit.
516 */
517
518 valerie_error_code valerie_unit_clear_in_out( valerie this, int unit )
519 {
520 valerie_error_code error = valerie_unit_clear_out( this, unit );
521 if ( error == valerie_ok )
522 error = valerie_unit_clear_in( this, unit );
523 return error;
524 }
525
526 /** Set a unit configuration property.
527 */
528
529 valerie_error_code valerie_unit_set( valerie this, int unit, char *name, char *value )
530 {
531 return valerie_execute( this, 1024, "USET U%d %s=%s", unit, name, value );
532 }
533
534 /** Get a unit configuration property.
535 */
536
537 valerie_error_code valerie_unit_get( valerie this, int unit, char *name )
538 {
539 return valerie_execute( this, 1024, "UGET U%d %s", unit, name );
540 }
541
542 /** Get a units status.
543 */
544
545 valerie_error_code valerie_unit_status( valerie this, int unit, valerie_status status )
546 {
547 valerie_error_code error = valerie_execute( this, 1024, "USTA U%d", unit );
548 int error_code = valerie_response_get_error_code( this->last_response );
549
550 memset( status, 0, sizeof( valerie_status_t ) );
551 status->unit = unit;
552 if ( error_code == 202 && valerie_response_count( this->last_response ) == 2 )
553 valerie_status_parse( status, valerie_response_get_line( this->last_response, 1 ) );
554 else if ( error_code == 403 )
555 status->status = unit_undefined;
556
557 return error;
558 }
559
560 /** Transfer the current settings of unit src to unit dest.
561 */
562
563 valerie_error_code valerie_unit_transfer( valerie this, int src, int dest )
564 {
565 return valerie_execute( this, 1024, "XFER U%d U%d", src, dest );
566 }
567
568 /** Obtain the parsers notifier.
569 */
570
571 valerie_notifier valerie_get_notifier( valerie this )
572 {
573 if ( this != NULL )
574 return valerie_parser_get_notifier( this->parser );
575 else
576 return NULL;
577 }
578
579 /** List the contents of the specified directory.
580 */
581
582 valerie_dir valerie_dir_init( valerie this, char *directory )
583 {
584 valerie_dir dir = malloc( sizeof( valerie_dir_t ) );
585 if ( dir != NULL )
586 {
587 memset( dir, 0, sizeof( valerie_dir_t ) );
588 dir->directory = strdup( directory );
589 dir->response = valerie_parser_executef( this->parser, "CLS \"%s\"", directory );
590 }
591 return dir;
592 }
593
594 /** Return the error code associated to the dir.
595 */
596
597 valerie_error_code valerie_dir_get_error_code( valerie_dir dir )
598 {
599 if ( dir != NULL )
600 return valerie_get_error_code( NULL, dir->response );
601 else
602 return valerie_malloc_failed;
603 }
604
605 /** Get a particular file entry in the directory.
606 */
607
608 valerie_error_code valerie_dir_get( valerie_dir dir, int index, valerie_dir_entry entry )
609 {
610 valerie_error_code error = valerie_ok;
611 memset( entry, 0, sizeof( valerie_dir_entry_t ) );
612 if ( index < valerie_dir_count( dir ) )
613 {
614 char *line = valerie_response_get_line( dir->response, index + 1 );
615 valerie_tokeniser tokeniser = valerie_tokeniser_init( );
616 valerie_tokeniser_parse_new( tokeniser, line, " " );
617
618 if ( valerie_tokeniser_count( tokeniser ) > 0 )
619 {
620 valerie_util_strip( valerie_tokeniser_get_string( tokeniser, 0 ), '\"' );
621 strcpy( entry->full, dir->directory );
622 if ( entry->full[ strlen( entry->full ) - 1 ] != '/' )
623 strcat( entry->full, "/" );
624 strcpy( entry->name, valerie_tokeniser_get_string( tokeniser, 0 ) );
625 strcat( entry->full, entry->name );
626
627 switch ( valerie_tokeniser_count( tokeniser ) )
628 {
629 case 1:
630 entry->dir = 1;
631 break;
632 case 2:
633 entry->size = strtoull( valerie_tokeniser_get_string( tokeniser, 1 ), NULL, 10 );
634 break;
635 default:
636 error = valerie_invalid_file;
637 break;
638 }
639 }
640 valerie_tokeniser_close( tokeniser );
641 }
642 return error;
643 }
644
645 /** Get the number of entries in the directory
646 */
647
648 int valerie_dir_count( valerie_dir dir )
649 {
650 if ( dir != NULL && valerie_response_count( dir->response ) >= 2 )
651 return valerie_response_count( dir->response ) - 2;
652 else
653 return -1;
654 }
655
656 /** Close the directory structure.
657 */
658
659 void valerie_dir_close( valerie_dir dir )
660 {
661 if ( dir != NULL )
662 {
663 free( dir->directory );
664 valerie_response_close( dir->response );
665 free( dir );
666 }
667 }
668
669 /** List the playlist of the specified unit.
670 */
671
672 valerie_list valerie_list_init( valerie this, int unit )
673 {
674 valerie_list list = calloc( 1, sizeof( valerie_list_t ) );
675 if ( list != NULL )
676 {
677 list->response = valerie_parser_executef( this->parser, "LIST U%d", unit );
678 if ( valerie_response_count( list->response ) >= 2 )
679 list->generation = atoi( valerie_response_get_line( list->response, 1 ) );
680 }
681 return list;
682 }
683
684 /** Return the error code associated to the list.
685 */
686
687 valerie_error_code valerie_list_get_error_code( valerie_list list )
688 {
689 if ( list != NULL )
690 return valerie_get_error_code( NULL, list->response );
691 else
692 return valerie_malloc_failed;
693 }
694
695 /** Get a particular file entry in the list.
696 */
697
698 valerie_error_code valerie_list_get( valerie_list list, int index, valerie_list_entry entry )
699 {
700 valerie_error_code error = valerie_ok;
701 memset( entry, 0, sizeof( valerie_list_entry_t ) );
702 if ( index < valerie_list_count( list ) )
703 {
704 char *line = valerie_response_get_line( list->response, index + 2 );
705 valerie_tokeniser tokeniser = valerie_tokeniser_init( );
706 valerie_tokeniser_parse_new( tokeniser, line, " " );
707
708 if ( valerie_tokeniser_count( tokeniser ) > 0 )
709 {
710 entry->clip = atoi( valerie_tokeniser_get_string( tokeniser, 0 ) );
711 valerie_util_strip( valerie_tokeniser_get_string( tokeniser, 1 ), '\"' );
712 strcpy( entry->full, valerie_tokeniser_get_string( tokeniser, 1 ) );
713 entry->in = atol( valerie_tokeniser_get_string( tokeniser, 2 ) );
714 entry->out = atol( valerie_tokeniser_get_string( tokeniser, 3 ) );
715 entry->max = atol( valerie_tokeniser_get_string( tokeniser, 4 ) );
716 entry->size = atol( valerie_tokeniser_get_string( tokeniser, 5 ) );
717 entry->fps = atof( valerie_tokeniser_get_string( tokeniser, 6 ) );
718 }
719 valerie_tokeniser_close( tokeniser );
720 }
721 return error;
722 }
723
724 /** Get the number of entries in the list
725 */
726
727 int valerie_list_count( valerie_list list )
728 {
729 if ( list != NULL && valerie_response_count( list->response ) >= 3 )
730 return valerie_response_count( list->response ) - 3;
731 else
732 return -1;
733 }
734
735 /** Close the list structure.
736 */
737
738 void valerie_list_close( valerie_list list )
739 {
740 if ( list != NULL )
741 {
742 valerie_response_close( list->response );
743 free( list );
744 }
745 }
746
747 /** List the currently connected nodes.
748 */
749
750 valerie_nodes valerie_nodes_init( valerie this )
751 {
752 valerie_nodes nodes = malloc( sizeof( valerie_nodes_t ) );
753 if ( nodes != NULL )
754 {
755 memset( nodes, 0, sizeof( valerie_nodes_t ) );
756 nodes->response = valerie_parser_executef( this->parser, "NLS" );
757 }
758 return nodes;
759 }
760
761 /** Return the error code associated to the nodes list.
762 */
763
764 valerie_error_code valerie_nodes_get_error_code( valerie_nodes nodes )
765 {
766 if ( nodes != NULL )
767 return valerie_get_error_code( NULL, nodes->response );
768 else
769 return valerie_malloc_failed;
770 }
771
772 /** Get a particular node entry.
773 */
774
775 valerie_error_code valerie_nodes_get( valerie_nodes nodes, int index, valerie_node_entry entry )
776 {
777 valerie_error_code error = valerie_ok;
778 memset( entry, 0, sizeof( valerie_node_entry_t ) );
779 if ( index < valerie_nodes_count( nodes ) )
780 {
781 char *line = valerie_response_get_line( nodes->response, index + 1 );
782 valerie_tokeniser tokeniser = valerie_tokeniser_init( );
783 valerie_tokeniser_parse_new( tokeniser, line, " " );
784
785 if ( valerie_tokeniser_count( tokeniser ) == 3 )
786 {
787 entry->node = atoi( valerie_tokeniser_get_string( tokeniser, 0 ) );
788 strncpy( entry->guid, valerie_tokeniser_get_string( tokeniser, 1 ), sizeof( entry->guid ) );
789 valerie_util_strip( valerie_tokeniser_get_string( tokeniser, 2 ), '\"' );
790 strncpy( entry->name, valerie_tokeniser_get_string( tokeniser, 2 ), sizeof( entry->name ) );
791 }
792
793 valerie_tokeniser_close( tokeniser );
794 }
795 return error;
796 }
797
798 /** Get the number of nodes
799 */
800
801 int valerie_nodes_count( valerie_nodes nodes )
802 {
803 if ( nodes != NULL && valerie_response_count( nodes->response ) >= 2 )
804 return valerie_response_count( nodes->response ) - 2;
805 else
806 return -1;
807 }
808
809 /** Close the nodes structure.
810 */
811
812 void valerie_nodes_close( valerie_nodes nodes )
813 {
814 if ( nodes != NULL )
815 {
816 valerie_response_close( nodes->response );
817 free( nodes );
818 }
819 }
820
821 /** List the currently defined units.
822 */
823
824 valerie_units valerie_units_init( valerie this )
825 {
826 valerie_units units = malloc( sizeof( valerie_units_t ) );
827 if ( units != NULL )
828 {
829 memset( units, 0, sizeof( valerie_units_t ) );
830 units->response = valerie_parser_executef( this->parser, "ULS" );
831 }
832 return units;
833 }
834
835 /** Return the error code associated to the nodes list.
836 */
837
838 valerie_error_code valerie_units_get_error_code( valerie_units units )
839 {
840 if ( units != NULL )
841 return valerie_get_error_code( NULL, units->response );
842 else
843 return valerie_malloc_failed;
844 }
845
846 /** Get a particular unit entry.
847 */
848
849 valerie_error_code valerie_units_get( valerie_units units, int index, valerie_unit_entry entry )
850 {
851 valerie_error_code error = valerie_ok;
852 memset( entry, 0, sizeof( valerie_unit_entry_t ) );
853 if ( index < valerie_units_count( units ) )
854 {
855 char *line = valerie_response_get_line( units->response, index + 1 );
856 valerie_tokeniser tokeniser = valerie_tokeniser_init( );
857 valerie_tokeniser_parse_new( tokeniser, line, " " );
858
859 if ( valerie_tokeniser_count( tokeniser ) == 4 )
860 {
861 entry->unit = atoi( valerie_tokeniser_get_string( tokeniser, 0 ) + 1 );
862 entry->node = atoi( valerie_tokeniser_get_string( tokeniser, 1 ) );
863 strncpy( entry->guid, valerie_tokeniser_get_string( tokeniser, 2 ), sizeof( entry->guid ) );
864 entry->online = atoi( valerie_tokeniser_get_string( tokeniser, 3 ) );
865 }
866
867 valerie_tokeniser_close( tokeniser );
868 }
869 return error;
870 }
871
872 /** Get the number of units
873 */
874
875 int valerie_units_count( valerie_units units )
876 {
877 if ( units != NULL && valerie_response_count( units->response ) >= 2 )
878 return valerie_response_count( units->response ) - 2;
879 else
880 return -1;
881 }
882
883 /** Close the units structure.
884 */
885
886 void valerie_units_close( valerie_units units )
887 {
888 if ( units != NULL )
889 {
890 valerie_response_close( units->response );
891 free( units );
892 }
893 }
894
895 /** Get the response of the last command executed.
896 */
897
898 valerie_response valerie_get_last_response( valerie this )
899 {
900 return this->last_response;
901 }
902
903 /** Obtain a printable message associated to the error code provided.
904 */
905
906 char *valerie_error_description( valerie_error_code error )
907 {
908 char *msg = "Unrecognised error";
909 switch( error )
910 {
911 case valerie_ok:
912 msg = "OK";
913 break;
914 case valerie_malloc_failed:
915 msg = "Memory allocation error";
916 break;
917 case valerie_unknown_error:
918 msg = "Unknown error";
919 break;
920 case valerie_no_response:
921 msg = "No response obtained";
922 break;
923 case valerie_invalid_command:
924 msg = "Invalid command";
925 break;
926 case valerie_server_timeout:
927 msg = "Communications with server timed out";
928 break;
929 case valerie_missing_argument:
930 msg = "Missing argument";
931 break;
932 case valerie_server_unavailable:
933 msg = "Unable to communicate with server";
934 break;
935 case valerie_unit_creation_failed:
936 msg = "Unit creation failed";
937 break;
938 case valerie_unit_unavailable:
939 msg = "Unit unavailable";
940 break;
941 case valerie_invalid_file:
942 msg = "Invalid file";
943 break;
944 case valerie_invalid_position:
945 msg = "Invalid position";
946 break;
947 }
948 return msg;
949 }
950
951 /** Close the valerie structure.
952 */
953
954 void valerie_close( valerie this )
955 {
956 if ( this != NULL )
957 {
958 valerie_set_last_response( this, NULL );
959 free( this );
960 }
961 }