2 * dvunit.c -- DV Transmission Unit Implementation
3 * Copyright (C) 2002-2003 Ushodaya Enterprises Limited
4 * Author: Dan Dennedy <dan@dennedy.org>
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.
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.
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.
27 #include <sys/ioctl.h>
30 #include <sys/types.h>
37 #include <libdv/dv1394.h>
38 #include <libraw1394/raw1394.h>
39 #include <libavc1394/avc1394_vcr.h>
44 #include "dvframepool.h"
49 #include "raw1394util.h"
53 /* Forward references */
54 static void dv_unit_status_communicate( dv_unit
);
56 /** dv1394 device file names based upon devfs default names. */
58 static char *devices
[4][4] = {
60 "/dev/ieee1394/dv/host0/NTSC/in",
61 "/dev/ieee1394/dv/host0/NTSC/out",
62 "/dev/ieee1394/dv/host0/PAL/in",
63 "/dev/ieee1394/dv/host0/PAL/out",
65 "/dev/ieee1394/dv/host1/NTSC/in",
66 "/dev/ieee1394/dv/host1/NTSC/out",
67 "/dev/ieee1394/dv/host1/PAL/in",
68 "/dev/ieee1394/dv/host1/PAL/out"
70 "/dev/ieee1394/dv/host2/NTSC/in",
71 "/dev/ieee1394/dv/host2/NTSC/out",
72 "/dev/ieee1394/dv/host2/PAL/in",
73 "/dev/ieee1394/dv/host2/PAL/out"
75 "/dev/ieee1394/dv/host3/NTSC/in",
76 "/dev/ieee1394/dv/host3/NTSC/out",
77 "/dev/ieee1394/dv/host3/PAL/in",
78 "/dev/ieee1394/dv/host3/PAL/out"
82 static int device_count
[4] = {0,0,0,0};
84 /** Allocate a new DV transmission unit.
86 \param dv1394d_fd The file descriptor of a dv1394 device file to
88 \param guid The node GUID of the receiving device.
89 \param channel The channel to use for transmission.
90 \return A new dv_unit handle.
93 dv_unit
dv_unit_init( octlet_t guid
, int channel
)
95 dv_unit unit
= malloc( sizeof( dv_unit_t
) );
100 memset( unit
, 0, sizeof( dv_unit_t
) );
102 unit
->buffer_size
= 25;
103 unit
->is_terminated
= 1;
104 unit
->channel
= channel
;
105 unit
->dv1394_fd
= -1;
106 unit
->n_frames
= DV1394_MAX_FRAMES
/ 2;
109 /* get a raw1394 handle for plug control */
110 if ( ( node_id
= raw1394_find_node( &(unit
->raw1394
), guid
) ) != -1 )
112 if ( dv_unit_online( unit
) == 1 )
113 dv1394d_log( LOG_DEBUG
, "Added online unit with GUID %08x%08x",
114 (quadlet_t
) (unit
->guid
>>32), (quadlet_t
) (unit
->guid
& 0xffffffff) );
117 dv_unit_close( unit
);
123 dv1394d_log( LOG_DEBUG
, "Added offline unit with GUID %08x%08x",
124 (quadlet_t
) (unit
->guid
>>32), (quadlet_t
) (unit
->guid
& 0xffffffff) );
130 /** Allow stdin to feed the unit (redundant now that senddv has been dropped).
133 void dv_unit_allow_stdin( dv_unit unit
, int flag
)
135 unit
->allow_stdin
= flag
;
138 /** Override the default buffer/pump size - this must be done prior to the pumps
142 void dv_unit_set_buffer_size( dv_unit unit
, int size
)
146 if ( unit
->pump
== NULL
)
147 unit
->buffer_size
= size
;
149 unit
->buffer_size
= dv_pump_resize( unit
->pump
, size
);
153 int dv_unit_get_buffer_size( dv_unit unit
)
155 return unit
->buffer_size
;
158 void dv_unit_set_n_frames( dv_unit unit
, int size
)
160 if ( size
> 0 && size
<= DV1394_MAX_FRAMES
/ 2 )
161 unit
->n_frames
= size
;
164 int dv_unit_get_n_frames( dv_unit unit
)
166 return unit
->n_frames
;
169 void dv_unit_set_n_fill( dv_unit unit
, int size
)
174 int dv_unit_get_n_fill( dv_unit unit
)
179 /** Set the notifier info
182 void dv_unit_set_notifier( dv_unit
this, dv1394_notifier notifier
, char *root_dir
)
184 this->notifier
= notifier
;
185 this->root_dir
= root_dir
;
186 dv_unit_status_communicate( this );
189 /** Communicate the current status to all threads waiting on the notifier.
192 static void dv_unit_status_communicate( dv_unit unit
)
194 if ( unit
!= NULL
&& unit
->notifier
!= NULL
&& unit
->root_dir
!= NULL
)
196 dv1394_status_t status
;
197 if ( dv_unit_get_status( unit
, &status
) == 0 )
198 if ( !( ( status
.status
== unit_playing
|| status
.status
== unit_paused
) &&
199 strcmp( status
.clip
, "" ) &&
200 !strcmp( status
.tail_clip
, "" ) &&
201 status
.position
== 0 &&
204 dv1394_notifier_put( unit
->notifier
, &status
);
208 /** Load a clip into the unit clearing existing play list.
211 \param unit A dv_unit handle.
212 \param clip The absolute file name of the clip to load.
213 \param in The starting frame (-1 for 0)
214 \param out The ending frame (-1 for maximum)
217 dv_error_code
dv_unit_load( dv_unit unit
, const char *clip
, long in
, long out
, int flush
)
219 dv_player player
= dv_unit_get_dv_player( unit
);
220 dv_error_code error
= dv_player_get_error( player
);
221 if ( error
== dv_pump_ok
)
223 error
= dv_player_replace_file( player
, (char*) clip
, in
, out
, flush
);
224 dv1394d_log( LOG_DEBUG
, "loaded clip %s", clip
);
225 if ( unit
->is_terminated
)
226 dv_unit_status_communicate( unit
);
231 dv_error_code
dv_unit_insert( dv_unit unit
, const char *clip
, int index
, long in
, long out
)
233 dv_player player
= dv_unit_get_dv_player( unit
);
234 dv_error_code error
= dv_player_get_error( player
);
235 if ( error
== dv_pump_ok
)
237 error
= dv_player_insert_file( player
, (char*) clip
, index
, in
, out
);
238 dv1394d_log( LOG_DEBUG
, "inserted clip %s", clip
);
239 if ( unit
->is_terminated
)
240 dv_unit_status_communicate( unit
);
245 dv_error_code
dv_unit_remove( dv_unit unit
, int index
)
247 dv_player player
= dv_unit_get_dv_player( unit
);
248 dv_error_code error
= dv_player_get_error( player
);
249 if ( error
== dv_pump_ok
)
251 error
= dv_player_remove_clip( player
, index
);
252 dv1394d_log( LOG_DEBUG
, "removed clip %d", index
);
253 if ( unit
->is_terminated
)
254 dv_unit_status_communicate( unit
);
259 dv_error_code
dv_unit_clean( dv_unit unit
)
261 dv_player player
= dv_unit_get_dv_player( unit
);
262 dv_error_code error
= dv_player_get_error( player
);
263 if ( error
== dv_pump_ok
)
265 error
= dv_player_clean( player
);
266 dv1394d_log( LOG_DEBUG
, "Cleaned playlist" );
267 if ( unit
->is_terminated
)
268 dv_unit_status_communicate( unit
);
273 dv_error_code
dv_unit_move( dv_unit unit
, int src
, int dest
)
275 dv_player player
= dv_unit_get_dv_player( unit
);
276 dv_error_code error
= dv_player_get_error( player
);
277 if ( error
== dv_pump_ok
)
279 error
= dv_player_move_clip( player
, src
, dest
);
280 dv1394d_log( LOG_DEBUG
, "moved clip %d to %d", src
, dest
);
281 if ( unit
->is_terminated
)
282 dv_unit_status_communicate( unit
);
287 /** Add a clip to the unit play list.
290 \param unit A dv_unit handle.
291 \param clip The absolute file name of the clip to load.
292 \param in The starting frame (-1 for 0)
293 \param out The ending frame (-1 for maximum)
296 dv_error_code
dv_unit_append( dv_unit unit
, const char *clip
, long in
, long out
)
298 dv_player player
= dv_unit_get_dv_player( unit
);
299 dv_error_code error
= dv_player_add_file( player
, (char*) clip
, in
, out
);
300 dv_unit_status_communicate( unit
);
304 void *output_cleanup( void *arg
)
307 if ( unit
!= NULL
&& unit
->mmap
!= NULL
)
309 unit
->is_terminated
= 1;
310 dv_unit_status_communicate( unit
);
311 munmap( unit
->mmap
, unit
->mmap_length
);
312 /* this actually stops transmission as opposed to allowing the
313 last frame to loop in the OHCI DMA context. */
314 ioctl( unit
->dv1394_fd
, DV1394_SHUTDOWN
, NULL
);
320 /** The dv1394 transmission thread.
322 \param arg A dv_unit handle.
325 static void *output( void *arg
)
328 dv_frame frames
[ DV1394_MAX_FRAMES
];
329 int frames_dropped
= 0; /* count of total frames dropped (repeated) */
330 struct dv1394_status status
;
332 int n_fill
= unit
->n_fill
;
333 int n_frames
= unit
->n_frames
;
335 /* Determine the number of frames to wait for/fill on each iteration */
338 else if ( n_fill
> unit
->n_frames
)
339 n_fill
= n_frames
/ 2;
341 unit
->mmap
= mmap( NULL
,unit
->mmap_length
,PROT_WRITE
,MAP_SHARED
,unit
->dv1394_fd
,0 );
342 if ( unit
->mmap
== MAP_FAILED
|| unit
->mmap
== NULL
)
348 pthread_cleanup_push( output_cleanup
, (void *)arg
);
350 while ( dv_pump_get_available_output_count( unit
->pump
) ||
351 !( dv_unit_has_terminated( unit
) || dv_pump_has_terminated( unit
->pump
) ) )
355 if ( ioctl( unit
->dv1394_fd
, DV1394_WAIT_FRAMES
, n_fill
) < 0)
356 perror( "DV1394_WAIT_FRAMES" );
358 pthread_testcancel();
360 /* update the status for the next iteration and detect dropped frames */
361 if ( ioctl( unit
->dv1394_fd
, DV1394_GET_STATUS
, &status
) >= 0)
363 pthread_testcancel();
366 printf( "dv1394 status: active=%02d, #clear=%02d, first clear=%02d\n",
367 status.active_frame, status.n_clear_frames, status.first_clear_frame);
370 /* report dropped frames */
371 if( status
.dropped_frames
> 0 )
373 frames_dropped
+= status
.dropped_frames
;
374 dv1394d_log( LOG_WARNING
, "dv1394 repeated %d frames with %d available.",
375 status
.dropped_frames
, dv_pump_get_available_output_count( unit
->pump
) );
378 available
= dv_pump_get_output_block( unit
->pump
, (void **)frames
, n_fill
);
380 dv_unit_status_communicate( unit
);
382 /* The only time we get 0 frames is when the unit is being stopped. */
383 if ( available
!= 0 )
385 int size
= dv_frame_size( frames
[ 0 ] );
386 int pos
= status
.first_clear_frame
;
389 for ( index
= 0; index
< available
; index
++ )
390 memcpy( unit
->mmap
+ ( ( pos
+ index
) % n_frames
) * size
, dv_frame_data( frames
[ index
] ), size
);
392 if ( ioctl( unit
->dv1394_fd
, DV1394_SUBMIT_FRAMES
, available
) >= 0)
394 for ( index
= 0; index
< available
- 1; index
++ )
396 dv_frame_clear_error( frames
[ index
] );
397 dv_frame_id_clear( dv_frame_get_id( frames
[ index
] ) );
399 dv_pump_return_output_block( unit
->pump
);
400 pthread_testcancel();
404 dv1394d_log( LOG_ERR
, "failed to write frames to dv1394: %s.", strerror_r( errno
, errstr
, 63 ) );
405 dv_pump_terminate( unit
->pump
);
406 dv_pump_flush( unit
->pump
);
407 pthread_testcancel();
413 dv1394d_log( LOG_ERR
, "failed to get dv1394 status: %s.", strerror_r( errno
, errstr
, 63 ) );
414 dv_pump_return_used_output( unit
->pump
);
418 if ( frames_dropped
> 0 )
419 dv1394d_log( LOG_WARNING
, "dv1394 repeated %d frames total during this transmission.", frames_dropped
);
421 pthread_cleanup_pop( 1 );
426 /** Start playing the clip.
428 Start a dv-pump and commence dv1394 transmission.
431 \param unit A dv_unit handle.
432 \param speed An integer that specifies the playback rate as a
433 percentage multiplied by 100.
436 void dv_unit_play( dv_unit_t
*unit
, int speed
)
438 dv_player player
= dv_unit_get_dv_player( unit
);
440 if ( unit
->is_terminated
== 1 && ( dv_player_get_total_frames( player
) > 0 || unit
->allow_stdin
) )
443 dv_frame frame
= NULL
;
444 struct dv1394_init setup
=
446 api_version
: DV1394_API_VERSION
,
447 channel
: unit
->channel
,
448 /* this only sets the *requested* size of the ringbuffer,
450 n_frames
: unit
->n_frames
,
451 /* we set the format later */
452 cip_n
: unit
->dv1394_cip_n
,
453 cip_d
: unit
->dv1394_cip_d
,
454 syt_offset
: unit
->dv1394_syt_offset
458 if ( unit
->in
== NULL
)
460 if ( !unit
->allow_stdin
|| dv_player_get_total_frames( player
) != 0 )
461 unit
->in
= dv_player_get_dv_input( player
);
463 unit
->in
= dv_input_init( unit
->pump
);
467 dv_input_join_thread( unit
->in
);
468 pthread_join( unit
->out
, NULL
);
471 unit
->is_terminated
= 0;
472 dv_pump_restart( unit
->pump
);
473 dv_input_start_thread( unit
->in
);
474 dv_player_set_speed( player
, (double) speed
/1000.0 );
476 /* first we read a little data to see if this is PAL or NTSC
477 so we can initialize dv1394 properly */
478 frame
= dv_pump_get_available_output( unit
->pump
);
480 /* initialize dv1394 */
481 setup
.format
= dv_frame_is_pal(frame
) ? DV1394_PAL
: DV1394_NTSC
;
483 retval
= ioctl( unit
->dv1394_fd
, DV1394_INIT
, &setup
);
486 perror( "DV1394_INIT" );
490 unit
->mmap_length
= unit
->n_frames
* dv_frame_size( frame
);
492 pthread_attr_init( &attr
);
493 pthread_attr_setdetachstate( &attr
, PTHREAD_CREATE_JOINABLE
);
494 pthread_attr_setinheritsched( &attr
, PTHREAD_INHERIT_SCHED
);
495 pthread_create( &unit
->out
, &attr
, output
, unit
);
499 dv_player_set_speed( player
, (double) speed
/1000.0 );
501 dv_unit_status_communicate( unit
);
506 Terminates the dv_pump and halts dv1394 transmission.
508 \param unit A dv_unit handle.
511 void dv_unit_terminate( dv_unit unit
)
513 unit
->is_terminated
= 1;
514 if ( unit
->pump
!= NULL
)
516 dv_pump_terminate( unit
->pump
);
517 dv_pump_flush( unit
->pump
);
521 /** Query the status of unit playback.
523 \param unit A dv_unit handle.
524 \return 1 if the unit is not playing, 0 if playing.
527 int dv_unit_has_terminated( dv_unit unit
)
529 return unit
->is_terminated
;
532 /** Get the dv_player from the dv_unit.
534 \param unit A dv_unit handle.
535 \return A dv_player handle.
538 dv_player
dv_unit_get_dv_player( dv_unit unit
)
542 if ( unit
->pump
== NULL
)
544 unit
->pump
= dv_pump_init( unit
->buffer_size
);
545 if ( unit
->pump
!= NULL
)
546 unit
->player
= dv_player_init( unit
->pump
);
554 /** Transfer the currently loaded clip to another unit
557 int dv_unit_transfer( dv_unit dest_unit
, dv_unit src_unit
)
559 dv_player src_player
= dv_unit_get_dv_player( src_unit
);
560 dv_player dest_player
= dv_unit_get_dv_player( dest_unit
);
562 if( dest_player
!= NULL
&& src_player
!= NULL
)
563 dv_player_replace_player( dest_player
, src_player
);
568 /** Get the guid associated to this unit.
571 octlet_t
dv_unit_get_guid( dv_unit unit
)
576 /** Get the node id associated to this unit.
579 int dv_unit_get_nodeid( dv_unit unit
)
581 return (unit
->node_id
& 0x3f);
584 /** Get the channel associated to this unit.
587 int dv_unit_get_channel( dv_unit unit
)
589 return (unit
->channel
);
592 /** Turn unit online.
595 int dv_unit_online( dv_unit unit
)
600 if ( unit
->raw1394
!= NULL
)
601 raw1394_close( unit
->raw1394
);
603 node_id
= raw1394_find_node( &(unit
->raw1394
), unit
->guid
);
606 unit
->node_id
= 0xffc0 | node_id
;
607 port
= dv_unit_get_port( unit
);
609 unit
->dv1394_fd
= open( devices
[ port
][ device_count
[port
] ], O_RDWR
);
610 if ( unit
->dv1394_fd
< 0 )
612 dv1394d_log( LOG_ERR
, "failed to open dv1394 device - %s\n", devices
[ port
][ device_count
[port
] ] );
613 dv_unit_close( unit
);
617 device_count
[ port
] ++;
618 if ( establish_p2p_connection( unit
->raw1394
, unit
->node_id
, (unsigned int *) &(unit
->channel
) ) )
620 avc1394_vcr_record( unit
->raw1394
, unit
->node_id
);
622 dv_unit_status_communicate( unit
);
631 /** Turn unit offline.
634 void dv_unit_offline( dv_unit unit
)
636 if ( unit
->online
== 1 )
638 if ( unit
->is_terminated
== 0 )
639 dv_unit_terminate( unit
);
641 if ( unit
->raw1394
!= NULL
)
643 avc1394_vcr_stop( unit
->raw1394
, unit
->node_id
);
644 break_p2p_connection( unit
->raw1394
, unit
->node_id
, unit
->channel
);
646 if ( unit
->dv1394_fd
> -1 )
648 close( unit
->dv1394_fd
);
649 device_count
[ dv_unit_get_port( unit
) ] --;
651 dv_unit_status_communicate( unit
);
652 dv1394d_log( LOG_DEBUG
, "Unit with GUID %08x%08x is now offline.",
653 (quadlet_t
) (unit
->guid
>>32), (quadlet_t
) (unit
->guid
& 0xffffffff) );
657 /** Determine if unit is offline.
660 int dv_unit_is_offline( dv_unit unit
)
662 return (unit
->online
== 0);
665 /** Obtain the status for a given unit
668 int dv_unit_get_status( dv_unit unit
, dv1394_status status
)
672 memset( status
, 0, sizeof( dv1394_status_t
) );
676 dv_player player
= dv_unit_get_dv_player( unit
);
680 if ( player
!= NULL
)
682 dv_frame head
= dv_pump_get_head( player
->pump
);
683 dv_frame tail
= dv_pump_get_tail( player
->pump
);
685 status
->speed
= (int)( dv_player_get_speed( player
) * 1000.0 );
686 status
->fps
= dv_player_frames_per_second( player
, 0 );
690 dv_frame_id id
= dv_frame_get_id( head
);
691 if ( id
->resource
!= NULL
)
693 const char *resource
= id
->resource
;
694 if ( resource
!= NULL
&& unit
->root_dir
!= NULL
)
695 resource
+= strlen( unit
->root_dir
) - ( unit
->root_dir
[ strlen( unit
->root_dir
) - 1 ] == '/' );
696 strncpy( status
->clip
, resource
, sizeof( status
->clip
) );
700 char *title
= dv_player_get_name( player
, dv_player_get_clip_containing( player
, 0 ), unit
->root_dir
);
702 strncpy( status
->clip
, title
, sizeof( status
->clip
) );
705 status
->position
= id
->relative
;
707 status
->out
= id
->out
;
708 status
->length
= id
->length
;
709 status
->seek_flag
= id
->seek_flag
;
713 char *title
= dv_player_get_name( player
, dv_player_get_clip_containing( player
, 0 ), unit
->root_dir
);
715 strncpy( status
->clip
, title
, sizeof( status
->clip
) );
720 dv_frame_id id
= dv_frame_get_id( tail
);
721 const char *resource
= id
->resource
;
722 if ( resource
!= NULL
&& unit
->root_dir
!= NULL
)
723 resource
+= strlen( unit
->root_dir
) - ( unit
->root_dir
[ strlen( unit
->root_dir
) - 1 ] == '/' );
724 if ( resource
!= NULL
)
725 strncpy( status
->tail_clip
, resource
, sizeof( status
->clip
) );
726 status
->tail_position
= id
->relative
;
727 status
->tail_in
= id
->in
;
728 status
->tail_out
= id
->out
;
729 status
->tail_length
= id
->length
;
732 status
->generation
= player
->generation
;
733 status
->clip_index
= dv_unit_get_current_clip( unit
);
736 if ( dv_unit_is_offline( unit
) )
737 status
->status
= unit_offline
;
738 else if ( !strcmp( status
->clip
, "" ) )
739 status
->status
= unit_not_loaded
;
740 else if ( dv_unit_has_terminated( unit
) )
741 status
->status
= unit_stopped
;
742 else if ( status
->speed
== 0 )
743 status
->status
= unit_paused
;
745 status
->status
= unit_playing
;
749 status
->status
= unit_undefined
;
752 status
->unit
= unit
->unit
;
757 /** Change position in the playlist.
760 void dv_unit_change_position( dv_unit unit
, int clip
, long position
)
762 dv_player player
= dv_unit_get_dv_player( unit
);
763 dv_player_set_clip_position( player
, clip
, position
);
764 dv_unit_status_communicate( unit
);
770 void dv_unit_change_speed( dv_unit unit
, int speed
)
772 if ( dv_unit_has_terminated( unit
) )
773 dv_unit_change_position( unit
, 0, 0 );
775 dv_unit_play( unit
, speed
);
778 int dv_unit_get_current_clip( dv_unit unit
)
780 dv_player player
= dv_unit_get_dv_player( unit
);
781 unsigned long position
= dv_player_get_position( player
);
782 return dv_player_get_clip_containing( player
, position
);
785 /** Set a clip's in point
788 int dv_unit_set_clip_in( dv_unit unit
, int index
, long position
)
791 dv_player player
= dv_unit_get_dv_player( unit
);
793 if ( player
!= NULL
)
795 dv_unit_change_speed( unit
, 0 );
796 if ( dv_player_set_in_point( player
, index
, (unsigned long) position
) == position
)
797 dv_player_set_clip_position( player
, index
, position
);
806 dv_unit_status_communicate( unit
);
812 /** Set a clip's out point.
815 int dv_unit_set_clip_out( dv_unit unit
, int index
, long position
)
818 dv_player player
= dv_unit_get_dv_player( unit
);
820 if ( player
!= NULL
)
822 dv_unit_change_speed( unit
, 0 );
823 if ( dv_player_set_out_point( player
, index
, position
) == position
)
824 dv_player_set_clip_position( player
, index
, position
);
833 dv_unit_status_communicate( unit
);
838 /** Step by specified position.
841 void dv_unit_step( dv_unit unit
, int offset
)
843 dv_player player
= dv_unit_get_dv_player( unit
);
844 dv_player_change_position( player
, dv_seek_relative
, offset
);
847 /** Set the unit's clip mode regarding in and out points.
850 void dv_unit_set_mode( dv_unit unit
, dv_player_clip_mode mode
)
852 dv_player player
= dv_unit_get_dv_player( unit
);
853 if ( player
!= NULL
)
854 dv_player_set_clip_mode( player
, mode
);
855 dv_unit_status_communicate( unit
);
858 /** Get the unit's clip mode regarding in and out points.
861 dv_player_clip_mode
dv_unit_get_mode( dv_unit unit
)
863 dv_player player
= dv_unit_get_dv_player( unit
);
864 return dv_player_get_clip_mode( player
);
867 /** Set the unit's clip mode regarding eof handling.
870 void dv_unit_set_eof_action( dv_unit unit
, dv_player_eof_action action
)
872 dv_player player
= dv_unit_get_dv_player( unit
);
873 dv_player_set_eof_action( player
, action
);
874 dv_unit_status_communicate( unit
);
877 /** Get the unit's clip mode regarding eof handling.
880 dv_player_eof_action
dv_unit_get_eof_action( dv_unit unit
)
882 dv_player player
= dv_unit_get_dv_player( unit
);
883 return dv_player_get_eof_action( player
);
889 \param unit A dv_unit handle.
892 void dv_unit_close( dv_unit unit
)
896 dv1394d_log( LOG_DEBUG
, "closing unit..." );
897 dv_unit_offline( unit
);
898 if ( unit
->pump
!= NULL
)
900 dv_pump_terminate( unit
->pump
);
901 dv_pump_flush( unit
->pump
);
902 dv_pump_return_used_output( unit
->pump
);
903 dv_input_join_thread( unit
->in
);
904 if ( !unit
->is_terminated
)
905 pthread_join( unit
->out
, NULL
);
906 dv_pump_close( unit
->pump
);
909 raw1394_close( unit
->raw1394
);
911 dv1394d_log( LOG_DEBUG
, "... unit closed." );
915 /** Get the raw1394 port associated to this unit.
918 int dv_unit_get_port( dv_unit unit
)
920 if ( unit
->raw1394
!= NULL
)
921 return (int) raw1394_get_userdata( unit
->raw1394
);
926 /** Set the dv1394 file descriptor for the unit.
929 void dv_unit_set_dv1394_fd( dv_unit unit
, int fd
)
931 unit
->dv1394_fd
= fd
;
934 /** Get the dv1394 syt_offset (timestamp latency) property.
937 unsigned int dv_unit_get_syt_offset( dv_unit unit
)
939 return unit
->dv1394_syt_offset
;
942 /** Get the dv1394 cip_n (timing numerator) property.
945 unsigned int dv_unit_get_cip_n( dv_unit unit
)
947 return unit
->dv1394_cip_n
;
950 /** Get the dv1394 cip_d (timing denominator) property.
953 unsigned int dv_unit_get_cip_d( dv_unit unit
)
955 return unit
->dv1394_cip_d
;
958 /** Set the dv1394 syt_offset (timestamp latency) property.
960 Stops and restarts the unit if playing.
963 void dv_unit_set_syt_offset( dv_unit unit
, unsigned int syt_offset
)
965 int restart
= !unit
->is_terminated
;
966 int speed
= (int)( dv_player_get_speed( dv_unit_get_dv_player(unit
) ) * 1000.0 );
968 dv_unit_terminate( unit
);
969 unit
->dv1394_syt_offset
= syt_offset
;
971 dv_unit_play( unit
, speed
);
974 /** Set the dv1394 cip_n (timing numerator) property.
976 Stops and restarts the unit if playing.
979 void dv_unit_set_cip_n( dv_unit unit
, unsigned int cip_n
)
981 int restart
= !unit
->is_terminated
;
982 int speed
= (int)( dv_player_get_speed( dv_unit_get_dv_player(unit
) ) * 1000.0 );
984 dv_unit_terminate( unit
);
985 unit
->dv1394_cip_n
= cip_n
;
987 dv_unit_play( unit
, speed
);
990 /** Set the dv1394 cip_d (timing denominator) property.
992 Stops and restarts the unit if playing.
995 void dv_unit_set_cip_d( dv_unit unit
, unsigned int cip_d
)
997 int restart
= !unit
->is_terminated
;
998 int speed
= (int)( dv_player_get_speed( dv_unit_get_dv_player(unit
) ) * 1000.0 );
1000 dv_unit_terminate( unit
);
1001 unit
->dv1394_cip_d
= cip_d
;
1003 dv_unit_play( unit
, speed
);
1006 /** Terminate, but only the output thread and close dv1394.
1009 void dv_unit_suspend( dv_unit unit
)
1011 if ( unit
->is_terminated
== 0 )
1013 unit
->is_terminated
= 1;
1014 unit
->is_suspended
= 1;
1015 dv_pump_terminate( unit
->pump
);
1016 dv_pump_flush( unit
->pump
);
1017 pthread_cancel( unit
->out
);
1019 if ( unit
->dv1394_fd
> -1 )
1021 close( unit
->dv1394_fd
);
1022 device_count
[ dv_unit_get_port( unit
) ] --;
1024 unit
->dv1394_fd
= -1;
1025 dv_unit_status_communicate( unit
);
1029 /** Restore unit on the bus, re-open dv1394, start playback if pump is running.
1032 void dv_unit_restore( dv_unit unit
)
1037 if ( unit
->raw1394
!= NULL
)
1038 raw1394_close( unit
->raw1394
);
1040 node_id
= raw1394_find_node( &(unit
->raw1394
), unit
->guid
);
1041 if ( node_id
!= -1 )
1043 unit
->node_id
= 0xffc0 | node_id
;
1044 port
= dv_unit_get_port( unit
);
1046 unit
->dv1394_fd
= open( devices
[ port
][ device_count
[port
] ], O_RDWR
);
1047 if ( unit
->dv1394_fd
< 0 )
1049 dv1394d_log( LOG_ERR
, "failed to open dv1394 device - %s\n", devices
[ port
][ device_count
[port
] ] );
1050 dv_unit_close( unit
);
1054 device_count
[ port
] ++;
1055 break_p2p_connection( unit
->raw1394
, unit
->node_id
, unit
->channel
);
1056 if ( establish_p2p_connection( unit
->raw1394
, unit
->node_id
, (unsigned int *) &(unit
->channel
) ) )
1058 avc1394_vcr_record( unit
->raw1394
, unit
->node_id
);
1064 if ( unit
->is_suspended
== 1 )
1067 dv_frame frame
= dv_pump_get_available_output( unit
->pump
);
1068 struct dv1394_init setup
=
1070 api_version
: DV1394_API_VERSION
,
1071 channel
: unit
->channel
,
1072 /* this only sets the *requested* size of the ringbuffer,
1074 n_frames
: unit
->n_frames
,
1075 format
: dv_frame_is_pal(frame
) ? DV1394_PAL
: DV1394_NTSC
,
1076 cip_n
: unit
->dv1394_cip_n
,
1077 cip_d
: unit
->dv1394_cip_d
,
1078 syt_offset
: unit
->dv1394_syt_offset
1080 pthread_attr_t attr
;
1082 dv_input_join_thread( unit
->in
);
1083 unit
->is_terminated
= 0;
1084 unit
->is_suspended
= 0;
1085 dv_pump_restart( unit
->pump
);
1086 dv_input_start_thread( unit
->in
);
1088 /* initialize dv1394 */
1089 retval
= ioctl( unit
->dv1394_fd
, DV1394_INIT
, &setup
);
1093 pthread_attr_init( &attr
);
1094 pthread_attr_setdetachstate( &attr
, PTHREAD_CREATE_JOINABLE
);
1095 pthread_attr_setinheritsched( &attr
, PTHREAD_INHERIT_SCHED
);
1096 /* pthread_attr_setschedpolicy( &attr, SCHED_RR ); */
1097 pthread_create( &unit
->out
, &attr
, output
, unit
);
1099 dv_unit_status_communicate( unit
);