summaryrefslogtreecommitdiff
path: root/esd.h
blob: 21c40e987f63ba4fa55ba9312adffe8778ba7b4a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
#ifndef ESD_H
#define ESD_H
#include <audiofile.h>

#ifdef __cplusplus
extern "C" {
#endif

/* path and name of the default EsounD domain socket */
#define ESD_UNIX_SOCKET_DIR	esd_get_socket_dirname()
#define ESD_UNIX_SOCKET_NAME	esd_get_socket_name()

/* size of the audio buffer */
#define ESD_BUF_SIZE (4 * 1024)
/* maximum size we can write().  Otherwise we might overflow */
#define ESD_MAX_WRITE_SIZE (21 * 4096)

/* length of the authorization key, octets */
#define ESD_KEY_LEN (16)

/* default port for the EsounD server */
#define ESD_DEFAULT_PORT (16001)

/* default sample rate for the EsounD server */
#define ESD_DEFAULT_RATE (44100)

/* maximum length of a stream/sample name */
#define ESD_NAME_MAX (128)

/* a magic number to identify the relative endianness of a client */
#define ESD_ENDIAN_KEY \
	( (unsigned int) ( ('E' << 24) + ('N' << 16) + ('D' << 8) + ('N') ) )

#define ESD_VOLUME_BASE (256)

/*************************************/
/* what can we do to/with the EsounD */
enum esd_proto { 
    ESD_PROTO_CONNECT,      /* implied on inital client connection */

    /* pseudo "security" functionality */
    ESD_PROTO_LOCK,	    /* disable "foreign" client connections */
    ESD_PROTO_UNLOCK,	    /* enable "foreign" client connections */

    /* stream functionality: play, record, monitor */
    ESD_PROTO_STREAM_PLAY,  /* play all following data as a stream */
    ESD_PROTO_STREAM_REC,   /* record data from card as a stream */
    ESD_PROTO_STREAM_MON,   /* send mixed buffer output as a stream */

    /* sample functionality: cache, free, play, loop, EOL, kill */
    ESD_PROTO_SAMPLE_CACHE, /* cache a sample in the server */
    ESD_PROTO_SAMPLE_FREE,  /* release a sample in the server */
    ESD_PROTO_SAMPLE_PLAY,  /* play a cached sample */
    ESD_PROTO_SAMPLE_LOOP,  /* loop a cached sample, til eoloop */
    ESD_PROTO_SAMPLE_STOP,  /* stop a looping sample when done */
    ESD_PROTO_SAMPLE_KILL,  /* stop the looping sample immed. */

    /* free and reclaim /dev/dsp functionality */
    ESD_PROTO_STANDBY,	    /* release /dev/dsp and ignore all data */
    ESD_PROTO_RESUME,	    /* reclaim /dev/dsp and play sounds again */

    /* TODO: move these to a more logical place. NOTE: will break the protocol */
    ESD_PROTO_SAMPLE_GETID, /* get the ID for an already-cached sample */
    ESD_PROTO_STREAM_FILT,  /* filter mixed buffer output as a stream */

    /* esd remote management */
    ESD_PROTO_SERVER_INFO,  /* get server info (ver, sample rate, format) */
    ESD_PROTO_ALL_INFO,     /* get all info (server info, players, samples) */
    ESD_PROTO_SUBSCRIBE,    /* track new and removed players and samples */
    ESD_PROTO_UNSUBSCRIBE,  /* stop tracking updates */

    /* esd remote control */
    ESD_PROTO_STREAM_PAN,   /* set stream panning */
    ESD_PROTO_SAMPLE_PAN,   /* set default sample panning */

    /* esd status */
    ESD_PROTO_STANDBY_MODE, /* see if server is in standby, autostandby, etc */

    /* esd latency */
    ESD_PROTO_LATENCY,      /* retrieve latency between write()'s and output */
  
    ESD_PROTO_MAX           /* for bounds checking */
};
    

/******************/
/* The EsounD api */

/* the properties of a sound buffer are logically or'd */

/* bits of stream/sample data */
#define ESD_MASK_BITS	( 0x000F )
#define ESD_BITS8 	( 0x0000 )
#define ESD_BITS16	( 0x0001 )

/* how many interleaved channels of data */
#define ESD_MASK_CHAN	( 0x00F0 )
#define ESD_MONO	( 0x0010 )
#define ESD_STEREO	( 0x0020 )

/* whether it's a stream or a sample */
#define ESD_MASK_MODE	( 0x0F00 )
#define ESD_STREAM	( 0x0000 )
#define ESD_SAMPLE	( 0x0100 )
#define ESD_ADPCM	( 0x0200 )	/* TODO: anyone up for this? =P */

/* the function of the stream/sample, and common functions */
#define ESD_MASK_FUNC	( 0xF000 )
#define ESD_PLAY	( 0x1000 )
/* functions for streams only */
#define ESD_MONITOR	( 0x0000 )
#define ESD_RECORD	( 0x2000 )
/* functions for samples only */
#define ESD_STOP	( 0x0000 )
#define ESD_LOOP	( 0x2000 )

typedef int esd_format_t;
typedef int esd_proto_t;

/*******************************************************************/
/* client side API for playing sounds */

typedef unsigned char octet;

/*******************************************************************/
/* esdlib.c - basic esd client interface functions */

/* opens channel, authenticates connection, and prefares for protos */
/* returns EsounD socket for communication, result < 0 = error */
/* server = listen socket (localhost:5001, 192.168.168.0:9999 */
/* rate, format = (bits | channels | stream | func) */
int esd_open_sound( const char *host );

/* send the authorization cookie, create one if needed */
int esd_send_auth( int sock );

/* lock/unlock will disable/enable foreign clients from connecting */
int esd_lock( int esd );
int esd_unlock( int esd );

/* standby/resume will free/reclaim audio device so others may use it */
int esd_standby( int esd );
int esd_resume( int esd );

/* open a socket for playing, monitoring, or recording as a stream */
/* the *_fallback functions try to open /dev/dsp if there's no EsounD */
int esd_play_stream( esd_format_t format, int rate, 
		     const char *host, const char *name );
int esd_play_stream_fallback( esd_format_t format, int rate, 
			      const char *host, const char *name );
int esd_monitor_stream( esd_format_t format, int rate, 
			const char *host, const char *name );
/* int esd_monitor_stream_fallback( esd_format_t format, int rate ); */
int esd_record_stream( esd_format_t format, int rate, 
		       const char *host, const char *name );
int esd_record_stream_fallback( esd_format_t format, int rate, 
				const char *host, const char *name );
int esd_filter_stream( esd_format_t format, int rate, 
		       const char *host, const char *name );

/* cache a sample in the server returns sample id, < 0 = error */
int esd_sample_cache( int esd, esd_format_t format, const int rate, 
		      const int length, const char *name );
int esd_confirm_sample_cache( int esd );

/* get the sample id for an already-cached sample */
int esd_sample_getid( int esd, const char *name);

/* uncache a sample in the server */
int esd_sample_free( int esd, int sample );

/* play a cached sample once */
int esd_sample_play( int esd, int sample );
/* make a cached sample loop */
int esd_sample_loop( int esd, int sample );

/* stop the looping sample at end */
int esd_sample_stop( int esd, int sample );
/* stop a playing sample immed. */
int esd_sample_kill( int esd, int sample );

/* closes fd, previously obtained by esd_open */
int esd_close( int esd );

/* get the stream latency to esound (latency is number of samples  */
/* at 44.1khz stereo 16 bit - you'll have to adjust if oyur input  */
/* sampling rate is less (in bytes per second)                     */
/* so if you're at 44.1khz stereo 16bit in your stream - your lag  */
/* in bytes woudl be lag * 2 * 2 bytes (2 for stereo, 2 for 16bit) */
/* if your stream is at 22.05 Khz it'll be double this - in mono   */
/* double again ... etc.                                           */
int esd_get_latency(int esd);
    

/*******************************************************************/
/* esdmgr.c - functions to implement a "sound manager" for esd */

/* structures to retrieve information about streams/samples from the server */
typedef struct esd_server_info {

    int version; 		/* server version encoded as an int */
    esd_format_t format;	/* magic int with the format info */
    int rate;			/* sample rate */

} esd_server_info_t;

typedef struct esd_player_info {

    struct esd_player_info *next; /* point to next entry in list */
    esd_server_info_t *server;	/* the server that contains this stream */
    
    int source_id;		/* either a stream fd or sample id */
    char name[ ESD_NAME_MAX ];	/* name of stream for remote control */
    int rate;			/* sample rate */
    int left_vol_scale;		/* volume scaling */
    int right_vol_scale;

    esd_format_t format;	/* magic int with the format info */

} esd_player_info_t;

typedef struct esd_sample_info {

    struct esd_sample_info *next; /* point to next entry in list */
    esd_server_info_t *server;	/* the server that contains this sample */
    
    int sample_id;		/* either a stream fd or sample id */
    char name[ ESD_NAME_MAX ];	/* name of stream for remote control */
    int rate;			/* sample rate */
    int left_vol_scale;		/* volume scaling */
    int right_vol_scale;

    esd_format_t format;	/* magic int with the format info */
    int length;			/* total buffer length */

} esd_sample_info_t;

typedef struct esd_info {

    esd_server_info_t *server;
    esd_player_info_t *player_list;
    esd_sample_info_t *sample_list;

} esd_info_t;

enum esd_standby_mode { 
    ESM_ERROR, ESM_ON_STANDBY, ESM_ON_AUTOSTANDBY, ESM_RUNNING
};
typedef int esd_standby_mode_t;

/* define callbacks for esd_update_info() */
/* what to do when a stream connects, or sample is played */
typedef int esd_new_player_callback_t( esd_player_info_t * );
/* what to do when a stream disconnects, or sample stops playing */
typedef int esd_old_player_callback_t( esd_player_info_t * );
/* what to do when a sample is cached */
typedef int esd_new_sample_callback_t( esd_sample_info_t * );
/* what to do when a sample is uncached */
typedef int esd_old_sample_callback_t( esd_sample_info_t * );

typedef struct esd_update_info_callbacks {
    esd_new_player_callback_t *esd_new_player_callback;
    esd_old_player_callback_t *esd_old_player_callback;
    esd_new_sample_callback_t *esd_new_sample_callback;
    esd_old_sample_callback_t *esd_old_sample_callback;
} esd_update_info_callbacks_t;

/* print server into to stdout */
void esd_print_server_info( esd_server_info_t *server_info );
void esd_print_player_info( esd_player_info_t *player_info );
void esd_print_sample_info( esd_sample_info_t *sample_info );
/* print all info to stdout */
void esd_print_all_info( esd_info_t *all_info );

/* retrieve server properties (sample rate, format, version number) */
esd_server_info_t *esd_get_server_info( int esd );
/* release all memory allocated for the server properties structure */
void esd_free_server_info( esd_server_info_t *server_info );

/* retrieve all information from server */
esd_info_t *esd_get_all_info( int esd );

/* retrieve all information from server, and update until unsubsribed or closed */
esd_info_t *esd_subscribe_all_info( int esd );

/* call to update the info structure with new information, and call callbacks */
esd_info_t *esd_update_info( int esd, esd_info_t *info, 
			     esd_update_info_callbacks_t *callbacks );
esd_info_t *esd_unsubscribe_info( int esd );

/* release all memory allocated for the esd info structure */
void esd_free_all_info( esd_info_t *info );


/* reset the volume panning for a stream */
int esd_set_stream_pan( int esd, int stream_id, 
			int left_scale, int right_scale );

/* reset the default volume panning for a sample */
int esd_set_default_sample_pan( int esd, int sample_id, 
				int left_scale, int right_scale );

/* see if the server is in stnaby, autostandby, etc */
esd_standby_mode_t esd_get_standby_mode( int esd );


/*******************************************************************/
/* esdfile.c - audiofile wrappers for sane handling of files */

int esd_send_file( int esd, AFfilehandle au_file, int frame_length );
int esd_play_file( const char *name_prefix, const char *filename, int fallback );
int esd_file_cache( int esd, const char *name_prefix, const char *filename );


/*******************************************************************/
/* audio.c - abstract the sound hardware for cross platform usage */
extern esd_format_t esd_audio_format;
extern int esd_audio_rate;
extern char *esd_audio_device;

const char *esd_audio_devices( void );
int esd_audio_open( void );
void esd_audio_close( void );
void esd_audio_pause( void );
int esd_audio_write( void *buffer, int buf_size );
int esd_audio_read( void *buffer, int buf_size );
void esd_audio_flush( void );

/******************************************************************/
/* util.c utilities						  */

const char *esd_get_socket_dirname( void );
const char *esd_get_socket_name( void );

int have_ipv6( void );

#ifdef __cplusplus
}
#endif


#endif /* #ifndef ESD_H */