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