esound r524 - trunk
- From: jmouette svn gnome org
- To: svn-commits-list gnome org
- Subject: esound r524 - trunk
- Date: Tue, 18 Nov 2008 20:32:56 +0000 (UTC)
Author: jmouette
Date: Tue Nov 18 20:32:55 2008
New Revision: 524
URL: http://svn.gnome.org/viewvc/esound?rev=524&view=rev
Log:
* esd-server.h:
* esd.c: (reconnect_driver), (main): Install signal handler for
SIGUSR1 that reconnects to the ALSA driver. This is useful
after changing the ALSA configuration file.
* clients.c: (esd_comm_loop): Integrate driver reconnection
into client loop.
* audio_alsa09.c: Call snd_config_update_free_global() to purge
configuration cache and to properly reload configuration
files.
Modified:
trunk/ChangeLog
trunk/audio_alsa09.c
trunk/clients.c
trunk/esd-server.h
trunk/esd.c
Modified: trunk/audio_alsa09.c
==============================================================================
--- trunk/audio_alsa09.c (original)
+++ trunk/audio_alsa09.c Tue Nov 18 20:32:55 2008
@@ -101,6 +101,7 @@
snd_pcm_uframes_t t_bufsize=BUFFERSIZE;
#endif
+ snd_config_update_free_global();
err = snd_pcm_open(&handle, dev, mode, SND_PCM_NONBLOCK);
if (err < 0) {
if (alsadbg)
Modified: trunk/clients.c
==============================================================================
--- trunk/clients.c (original)
+++ trunk/clients.c Tue Nov 18 20:32:55 2008
@@ -1,6 +1,7 @@
#include "esd-server.h"
#include <arpa/inet.h>
#include <time.h>
+#include <errno.h>
#ifdef HAVE_SYS_IOCTL_H
# include <sys/ioctl.h>
@@ -26,6 +27,7 @@
/* the list of the currently connected clients */
esd_client_t *esd_clients_list;
+static int write_wait = 0;
/*******************************************************************/
/* prototypes */
@@ -251,113 +253,183 @@
return 0;
}
-static int is_paused_here = 0;
-/*******************************************************************/
-/* blocks waiting for data from the listener, and client conns. */
-int wait_for_clients_and_data( int listen )
+void esd_comm_loop( int listen_socket, void *output_buffer, int esd_terminate )
{
fd_set rd_fds;
struct timeval timeout;
struct timeval *timeout_ptr = NULL;
- esd_client_t *client = esd_clients_list;
- int max_fd = listen, ready;
-
- /* add the listener to the file descriptor list */
- FD_ZERO( &rd_fds );
- FD_SET( listen, &rd_fds );
+ esd_client_t *client;
+ int max_fd = listen_socket, ready;
+ int first = 1;
+ int is_paused_here = 0;
+ int length = 0;
- /* add the clients to the list, too */
- while ( client != NULL )
+ while ( 1 )
{
- /* add this client, but only if it's not monitoring */
- if ( client->state == ESD_STREAMING_DATA &&
- client->request == ESD_PROTO_STREAM_MON )
- {
- client = client->next;
- continue;
- }
-
- FD_SET( client->fd, &rd_fds );
-
- /* update the maximum fd for the select() */
- if ( client->fd > max_fd )
- max_fd = client->fd;
+ FD_ZERO( &rd_fds );
+ FD_SET( listen_socket, &rd_fds );
- /* next client */
- client = client->next;
- }
-
- /* if we're doing something useful, make sure we return immediately */
- if ( esd_recorder_list || esd_playing_samples ) {
- timeout.tv_sec = 0;
- timeout.tv_usec = 0;
- timeout_ptr = &timeout;
- } else {
-
- /* TODO: any reason not to pause indefinitely here? */
- /* sample players that's why, if no players, can pause indefinitely */
- /* if ( esd_on_autostandby
- || (esd_autostandby_secs < 0 && !esd_playing_samples ) )
- timeout_ptr = NULL; else { ... } */
-
- if ( is_paused_here ) {
-
- ESDBG_TRACE( printf( "paused, awaiting instructions.\n" ); );
- timeout_ptr = NULL;
+ if( esd_pending_driver_reconnect ) {
+ esd_pending_driver_reconnect = 0;
+ esd_audio_close();
+ usleep(100);
+ if( esd_audio_open() < 0 )
+ fprintf( stderr, "could not reopen the audio device\n" );
+ }
+
+ if ((esd_clients_list == NULL) && (!first) && (esd_terminate)
+ && (esd_autostandby_secs<0 || esd_on_autostandby)) {
+ clean_exit(0);
+ exit(0);
+ }
- } else {
+ for( client = esd_clients_list ; client ; client = client->next)
+ {
+ if ( client->state == ESD_STREAMING_DATA &&
+ client->request == ESD_PROTO_STREAM_MON )
+ continue;
+
+ FD_SET( client->fd, &rd_fds );
+ if ( client->fd > max_fd )
+ max_fd = client->fd;
+ }
+ /* if we're doing something useful, make sure we return immediately */
+ if ( esd_recorder_list || esd_playing_samples ) {
timeout.tv_sec = 0;
- /* funky math to make sure a long can hold it all, calulate in ms */
- timeout.tv_usec = (long) esd_buf_size_samples * 1000L
- / (long) esd_audio_rate / 4L; /* divide by two for stereo */
- timeout.tv_usec *= 1000L; /* convert to microseconds */
+ timeout.tv_usec = 0;
timeout_ptr = &timeout;
-
- }
- }
-
- ready = select( max_fd+1, &rd_fds, NULL, NULL, timeout_ptr );
-
- ESDBG_COMMS( printf(
- "paused=%d, samples=%d, auto=%d, standby=%d, record=%d, ready=%d\n",
- is_paused_here, esd_playing_samples,
- esd_autostandby_secs, esd_on_standby,
- (esd_recorder_list != 0), ready ); );
-
- /* TODO: return ready, and do this in esd.c */
- if ( ready <= 0 ) {
- /* if < 0, something horrible happened:
- EBADF invalid file descriptor - let individual read sort it out
- EINTR non blocked signal caught - o well, no big deal
- EINVAL n is negative - not bloody likely
- ENOMEM unable to allocate internal tables - o well, no big deal */
-
- if ( !is_paused_here && !esd_playing_samples && (esd_autostandby_secs<0) ) {
- ESDBG_TRACE( printf( "doing nothing, pausing server.\n" ); );
- esd_audio_flush();
- esd_audio_pause();
- esd_last_activity = time( NULL );
- is_paused_here = 1;
+ } else {
+ if ( is_paused_here && (esd_autostandby_secs<0 || esd_on_standby)) {
+ ESDBG_TRACE( printf( "paused, awaiting instructions.\n" ); );
+ timeout_ptr = NULL;
+ } else {
+ if (is_paused_here && esd_autostandby_secs>=0) {
+ timeout.tv_sec = (esd_last_activity+esd_autostandby_secs+1)-time(NULL);
+ if (timeout.tv_sec < 0 || timeout.tv_sec > esd_autostandby_secs+1)
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 0;
+ timeout_ptr = &timeout;
+ } else {
+ if (!write_wait)
+ {
+ int samples;
+
+ samples = ((esd_audio_format & ESD_MASK_CHAN) == ESD_STEREO) ? 2 : 1;
+ timeout.tv_sec = 0;
+ /* funky math to make sure a long can hold it all, calulate in ms */
+ timeout.tv_usec = ((long) samples * 1000L
+ / (long) esd_audio_rate)+1;
+ timeout.tv_usec *= 1000; /* convert to microseconds */
+ timeout_ptr = &timeout;
+ }
+ else
+ timeout_ptr = NULL;
+ }
+ }
}
- if ( !is_paused_here && !esd_playing_samples && !esd_recorder_list ) {
+ ready = select( max_fd+1, &rd_fds, NULL, NULL, timeout_ptr );
- if ( esd_autostandby_secs >= 0
+ ESDBG_COMMS( printf(
+ "paused=%d, samples=%d, auto=%d, standby=%d, record=%d, ready=%d\n",
+ is_paused_here, esd_playing_samples,
+ esd_autostandby_secs, esd_on_standby,
+ (esd_recorder_list != 0), ready ); );
+
+ if ( ready < 0 ) {
+ if ( errno == EINTR && timeout_ptr == NULL && write_wait == 0 ) {
+ ready = 1;
+ } else {
+ if ( errno == EINTR || errno == EAGAIN )
+ continue;
+ perror("select");
+ exit(1);
+ }
+ } else if ( ready == 0 ) {
+ if ( !is_paused_here && !esd_playing_samples && !esd_recorder_list ) {
+ ESDBG_TRACE( printf( "doing nothing, pausing server.\n" ); );
+ esd_audio_flush();
+ if (!first)
+ esd_audio_pause();
+ esd_last_activity = time( NULL );
+ is_paused_here = 1;
+ }
+ if ( is_paused_here && esd_autostandby_secs >= 0
&& ( time(NULL) > esd_last_activity + esd_autostandby_secs ) ) {
ESDBG_TRACE( printf( "bored, going to standby mode.\n" ); );
esd_server_standby();
esd_on_autostandby = 1;
- is_paused_here = 1;
}
+ if (!esd_recorder_list && is_paused_here)
+ continue;
+ }
+ is_paused_here = 0;
+ if ( FD_ISSET(listen_socket, &rd_fds ) ) {
+ get_new_clients( listen_socket );
}
- } else {
+ if ( ready || esd_playing_samples ) {
+ /* check for new protocol requests */
+ poll_client_requests();
+ first = 0;
+
+ /* mix new requests, and output to device */
+ refresh_mix_funcs(); /* TODO: set a flag to cue when to do this */
+ length = mix_players( output_buffer, esd_buf_size_octets );
+
+ /* awaken if on autostandby and doing anything */
+ if ( esd_on_autostandby && length && !esd_forced_standby ) {
+ ESDBG_TRACE( printf( "stuff to play, waking up.\n" ); );
+ if ( !esd_server_resume()) {
+ usleep(100);
+ }
+ }
- is_paused_here = 0;
+ /* we handle this even when length == 0 because a filter could have
+ * closed, and we don't want to eat the processor if one did.. */
+ if ( esd_filter_list && !esd_on_standby ) {
+ length = filter_write( output_buffer, length,
+ esd_audio_format, esd_audio_rate );
+ }
+
+ if ( length > 0 && !write_wait) {
+ if ( !esd_on_standby ) {
+ int nbytes;
+ /* standby check goes in here, so esd will eat sound data */
+ /* TODO: eat a round of data with a better algorithm */
+ /* this will cause guaranteed timing issues */
+ /* TODO: on monitor, why isn't this a buffer of zeroes? */
+ nbytes = esd_audio_write( output_buffer, length );
+#if 0
+ val.tv_sec = 0;
+ val.tv_usec = ((nbytes / esd_sample_size /
+ (((esd_audio_format & ESD_MASK_CHAN) == ESD_STEREO) ? 2 : 1))
+ * 1000) / esd_audio_rate;
+ val.tv_usec *= 1000000;
+#endif
- }
+ esd_last_activity = time( NULL );
+ }
- return ready;
+ /* if someone's monitoring the sound stream, send them data */
+ /* mix_players, above, forces buffer to zero if no players */
+ /* this clears out any leftovers from recording, below */
+ if ( esd_monitor_list && !esd_on_standby && length ) {
+ monitor_write( output_buffer, length );
+ }
+
+ }
+ }
+
+ /* if someone's recording from the audio device, send them data */
+ if ( esd_recorder_list && !esd_on_standby ) {
+ length = esd_audio_read( output_buffer, esd_buf_size_octets );
+ if ( length ) {
+ length = recorder_write( output_buffer, length );
+ esd_last_activity = time( NULL );
+ }
+ }
+ }
}
Modified: trunk/esd-server.h
==============================================================================
--- trunk/esd-server.h (original)
+++ trunk/esd-server.h Tue Nov 18 20:32:55 2008
@@ -121,6 +121,7 @@
extern char esd_owner_key[ESD_KEY_LEN];
extern int esd_on_standby;
+extern int esd_pending_driver_reconnect;
extern int esdbg_trace;
extern int esdbg_comms;
extern int esdbg_mixer;
@@ -144,6 +145,7 @@
int get_new_clients( int listen );
int wait_for_clients_and_data( int listen );
+void esd_comm_loop( int listen_socket, void *output_buffer, int esd_terminate );
/* filter.c - things with which to handle filters */
extern esd_player_t *esd_filter_list;
Modified: trunk/esd.c
==============================================================================
--- trunk/esd.c (original)
+++ trunk/esd.c Tue Nov 18 20:32:55 2008
@@ -70,6 +70,7 @@
void clean_exit( int signum );
void reset_signal( int signum );
void reset_daemon( int signum );
+void reconnect_driver( int signum );
int open_listen_socket( const char *hostname, int port );
/* from esd_config.c */
@@ -82,6 +83,8 @@
int esd_is_locked = 1; /* if owned, will prohibit foreign sources */
char esd_owner_key[ESD_KEY_LEN]; /* the key that locks the daemon */
+int esd_pending_driver_reconnect = 0; /* set by SIGUSR1 handler for
+ reconnecting to the audio card */
int esd_on_standby = 0; /* set to ignore incoming audio data */
int esdbg_trace = 0; /* show warm fuzzy debug messages */
int esdbg_comms = 0; /* show protocol level debug messages */
@@ -224,6 +227,15 @@
exit( 0 );
}
+void reconnect_driver( int signum )
+{
+ ESDBG_TRACE(
+ printf( "(ca) reconnecting to driver on signal %d\n",
+ signum ); );
+ esd_pending_driver_reconnect = 1;
+ signal( signum, reconnect_driver );
+}
+
void reset_signal(int signum) {
/* fprintf( stderr, "received signal %d: resetting...\n", signum );*/
signal( signum, reset_signal);
@@ -612,7 +624,6 @@
/* Enlightened sound Daemon */
int esd_port = ESD_DEFAULT_PORT;
- int length = 0;
int arg = 0;
int itmp;
@@ -644,8 +655,6 @@
int i, j, freq=440;
int magl, magr;
- int first = 1;
-
int default_format = ESD_BITS16 | ESD_STEREO;
/* end test scaffolding parameters */
@@ -970,6 +979,7 @@
signal( SIGTERM, clean_exit ); /* for default kill */
signal( SIGPIPE, reset_signal ); /* for closed rec/mon clients */
signal( SIGHUP, reset_daemon ); /* kill -HUP clear ownership */
+ signal( SIGUSR1, reconnect_driver ); /* react to changed sound card */
/* send some sine waves just to check the sound connection */
i = 0;
@@ -1000,106 +1010,7 @@
close (esd_spawnfd);
}
- /* until we kill the daemon */
- while ( 1 )
- {
- /* block while waiting for more clients and new data */
- wait_for_clients_and_data( listen_socket );
-
- /* accept new connections */
- get_new_clients( listen_socket );
-
-
- if ((esd_clients_list == NULL) && (!esd_playing_samples) &&
- (!first) && (esd_terminate)) {
-/* fprintf(stderr, "No clients!\n");*/
- clean_exit(0);
- exit(0);
- }
-
- /* check for new protocol requests */
- poll_client_requests();
- first = 0;
-
- /* mix new requests, and output to device */
- refresh_mix_funcs(); /* TODO: set a flag to cue when to do this */
- length = mix_players( output_buffer, esd_buf_size_octets );
-
- /* awaken if on autostandby and doing anything */
- if ( esd_on_autostandby && length && !esd_forced_standby ) {
- ESDBG_TRACE( printf( "stuff to play, waking up.\n" ); );
- esd_server_resume();
- }
-
- /* we handle this even when length == 0 because a filter could have
- * closed, and we don't want to eat the processor if one did.. */
- if ( esd_filter_list && !esd_on_standby ) {
- length = filter_write( output_buffer, length,
- esd_audio_format, esd_audio_rate );
- }
-
- if ( length > 0 /* || esd_monitor */ ) {
- /* do_sleep = 0; */
- if ( !esd_on_standby ) {
- /* standby check goes in here, so esd will eat sound data */
- /* TODO: eat a round of data with a better algorithm */
- /* this will cause guaranteed timing issues */
- /* TODO: on monitor, why isn't this a buffer of zeroes? */
- /* esd_audio_write( output_buffer, esd_buf_size_octets ); */
- esd_audio_write( output_buffer, length );
- /* esd_audio_flush(); */ /* this is overkill */
- esd_last_activity = time( NULL );
- }
- } else {
- /* should be pausing just fine within wait_for_clients_and_data */
- /* if so, this isn't really needed */
-
- /* be very quiet, and wait for a wabbit to come along */
-#if 0
- if ( !do_sleep ) { ESDBG_TRACE( printf( "pausing in esd.c\n" ); ); }
- do_sleep = 1;
- esd_audio_pause();
-#endif
- }
-
- /* if someone's monitoring the sound stream, send them data */
- /* mix_players, above, forces buffer to zero if no players */
- /* this clears out any leftovers from recording, below */
- if ( esd_monitor_list && !esd_on_standby && length ) {
- /* if ( esd_monitor_list && !esd_on_standby ) { */
- monitor_write( output_buffer, length );
- }
-
- /* if someone's recording the sound stream, send them data */
- if ( esd_recorder_list && !esd_on_standby ) {
- length = esd_audio_read( output_buffer, esd_buf_size_octets );
- if ( length ) {
- length = recorder_write( output_buffer, length );
- esd_last_activity = time( NULL );
- }
- }
-
- if ( esd_on_standby ) {
-#ifdef HAVE_NANOSLEEP
- struct timespec restrain;
- restrain.tv_sec = 0;
- /* funky math to make sure a long can hold it all, calulate in ms */
- restrain.tv_nsec = (long) esd_buf_size_samples * 1000L
- / (long) esd_audio_rate / 4L; /* divide by two for stereo */
- restrain.tv_nsec *= 1000000L; /* convert to nanoseconds */
- nanosleep( &restrain, NULL );
-#else
- struct timeval restrain;
- restrain.tv_sec = 0;
- /* funky math to make sure a long can hold it all, calulate in ms */
- restrain.tv_usec = (long) esd_buf_size_samples * 1000L
- / (long) esd_audio_rate / 4L; /* divide by two for stereo */
- restrain.tv_usec *= 1000L; /* convert to microseconds */
- select( 0, 0, 0, 0, &restrain );
-#endif
- }
- } /* while ( 1 ) */
-
+ esd_comm_loop(listen_socket,output_buffer,esd_terminate);
close (listen_socket);
/* how we'd get here, i have no idea, should only exit on signal */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]