1 /* $Id: ports.c,v 1.15 2005/10/15 18:05:03 titer Exp $
3 This file is part of the HandBrake source code.
4 Homepage: <http://handbrake.m0k.org/>.
5 It may be used under the terms of the GNU General Public License. */
10 #if defined( SYS_BEOS )
13 #elif defined( SYS_CYGWIN )
22 //#include <winsock2.h>
23 //#include <ws2tcpip.h>
25 #include <sys/types.h>
26 #include <sys/socket.h>
28 #include <netinet/in.h>
33 /************************************************************************
35 ************************************************************************
36 * Returns the current date in milliseconds.
37 * On Win32, we implement a gettimeofday emulation here because
38 * libdvdread and libmp4v2 use it without checking.
39 ************************************************************************/
46 int gettimeofday( struct timeval * tv, struct timezone * tz )
49 tick = GetTickCount();
50 tv->tv_sec = tick / 1000;
51 tv->tv_usec = ( tick % 1000 ) * 1000;
57 uint64_t hb_get_date()
60 gettimeofday( &tv
, NULL
);
61 return( (uint64_t) tv
.tv_sec
* 1000 + (uint64_t) tv
.tv_usec
/ 1000 );
64 /************************************************************************
66 ************************************************************************
67 * Waits <delay> milliseconds.
68 ************************************************************************/
69 void hb_snooze( int delay
)
75 #if defined( SYS_BEOS )
76 snooze( 1000 * delay
);
77 #elif defined( SYS_DARWIN ) || defined( SYS_LINUX ) || defined( SYS_FREEBSD )
78 usleep( 1000 * delay
);
79 #elif defined( SYS_CYGWIN )
84 /************************************************************************
86 ************************************************************************
87 * Whenever possible, returns the number of CPUs on the current
88 * computer. Returns 1 otherwise.
89 * The detection is actually only performed on the first call.
90 ************************************************************************/
91 int hb_get_cpu_count()
93 static int cpu_count
= 0;
101 #if defined( SYS_BEOS )
104 get_system_info( &info
);
105 cpu_count
= info
.cpu_count
;
108 #elif defined( SYS_DARWIN ) || defined( SYS_FREEBSD )
112 if( ( info
= popen( "/usr/sbin/sysctl hw.ncpu", "r" ) ) )
114 memset( buffer
, 0, 16 );
115 if( fgets( buffer
, 15, info
) )
117 if( sscanf( buffer
, "hw.ncpu: %d", &cpu_count
) != 1 )
125 #elif defined( SYS_LINUX )
130 if( ( info
= popen( "grep -c '^processor' /proc/cpuinfo",
133 memset( buffer
, 0, 8 );
134 if( fgets( buffer
, 7, info
) )
136 if( sscanf( buffer
, "%d", &cpu_count
) != 1 )
145 #elif defined( SYS_CYGWIN )
147 GetSystemInfo( &cpuinfo
);
148 cpu_count
= cpuinfo
.dwNumberOfProcessors
;
151 cpu_count
= MAX( 1, cpu_count
);
152 cpu_count
= MIN( cpu_count
, 8 );
157 /************************************************************************
158 * Get a tempory directory for HB
159 ***********************************************************************/
160 void hb_get_tempory_directory( hb_handle_t
* h
, char path
[512] )
164 /* Create the base */
167 int i_size
= GetTempPath( 512, base
);
168 if( i_size
<= 0 || i_size
>= 512 )
170 if( getcwd( base
, 512 ) == NULL
)
171 strcpy( base
, "c:" ); /* Bad fallback but ... */
174 /* c:/path/ works like a charm under cygwin(win32?) so use it */
175 while( ( p
= strchr( base
, '\\' ) ) )
178 strcpy( base
, "/tmp" );
180 /* I prefer to remove evntual last '/' (for cygwin) */
181 if( base
[strlen(base
)-1] == '/' )
182 base
[strlen(base
)-1] = '\0';
184 snprintf( path
, 512, "%s/hb.%d", base
, hb_get_pid( h
) );
187 /************************************************************************
188 * Get a tempory filename for HB
189 ***********************************************************************/
190 void hb_get_tempory_filename( hb_handle_t
* h
, char name
[1024],
195 hb_get_tempory_directory( h
, name
);
198 va_start( args
, fmt
);
199 vsnprintf( &name
[strlen(name
)], 1024 - strlen(name
), fmt
, args
);
203 /************************************************************************
205 ************************************************************************
206 * Wrapper to the real mkdir, needed only because it doesn't take a
207 * second argument on Win32. Grrr.
208 ***********************************************************************/
209 void hb_mkdir( char * name
)
218 /************************************************************************
219 * Portable thread implementation
220 ***********************************************************************/
225 void (* function
) ( void * );
231 #if defined( SYS_BEOS )
235 //#elif defined( SYS_CYGWIN )
240 /************************************************************************
242 ************************************************************************
243 * We use it as the root routine for any thread, for two reasons:
244 * + To set the thread priority on OS X (pthread_setschedparam() could
245 * be called from hb_thread_init(), but it's nicer to do it as we
246 * are sure it is done before the real routine starts)
247 * + Get informed when the thread exits, so we know whether
248 * hb_thread_close() will block or not.
249 ***********************************************************************/
250 static void hb_thread_func( void * _t
)
252 hb_thread_t
* t
= (hb_thread_t
*) _t
;
254 #if defined( SYS_DARWIN )
255 /* Set the thread priority */
256 struct sched_param param
;
257 memset( ¶m
, 0, sizeof( struct sched_param
) );
258 param
.sched_priority
= t
->priority
;
259 pthread_setschedparam( pthread_self(), SCHED_OTHER
, ¶m
);
262 #if defined( SYS_BEOS )
263 signal( SIGINT
, SIG_IGN
);
266 /* Start the actual routine */
267 t
->function( t
->arg
);
269 /* Inform that the thread can be joined now */
270 hb_log( "thread %d exited (\"%s\")", t
->thread
, t
->name
);
273 hb_unlock( t
->lock
);
276 /************************************************************************
278 ************************************************************************
279 * name: user-friendly name
280 * function: the thread routine
281 * arg: argument of the routine
282 * priority: HB_LOW_PRIORITY or HB_NORMAL_PRIORITY
283 ***********************************************************************/
284 hb_thread_t
* hb_thread_init( char * name
, void (* function
)(void *),
285 void * arg
, int priority
)
287 hb_thread_t
* t
= calloc( sizeof( hb_thread_t
), 1 );
289 t
->name
= strdup( name
);
290 t
->function
= function
;
292 t
->priority
= priority
;
294 t
->lock
= hb_lock_init();
296 /* Create and start the thread */
297 #if defined( SYS_BEOS )
298 t
->thread
= spawn_thread( (thread_func
) hb_thread_func
,
300 resume_thread( t
->thread
);
303 pthread_create( &t
->thread
, NULL
,
304 (void * (*)( void * )) hb_thread_func
, t
);
306 //#elif defined( SYS_CYGWIN )
307 // t->thread = CreateThread( NULL, 0,
308 // (LPTHREAD_START_ROUTINE) hb_thread_func, t, 0, NULL );
310 // /* Maybe use THREAD_PRIORITY_LOWEST instead */
311 // if( priority == HB_LOW_PRIORITY )
312 // SetThreadPriority( GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL );
315 hb_log( "thread %d started (\"%s\")", t
->thread
, t
->name
);
319 /************************************************************************
321 ************************************************************************
322 * Joins the thread and frees memory.
323 ***********************************************************************/
324 void hb_thread_close( hb_thread_t
** _t
)
326 hb_thread_t
* t
= *_t
;
328 /* Join the thread */
329 #if defined( SYS_BEOS )
331 wait_for_thread( t
->thread
, &exit_value
);
334 pthread_join( t
->thread
, NULL
);
336 //#elif defined( SYS_CYGWIN )
337 // WaitForSingleObject( t->thread, INFINITE );
340 hb_log( "thread %d joined (\"%s\")",
341 t
->thread
, t
->name
);
343 hb_lock_close( &t
->lock
);
349 /************************************************************************
350 * hb_thread_has_exited()
351 ************************************************************************
352 * Returns 1 if the thread can be joined right away, 0 otherwise.
353 ***********************************************************************/
354 int hb_thread_has_exited( hb_thread_t
* t
)
360 hb_unlock( t
->lock
);
365 /************************************************************************
366 * Portable mutex implementation
367 ***********************************************************************/
370 #if defined( SYS_BEOS )
373 pthread_mutex_t mutex
;
374 //#elif defined( SYS_CYGWIN )
379 /************************************************************************
384 ************************************************************************
385 * Basic wrappers to OS-specific semaphore or mutex functions.
386 ***********************************************************************/
387 hb_lock_t
* hb_lock_init()
389 hb_lock_t
* l
= calloc( sizeof( hb_lock_t
), 1 );
391 #if defined( SYS_BEOS )
392 l
->sem
= create_sem( 1, "sem" );
394 pthread_mutex_init( &l
->mutex
, NULL
);
395 //#elif defined( SYS_CYGWIN )
396 // l->mutex = CreateMutex( 0, FALSE, 0 );
402 void hb_lock_close( hb_lock_t
** _l
)
406 #if defined( SYS_BEOS )
407 delete_sem( l
->sem
);
409 pthread_mutex_destroy( &l
->mutex
);
410 //#elif defined( SYS_CYGWIN )
411 // CloseHandle( l->mutex );
418 void hb_lock( hb_lock_t
* l
)
420 #if defined( SYS_BEOS )
421 acquire_sem( l
->sem
);
423 pthread_mutex_lock( &l
->mutex
);
424 //#elif defined( SYS_CYGWIN )
425 // WaitForSingleObject( l->mutex, INFINITE );
429 void hb_unlock( hb_lock_t
* l
)
431 #if defined( SYS_BEOS )
432 release_sem( l
->sem
);
434 pthread_mutex_unlock( &l
->mutex
);
435 //#elif defined( SYS_CYGWIN )
436 // ReleaseMutex( l->mutex );
440 /************************************************************************
441 * Portable condition variable implementation
442 ***********************************************************************/
445 #if defined( SYS_BEOS )
449 //#elif defined( SYS_CYGWIN )
454 /************************************************************************
459 ************************************************************************
460 * Win9x is not supported by this implementation (SignalObjectAndWait()
461 * only available on Windows 2000/XP).
462 ***********************************************************************/
463 hb_cond_t
* hb_cond_init()
465 hb_cond_t
* c
= calloc( sizeof( hb_cond_t
), 1 );
467 #if defined( SYS_BEOS )
470 pthread_cond_init( &c
->cond
, NULL
);
471 //#elif defined( SYS_CYGWIN )
472 // c->event = CreateEvent( NULL, FALSE, FALSE, NULL );
478 void hb_cond_close( hb_cond_t
** _c
)
482 #if defined( SYS_BEOS )
484 pthread_cond_destroy( &c
->cond
);
485 //#elif defined( SYS_CYGWIN )
486 // CloseHandle( c->event );
493 void hb_cond_wait( hb_cond_t
* c
, hb_lock_t
* lock
)
495 #if defined( SYS_BEOS )
496 c
->thread
= find_thread( NULL
);
497 release_sem( lock
->sem
);
498 suspend_thread( c
->thread
);
499 acquire_sem( lock
->sem
);
502 pthread_cond_wait( &c
->cond
, &lock
->mutex
);
503 //#elif defined( SYS_CYGWIN )
504 // SignalObjectAndWait( lock->mutex, c->event, INFINITE, FALSE );
505 // WaitForSingleObject( lock->mutex, INFINITE );
509 void hb_cond_signal( hb_cond_t
* c
)
511 #if defined( SYS_BEOS )
512 while( c
->thread
!= -1 )
515 get_thread_info( c
->thread
, &info
);
516 if( info
.state
== B_THREAD_SUSPENDED
)
518 resume_thread( c
->thread
);
521 /* Looks like we have been called between hb_cond_wait's
522 release_sem() and suspend_thread() lines. Wait until the
523 thread is actually suspended before we resume it */
527 pthread_cond_signal( &c
->cond
);
528 //#elif defined( SYS_CYGWIN )
529 // PulseEvent( c->event );
533 /************************************************************************
535 ***********************************************************************/
542 hb_net_t
* hb_net_open( char * address
, int port
)
544 hb_net_t
* n
= calloc( sizeof( hb_net_t
), 1 );
546 struct sockaddr_in sock
;
547 struct hostent
* host
;
549 /* TODO: find out why this doesn't work on Win32 */
550 if( !( host
= gethostbyname( address
) ) )
552 hb_log( "gethostbyname failed (%s)", address
);
557 memset( &sock
, 0, sizeof( struct sockaddr_in
) );
558 sock
.sin_family
= host
->h_addrtype
;
559 sock
.sin_port
= htons( port
);
560 memcpy( &sock
.sin_addr
, host
->h_addr
, host
->h_length
);
562 if( ( n
->socket
= socket( host
->h_addrtype
, SOCK_STREAM
, 0 ) ) < 0 )
564 hb_log( "socket failed" );
569 if( connect( n
->socket
, (struct sockaddr
*) &sock
,
570 sizeof( struct sockaddr_in
) ) < 0 )
572 hb_log( "connect failed" );
580 int hb_net_send( hb_net_t
* n
, char * buffer
)
582 return send( n
->socket
, buffer
, strlen( buffer
), 0 );
585 int hb_net_recv( hb_net_t
* n
, char * buffer
, int size
)
587 return recv( n
->socket
, buffer
, size
- 1, 0 );
590 void hb_net_close( hb_net_t
** _n
)
592 hb_net_t
* n
= (hb_net_t
*) *_n
;