c9471d34191361bf3a8ec39c01c8767bac266056
[melted] / src / miracle / miracle_unit.c
1 /*
2 * miracle_unit.c -- Transmission Unit Implementation
3 * Copyright (C) 2002-2003 Ushodaya Enterprises Limited
4 * Author: Dan Dennedy <dan@dennedy.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program 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
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24
25 #include <stdio.h>
26 #include <unistd.h>
27 #include <sys/ioctl.h>
28 #include <sys/mman.h>
29 #include <sys/poll.h>
30 #include <sys/types.h>
31 #include <fcntl.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <errno.h>
35 #include <signal.h>
36 #include <limits.h>
37
38 #include <sys/mman.h>
39
40 #include "miracle_unit.h"
41 #include "miracle_log.h"
42 #include "miracle_local.h"
43
44 #include <framework/mlt.h>
45
46 /* Forward references */
47 static void miracle_unit_status_communicate( miracle_unit );
48
49 /** Allocate a new DV transmission unit.
50
51 \return A new miracle_unit handle.
52 */
53
54 miracle_unit miracle_unit_init( int index, char *constructor )
55 {
56 miracle_unit this = NULL;
57 mlt_consumer consumer = NULL;
58
59 char *id = strdup( constructor );
60 char *arg = strchr( id, ':' );
61
62 if ( arg != NULL )
63 *arg ++ = '\0';
64
65 consumer = mlt_factory_consumer( id, arg );
66
67 if ( consumer != NULL )
68 {
69 mlt_playlist playlist = mlt_playlist_init( );
70 this = calloc( sizeof( miracle_unit_t ), 1 );
71 this->properties = mlt_properties_new( );
72 mlt_properties_init( this->properties, this );
73 mlt_properties_set_int( this->properties, "unit", index );
74 mlt_properties_set_int( this->properties, "generation", 0 );
75 mlt_properties_set( this->properties, "constructor", constructor );
76 mlt_properties_set( this->properties, "id", id );
77 mlt_properties_set( this->properties, "arg", arg );
78 mlt_properties_set_data( this->properties, "consumer", consumer, 0, ( mlt_destructor )mlt_consumer_close, NULL );
79 mlt_properties_set_data( this->properties, "playlist", playlist, 0, ( mlt_destructor )mlt_playlist_close, NULL );
80 mlt_consumer_connect( consumer, MLT_PLAYLIST_SERVICE( playlist ) );
81 }
82
83 return this;
84 }
85
86 static char *strip_root( miracle_unit unit, char *file )
87 {
88 mlt_properties properties = unit->properties;
89 char *root = mlt_properties_get( properties, "root" );
90 if ( file != NULL && root != NULL )
91 {
92 int length = strlen( root );
93 if ( root[ length - 1 ] == '/' )
94 length --;
95 if ( !strncmp( file, root, length ) )
96 file += length;
97 }
98 return file;
99 }
100
101 /** Communicate the current status to all threads waiting on the notifier.
102 */
103
104 static void miracle_unit_status_communicate( miracle_unit unit )
105 {
106 if ( unit != NULL )
107 {
108 mlt_properties properties = unit->properties;
109 char *root_dir = mlt_properties_get( properties, "root" );
110 valerie_notifier notifier = mlt_properties_get_data( properties, "notifier", NULL );
111 valerie_status_t status;
112
113 if ( root_dir != NULL && notifier != NULL )
114 {
115 if ( miracle_unit_get_status( unit, &status ) == 0 )
116 /* if ( !( ( status.status == unit_playing || status.status == unit_paused ) &&
117 strcmp( status.clip, "" ) &&
118 !strcmp( status.tail_clip, "" ) &&
119 status.position == 0 &&
120 status.in == 0 &&
121 status.out == 0 ) ) */
122 valerie_notifier_put( notifier, &status );
123 }
124 }
125 }
126
127 /** Set the notifier info
128 */
129
130 void miracle_unit_set_notifier( miracle_unit this, valerie_notifier notifier, char *root_dir )
131 {
132 mlt_properties properties = this->properties;
133 mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL );
134 mlt_properties playlist_properties = MLT_PLAYLIST_PROPERTIES( playlist );
135
136 mlt_properties_set( properties, "root", root_dir );
137 mlt_properties_set_data( properties, "notifier", notifier, 0, NULL, NULL );
138 mlt_properties_set_data( playlist_properties, "notifier_arg", this, 0, NULL, NULL );
139 mlt_properties_set_data( playlist_properties, "notifier", miracle_unit_status_communicate, 0, NULL, NULL );
140
141 miracle_unit_status_communicate( this );
142 }
143
144 /** Create or locate a producer for the file specified.
145 */
146
147 static mlt_producer locate_producer( miracle_unit unit, char *file )
148 {
149 return mlt_factory_producer( "fezzik", file );
150 }
151
152 /** Update the generation count.
153 */
154
155 static void update_generation( miracle_unit unit )
156 {
157 mlt_properties properties = unit->properties;
158 int generation = mlt_properties_get_int( properties, "generation" );
159 mlt_properties_set_int( properties, "generation", ++ generation );
160 }
161
162 /** Wipe all clips on the playlist for this unit.
163 */
164
165 static void clear_unit( miracle_unit unit )
166 {
167 mlt_properties properties = unit->properties;
168 mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL );
169 mlt_producer producer = MLT_PLAYLIST_PRODUCER( playlist );
170
171 mlt_service_lock( MLT_PLAYLIST_SERVICE( playlist ) );
172 mlt_playlist_clear( playlist );
173 mlt_producer_seek( producer, 0 );
174 mlt_service_unlock( MLT_PLAYLIST_SERVICE( playlist ) );
175
176 update_generation( unit );
177 }
178
179 /** Wipe all but the playing clip from the unit.
180 */
181
182 static void clean_unit( miracle_unit unit )
183 {
184 mlt_properties properties = unit->properties;
185 mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL );
186 mlt_playlist_clip_info info;
187 int current = mlt_playlist_current_clip( playlist );
188 mlt_producer producer = MLT_PLAYLIST_PRODUCER( playlist );
189 mlt_position position = mlt_producer_frame( producer );
190 double speed = mlt_producer_get_speed( producer );
191 mlt_playlist_get_clip_info( playlist, &info, current );
192
193 if ( info.producer != NULL )
194 {
195 mlt_properties_inc_ref( MLT_PRODUCER_PROPERTIES( info.producer ) );
196 position -= info.start;
197 clear_unit( unit );
198 mlt_service_lock( MLT_PLAYLIST_SERVICE( playlist ) );
199 mlt_playlist_append_io( playlist, info.producer, info.frame_in, info.frame_out );
200 mlt_producer_seek( producer, position );
201 mlt_producer_set_speed( producer, speed );
202 mlt_service_unlock( MLT_PLAYLIST_SERVICE( playlist ) );
203 mlt_producer_close( info.producer );
204 }
205
206 update_generation( unit );
207 }
208
209 /** Remove everything up to the current clip from the unit.
210 */
211
212 static void wipe_unit( miracle_unit unit )
213 {
214 mlt_properties properties = unit->properties;
215 mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL );
216 mlt_playlist_clip_info info;
217 int current = mlt_playlist_current_clip( playlist );
218 mlt_playlist_get_clip_info( playlist, &info, current );
219
220 if ( info.producer != NULL && info.start > 0 )
221 {
222 mlt_service_lock( MLT_PLAYLIST_SERVICE( playlist ) );
223 mlt_playlist_remove_region( playlist, 0, info.start - 1 );
224 mlt_service_unlock( MLT_PLAYLIST_SERVICE( playlist ) );
225 }
226
227 update_generation( unit );
228 }
229
230 /** Generate a report on all loaded clips.
231 */
232
233 void miracle_unit_report_list( miracle_unit unit, valerie_response response )
234 {
235 int i;
236 mlt_properties properties = unit->properties;
237 int generation = mlt_properties_get_int( properties, "generation" );
238 mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL );
239
240 valerie_response_printf( response, 1024, "%d\n", generation );
241
242 for ( i = 0; i < mlt_playlist_count( playlist ); i ++ )
243 {
244 mlt_playlist_clip_info info;
245 char *title;
246 mlt_playlist_get_clip_info( playlist , &info, i );
247 title = mlt_properties_get( MLT_PRODUCER_PROPERTIES( info.producer ), "title" );
248 if ( title == NULL )
249 title = strip_root( unit, info.resource );
250 valerie_response_printf( response, 10240, "%d \"%s\" %d %d %d %d %.2f\n",
251 i,
252 title,
253 info.frame_in,
254 info.frame_out,
255 info.frame_count,
256 info.length,
257 info.fps );
258 }
259 valerie_response_printf( response, 1024, "\n" );
260 }
261
262 /** Load a clip into the unit clearing existing play list.
263
264 \todo error handling
265 \param unit A miracle_unit handle.
266 \param clip The absolute file name of the clip to load.
267 \param in The starting frame (-1 for 0)
268 \param out The ending frame (-1 for maximum)
269 */
270
271 valerie_error_code miracle_unit_load( miracle_unit unit, char *clip, int32_t in, int32_t out, int flush )
272 {
273 // Now try to create a producer
274 mlt_producer instance = locate_producer( unit, clip );
275
276 if ( instance != NULL )
277 {
278 mlt_properties properties = unit->properties;
279 mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL );
280 int original = mlt_producer_get_playtime( MLT_PLAYLIST_PRODUCER( playlist ) );
281 mlt_service_lock( MLT_PLAYLIST_SERVICE( playlist ) );
282 mlt_playlist_append_io( playlist, instance, in, out );
283 mlt_playlist_remove_region( playlist, 0, original );
284 mlt_service_unlock( MLT_PLAYLIST_SERVICE( playlist ) );
285 miracle_log( LOG_DEBUG, "loaded clip %s", clip );
286 update_generation( unit );
287 miracle_unit_status_communicate( unit );
288 mlt_producer_close( instance );
289 return valerie_ok;
290 }
291
292 return valerie_invalid_file;
293 }
294
295 valerie_error_code miracle_unit_insert( miracle_unit unit, char *clip, int index, int32_t in, int32_t out )
296 {
297 mlt_producer instance = locate_producer( unit, clip );
298
299 if ( instance != NULL )
300 {
301 mlt_properties properties = unit->properties;
302 mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL );
303 fprintf( stderr, "inserting clip %s before %d\n", clip, index );
304 mlt_service_lock( MLT_PLAYLIST_SERVICE( playlist ) );
305 mlt_playlist_insert( playlist, instance, index, in, out );
306 mlt_service_unlock( MLT_PLAYLIST_SERVICE( playlist ) );
307 miracle_log( LOG_DEBUG, "inserted clip %s at %d", clip, index );
308 update_generation( unit );
309 miracle_unit_status_communicate( unit );
310 mlt_producer_close( instance );
311 return valerie_ok;
312 }
313
314 return valerie_invalid_file;
315 }
316
317 valerie_error_code miracle_unit_remove( miracle_unit unit, int index )
318 {
319 mlt_properties properties = unit->properties;
320 mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL );
321 mlt_service_lock( MLT_PLAYLIST_SERVICE( playlist ) );
322 mlt_playlist_remove( playlist, index );
323 mlt_service_unlock( MLT_PLAYLIST_SERVICE( playlist ) );
324 miracle_log( LOG_DEBUG, "removed clip at %d", index );
325 update_generation( unit );
326 miracle_unit_status_communicate( unit );
327 return valerie_ok;
328 }
329
330 valerie_error_code miracle_unit_clean( miracle_unit unit )
331 {
332 clean_unit( unit );
333 miracle_log( LOG_DEBUG, "Cleaned playlist" );
334 miracle_unit_status_communicate( unit );
335 return valerie_ok;
336 }
337
338 valerie_error_code miracle_unit_wipe( miracle_unit unit )
339 {
340 wipe_unit( unit );
341 miracle_log( LOG_DEBUG, "Wiped playlist" );
342 miracle_unit_status_communicate( unit );
343 return valerie_ok;
344 }
345
346 valerie_error_code miracle_unit_clear( miracle_unit unit )
347 {
348 mlt_consumer consumer = mlt_properties_get_data( unit->properties, "consumer", NULL );
349 clear_unit( unit );
350 mlt_consumer_purge( consumer );
351 miracle_log( LOG_DEBUG, "Cleared playlist" );
352 miracle_unit_status_communicate( unit );
353 return valerie_ok;
354 }
355
356 valerie_error_code miracle_unit_move( miracle_unit unit, int src, int dest )
357 {
358 mlt_properties properties = unit->properties;
359 mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL );
360 mlt_service_lock( MLT_PLAYLIST_SERVICE( playlist ) );
361 mlt_playlist_move( playlist, src, dest );
362 mlt_service_unlock( MLT_PLAYLIST_SERVICE( playlist ) );
363 miracle_log( LOG_DEBUG, "moved clip %d to %d", src, dest );
364 update_generation( unit );
365 miracle_unit_status_communicate( unit );
366 return valerie_ok;
367 }
368
369 /** Add a clip to the unit play list.
370
371 \todo error handling
372 \param unit A miracle_unit handle.
373 \param clip The absolute file name of the clip to load.
374 \param in The starting frame (-1 for 0)
375 \param out The ending frame (-1 for maximum)
376 */
377
378 valerie_error_code miracle_unit_append( miracle_unit unit, char *clip, int32_t in, int32_t out )
379 {
380 mlt_producer instance = locate_producer( unit, clip );
381
382 if ( instance != NULL )
383 {
384 mlt_properties properties = unit->properties;
385 mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL );
386 mlt_service_lock( MLT_PLAYLIST_SERVICE( playlist ) );
387 mlt_playlist_append_io( playlist, instance, in, out );
388 miracle_log( LOG_DEBUG, "appended clip %s", clip );
389 mlt_service_unlock( MLT_PLAYLIST_SERVICE( playlist ) );
390 update_generation( unit );
391 miracle_unit_status_communicate( unit );
392 mlt_producer_close( instance );
393 return valerie_ok;
394 }
395
396 return valerie_invalid_file;
397 }
398
399 /** Add an mlt_service to the playlist
400
401 \param unit A miracle_unit handle.
402 \param service the service to add
403 */
404
405 valerie_error_code miracle_unit_append_service( miracle_unit unit, mlt_service service )
406 {
407 mlt_properties properties = unit->properties;
408 mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL );
409 mlt_service_lock( MLT_PLAYLIST_SERVICE( playlist ) );
410 mlt_playlist_append( playlist, ( mlt_producer )service );
411 mlt_service_unlock( MLT_PLAYLIST_SERVICE( playlist ) );
412 miracle_log( LOG_DEBUG, "appended clip" );
413 update_generation( unit );
414 miracle_unit_status_communicate( unit );
415 return valerie_ok;
416 }
417
418 /** Start playing the unit.
419
420 \todo error handling
421 \param unit A miracle_unit handle.
422 \param speed An integer that specifies the playback rate as a
423 percentage multiplied by 100.
424 */
425
426 void miracle_unit_play( miracle_unit_t *unit, int speed )
427 {
428 mlt_properties properties = unit->properties;
429 mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL );
430 mlt_producer producer = MLT_PLAYLIST_PRODUCER( playlist );
431 mlt_consumer consumer = mlt_properties_get_data( unit->properties, "consumer", NULL );
432 mlt_producer_set_speed( producer, ( double )speed / 1000 );
433 mlt_consumer_start( consumer );
434 miracle_unit_status_communicate( unit );
435 }
436
437 /** Stop playback.
438
439 Terminates the dv_pump and halts dv1394 transmission.
440
441 \param unit A miracle_unit handle.
442 */
443
444 void miracle_unit_terminate( miracle_unit unit )
445 {
446 mlt_consumer consumer = mlt_properties_get_data( unit->properties, "consumer", NULL );
447 mlt_playlist playlist = mlt_properties_get_data( unit->properties, "playlist", NULL );
448 mlt_producer producer = MLT_PLAYLIST_PRODUCER( playlist );
449 mlt_producer_set_speed( producer, 0 );
450 mlt_consumer_stop( consumer );
451 miracle_unit_status_communicate( unit );
452 }
453
454 /** Query the status of unit playback.
455
456 \param unit A miracle_unit handle.
457 \return 1 if the unit is not playing, 0 if playing.
458 */
459
460 int miracle_unit_has_terminated( miracle_unit unit )
461 {
462 mlt_consumer consumer = mlt_properties_get_data( unit->properties, "consumer", NULL );
463 return mlt_consumer_is_stopped( consumer );
464 }
465
466 /** Transfer the currently loaded clip to another unit
467 */
468
469 int miracle_unit_transfer( miracle_unit dest_unit, miracle_unit src_unit )
470 {
471 int i;
472 mlt_properties dest_properties = dest_unit->properties;
473 mlt_playlist dest_playlist = mlt_properties_get_data( dest_properties, "playlist", NULL );
474 mlt_properties src_properties = src_unit->properties;
475 mlt_playlist src_playlist = mlt_properties_get_data( src_properties, "playlist", NULL );
476 mlt_playlist tmp_playlist = mlt_playlist_init( );
477
478 for ( i = 0; i < mlt_playlist_count( src_playlist ); i ++ )
479 {
480 mlt_playlist_clip_info info;
481 mlt_playlist_get_clip_info( src_playlist, &info, i );
482 if ( info.producer != NULL )
483 mlt_playlist_append_io( tmp_playlist, info.producer, info.frame_in, info.frame_out );
484 }
485
486 clear_unit( src_unit );
487
488 mlt_service_lock( MLT_PLAYLIST_SERVICE( dest_playlist ) );
489
490 for ( i = 0; i < mlt_playlist_count( tmp_playlist ); i ++ )
491 {
492 mlt_playlist_clip_info info;
493 mlt_playlist_get_clip_info( tmp_playlist, &info, i );
494 if ( info.producer != NULL )
495 mlt_playlist_append_io( dest_playlist, info.producer, info.frame_in, info.frame_out );
496 }
497
498 mlt_service_unlock( MLT_PLAYLIST_SERVICE( dest_playlist ) );
499
500 update_generation( dest_unit );
501 miracle_unit_status_communicate( dest_unit );
502
503 mlt_playlist_close( tmp_playlist );
504
505 return 0;
506 }
507
508 /** Determine if unit is offline.
509 */
510
511 int miracle_unit_is_offline( miracle_unit unit )
512 {
513 return 0;
514 }
515
516 /** Obtain the status for a given unit
517 */
518
519 int miracle_unit_get_status( miracle_unit unit, valerie_status status )
520 {
521 int error = unit == NULL;
522
523 memset( status, 0, sizeof( valerie_status_t ) );
524
525 if ( !error )
526 {
527 mlt_properties properties = unit->properties;
528 mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL );
529 mlt_producer producer = MLT_PLAYLIST_PRODUCER( playlist );
530 mlt_producer clip = mlt_playlist_current( playlist );
531
532 mlt_playlist_clip_info info;
533 int clip_index = mlt_playlist_current_clip( playlist );
534 mlt_playlist_get_clip_info( playlist, &info, clip_index );
535
536 if ( info.resource != NULL && strcmp( info.resource, "" ) )
537 {
538 char *title = mlt_properties_get( MLT_PRODUCER_PROPERTIES( info.producer ), "title" );
539 if ( title == NULL )
540 title = strip_root( unit, info.resource );
541 strncpy( status->clip, title, sizeof( status->clip ) );
542 status->speed = (int)( mlt_producer_get_speed( producer ) * 1000.0 );
543 status->fps = mlt_producer_get_fps( producer );
544 status->in = info.frame_in;
545 status->out = info.frame_out;
546 status->position = mlt_producer_frame( clip );
547 status->length = mlt_producer_get_length( clip );
548 strncpy( status->tail_clip, title, sizeof( status->tail_clip ) );
549 status->tail_in = info.frame_in;
550 status->tail_out = info.frame_out;
551 status->tail_position = mlt_producer_frame( clip );
552 status->tail_length = mlt_producer_get_length( clip );
553 status->clip_index = mlt_playlist_current_clip( playlist );
554 status->seek_flag = 1;
555 }
556
557 status->generation = mlt_properties_get_int( properties, "generation" );
558
559 if ( miracle_unit_has_terminated( unit ) )
560 status->status = unit_stopped;
561 else if ( !strcmp( status->clip, "" ) )
562 status->status = unit_not_loaded;
563 else if ( status->speed == 0 )
564 status->status = unit_paused;
565 else
566 status->status = unit_playing;
567 }
568 else
569 {
570 status->status = unit_undefined;
571 }
572
573 status->unit = mlt_properties_get_int( unit->properties, "unit" );
574
575 return error;
576 }
577
578 /** Change position in the playlist.
579 */
580
581 void miracle_unit_change_position( miracle_unit unit, int clip, int32_t position )
582 {
583 mlt_properties properties = unit->properties;
584 mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL );
585 mlt_producer producer = MLT_PLAYLIST_PRODUCER( playlist );
586 mlt_playlist_clip_info info;
587
588 if ( clip < 0 )
589 {
590 clip = 0;
591 position = 0;
592 }
593 else if ( clip >= mlt_playlist_count( playlist ) )
594 {
595 clip = mlt_playlist_count( playlist ) - 1;
596 position = INT_MAX;
597 }
598
599 if ( mlt_playlist_get_clip_info( playlist, &info, clip ) == 0 )
600 {
601 int32_t frame_start = info.start;
602 int32_t frame_offset = position;
603
604 if ( frame_offset < 0 )
605 frame_offset = info.frame_out;
606 if ( frame_offset < info.frame_in )
607 frame_offset = info.frame_in;
608 if ( frame_offset >= info.frame_out )
609 frame_offset = info.frame_out;
610
611 mlt_producer_seek( producer, frame_start + frame_offset - info.frame_in );
612 }
613
614 miracle_unit_status_communicate( unit );
615 }
616
617 /** Get the index of the current clip.
618 */
619
620 int miracle_unit_get_current_clip( miracle_unit unit )
621 {
622 mlt_properties properties = unit->properties;
623 mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL );
624 int clip_index = mlt_playlist_current_clip( playlist );
625 return clip_index;
626 }
627
628 /** Set a clip's in point
629 */
630
631 int miracle_unit_set_clip_in( miracle_unit unit, int index, int32_t position )
632 {
633 mlt_properties properties = unit->properties;
634 mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL );
635 mlt_playlist_clip_info info;
636 int error = mlt_playlist_get_clip_info( playlist, &info, index );
637
638 if ( error == 0 )
639 {
640 miracle_unit_play( unit, 0 );
641 mlt_service_lock( MLT_PLAYLIST_SERVICE( playlist ) );
642 error = mlt_playlist_resize_clip( playlist, index, position, info.frame_out );
643 mlt_service_unlock( MLT_PLAYLIST_SERVICE( playlist ) );
644 update_generation( unit );
645 miracle_unit_change_position( unit, index, 0 );
646 }
647
648 return error;
649 }
650
651 /** Set a clip's out point.
652 */
653
654 int miracle_unit_set_clip_out( miracle_unit unit, int index, int32_t position )
655 {
656 mlt_properties properties = unit->properties;
657 mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL );
658 mlt_playlist_clip_info info;
659 int error = mlt_playlist_get_clip_info( playlist, &info, index );
660
661 if ( error == 0 )
662 {
663 miracle_unit_play( unit, 0 );
664 mlt_service_lock( MLT_PLAYLIST_SERVICE( playlist ) );
665 error = mlt_playlist_resize_clip( playlist, index, info.frame_in, position );
666 mlt_service_unlock( MLT_PLAYLIST_SERVICE( playlist ) );
667 update_generation( unit );
668 miracle_unit_status_communicate( unit );
669 miracle_unit_change_position( unit, index, -1 );
670 }
671
672 return error;
673 }
674
675 /** Step by specified position.
676 */
677
678 void miracle_unit_step( miracle_unit unit, int32_t offset )
679 {
680 mlt_properties properties = unit->properties;
681 mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL );
682 mlt_producer producer = MLT_PLAYLIST_PRODUCER( playlist );
683 mlt_position position = mlt_producer_frame( producer );
684 mlt_producer_seek( producer, position + offset );
685 }
686
687 /** Set the unit's clip mode regarding in and out points.
688 */
689
690 //void miracle_unit_set_mode( miracle_unit unit, dv_player_clip_mode mode )
691 //{
692 //dv_player player = miracle_unit_get_dv_player( unit );
693 //if ( player != NULL )
694 //dv_player_set_clip_mode( player, mode );
695 //miracle_unit_status_communicate( unit );
696 //}
697
698 /** Get the unit's clip mode regarding in and out points.
699 */
700
701 //dv_player_clip_mode miracle_unit_get_mode( miracle_unit unit )
702 //{
703 //dv_player player = miracle_unit_get_dv_player( unit );
704 //return dv_player_get_clip_mode( player );
705 //}
706
707 /** Set the unit's clip mode regarding eof handling.
708 */
709
710 //void miracle_unit_set_eof_action( miracle_unit unit, dv_player_eof_action action )
711 //{
712 //dv_player player = miracle_unit_get_dv_player( unit );
713 //dv_player_set_eof_action( player, action );
714 //miracle_unit_status_communicate( unit );
715 //}
716
717 /** Get the unit's clip mode regarding eof handling.
718 */
719
720 //dv_player_eof_action miracle_unit_get_eof_action( miracle_unit unit )
721 //{
722 //dv_player player = miracle_unit_get_dv_player( unit );
723 //return dv_player_get_eof_action( player );
724 //}
725
726 int miracle_unit_set( miracle_unit unit, char *name_value )
727 {
728 mlt_properties properties = NULL;
729
730 if ( strncmp( name_value, "consumer.", 9 ) )
731 {
732 mlt_playlist playlist = mlt_properties_get_data( unit->properties, "playlist", NULL );
733 properties = MLT_PLAYLIST_PROPERTIES( playlist );
734 }
735 else
736 {
737 mlt_consumer consumer = mlt_properties_get_data( unit->properties, "consumer", NULL );
738 properties = MLT_CONSUMER_PROPERTIES( consumer );
739 name_value += 9;
740 }
741
742 return mlt_properties_parse( properties, name_value );
743 }
744
745 char *miracle_unit_get( miracle_unit unit, char *name )
746 {
747 mlt_playlist playlist = mlt_properties_get_data( unit->properties, "playlist", NULL );
748 mlt_properties properties = MLT_PLAYLIST_PROPERTIES( playlist );
749 return mlt_properties_get( properties, name );
750 }
751
752 /** Release the unit
753
754 \todo error handling
755 \param unit A miracle_unit handle.
756 */
757
758 void miracle_unit_close( miracle_unit unit )
759 {
760 if ( unit != NULL )
761 {
762 miracle_log( LOG_DEBUG, "closing unit..." );
763 miracle_unit_terminate( unit );
764 mlt_properties_close( unit->properties );
765 free( unit );
766 miracle_log( LOG_DEBUG, "... unit closed." );
767 }
768 }
769