📄 esd.c
字号:
#include "esd-server.h"#include <arpa/inet.h>#ifndef HAVE_NANOSLEEP#include <sys/time.h>#include <sys/types.h>#include <unistd.h>#endif/*******************************************************************//* esd.c - prototypes */void set_audio_buffer( void *buf, esd_format_t format, int magl, int magr, int freq, int speed, int length, long offset );void clean_exit( int signum );void reset_signal( int signum );void reset_daemon( int signum );int open_listen_socket( int port );/*******************************************************************//* globals */int esd_is_owned = 0; /* start unowned, first client claims it */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_on_standby = 0; /* set to route ignore incoming audio data */int esdbg_trace = 0; /* show warm fuzzy debug messages */int esdbg_comms = 0; /* show protocol level debug messages */int esdbg_mixer = 0; /* show mixer engine debug messages */int esd_buf_size_octets = 0; /* size of audio buffer in bytes */int esd_buf_size_samples = 0; /* size of audio buffer in samples */int esd_sample_size = 0; /* size of sample in bytes */int esd_beeps = 1; /* whether or not to beep on startup */int listen_socket = -1; /* socket to accept connections on */int esd_autostandby_secs = -1; /* timeout to release audio device, disabled <0 */time_t esd_last_activity = 0; /* seconds since last activity */int esd_on_autostandby = 0; /* set when auto paused for auto reawaken *//*******************************************************************//* just to create the startup tones for the fun of it */void set_audio_buffer( void *buf, esd_format_t format, int magl, int magr, int freq, int speed, int length, long offset ){ int i; float sample; float kf = 2.0 * 3.14 * (float)freq / (float)speed; unsigned char *uc_buf = (unsigned char *)buf; signed short *ss_buf = (signed short *)buf; /* printf( "fmt=%d, ml=%d, mr=%d, freq=%d, speed=%d, len=%ld\n", format, magl, magr, freq, speed, length ); */ switch ( format & ESD_MASK_BITS ) { case ESD_BITS8: for ( i = 0 ; i < length ; i+=2 ) { sample = sin( (float)(i+offset) * kf ); uc_buf[i] = 127 + magl * sample; uc_buf[i+1] = 127 + magr * sample; } break; case ESD_BITS16: /* assume same endian */ for ( i = 0 ; i < length ; i+=2 ) { sample = sin( (float)(i+offset) * kf ); ss_buf[i] = magl * sample; ss_buf[i+1] = magr * sample; } break; default: fprintf( stderr, "unsupported format for set_audio_buffer: 0x%08x\n", format ); exit( 1 ); } return;}/*******************************************************************//* to properly handle signals */void reset_daemon( int signum ){ int tumbler; ESDBG_TRACE( printf( "(ca) resetting sound daemon on signal %d\n", signum ); ); /* reset the access rights */ esd_is_owned = 0; esd_is_locked = 1; /* scramble the stored key */ srand( time(NULL) ); for ( tumbler = 0 ; tumbler < ESD_KEY_LEN ; tumbler++ ) { esd_owner_key[ tumbler ] = rand() % 256; } /* close the clients */ while ( esd_clients_list != NULL ) { erase_client( esd_clients_list ); } /* free samples */ while ( esd_samples_list != NULL ) { erase_sample( esd_samples_list->sample_id, 1 ); /* TODO: kill_sample, so it stops playing */ /* a looping sample will get stuck */ } /* reset next sample id */ esd_next_sample_id = 1; /* reset signal handler, if not called from a signal, no effect */ signal( SIGHUP, reset_daemon );}void clean_exit(int signum) { /* just clean up as best we can and terminate from here */ esd_client_t * client = esd_clients_list; fprintf( stderr, "received signal %d: terminating...\n", signum ); /* free the sound device */ esd_audio_close(); /* close the listening socket */ close( listen_socket ); /* close the clients */ while ( client != NULL ) { close( client->fd ); client = client->next; } /* trust the os to clean up the memory for the samples and such */ fprintf( stderr, "bye bye.\n" ); exit( 0 );}void reset_signal(int signum) { fprintf( stderr, "received signal %d: resetting...\n", signum ); signal( signum, reset_signal); return;}/*******************************************************************//* returns the listening socket descriptor */int open_listen_socket( int port ){ /*********************/ /* socket test setup */ struct sockaddr_in socket_addr; int socket_listen; struct linger lin; /* create the socket, and set for non-blocking */ socket_listen=socket(AF_INET,SOCK_STREAM,0); if (socket_listen<0) { fprintf(stderr,"Unable to create socket\n"); return( -1 ); } if (fcntl(socket_listen,F_SETFL,O_NONBLOCK)<0) { fprintf(stderr,"Unable to set socket to non-blocking\n"); return( -1 ); } /* set socket for linger? */ lin.l_onoff=1; /* block a closing socket for 1 second */ lin.l_linger=100; /* if data is waiting to be sent */ if ( setsockopt( socket_listen, SOL_SOCKET, SO_LINGER, &lin, sizeof(struct linger) ) < 0 ) { fprintf(stderr,"Unable to set socket linger value to %d\n", lin.l_linger); return( -1 ); } { int n = 1; setsockopt(socket_listen, SOL_SOCKET, SO_REUSEADDR, &n, sizeof(n)); /* if it fails, so what */ } /* set the listening information */ socket_addr.sin_family = AF_INET; socket_addr.sin_port = htons( port ); socket_addr.sin_addr.s_addr = htonl( inet_addr("0.0.0.0") ); if ( bind( socket_listen, (struct sockaddr *) &socket_addr, sizeof(struct sockaddr_in) ) < 0 ) { fprintf(stderr,"Unable to bind port %d\n", port ); exit(1); } if (listen(socket_listen,16)<0) { fprintf(stderr,"Unable to set socket listen buffer length\n"); exit(1); } return socket_listen;}/*******************************************************************//* daemon eats sound data, without playing anything, return boolean ok */int esd_server_standby(void){ int ok = 1; /* only bother if we're not already on standby */ if ( !esd_on_standby ) { ESDBG_TRACE( printf( "setting sound daemon to standby\n" ); ); /* TODO: close down any recorders, too */ esd_on_standby = 1; esd_audio_close(); } return ok;}/*******************************************************************//* daemon goes back to playing sound data, returns boolean ok */int esd_server_resume(void){ int ok = 1; /* only bother if we're already on standby */ if ( esd_on_standby ) { ESDBG_TRACE( printf( "resuming sound daemon\n" ); ); /* reclaim the audio device */ if ( esd_audio_open() < 0 ) { /* device was busy or something, return error, try later */ ok = 0; } else { /* turn ourselves back on */ esd_on_standby = 0; esd_on_autostandby = 0; } } return ok;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -