File: Readme.devel

package info (click to toggle)
dbmix 0.9.8-6.3
  • links: PTS
  • area: main
  • in suites: bullseye, buster, jessie, jessie-kfreebsd, sid, stretch
  • size: 2,896 kB
  • sloc: ansic: 12,309; sh: 11,418; makefile: 153
file content (551 lines) | stat: -rw-r--r-- 17,777 bytes parent folder | download | duplicates (6)
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
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
This readme file explains the basic steps necessary to use the dbaudiolib 
audio library in a DBMix client application. It is staright forward, and 
working examples can be found in dbcat and the xmms output plugin.

This file is still incomplete, but now contains explanations of each of the
DBAudiolib API functions.

There are three ways to use dbaudiolib. The first is to statically link 
to the library. I strongly recommmend against static linking.

The second is to use dynamic linking by including -ldbaudiolib in the 
link line of your application. I prefer this method as the client 
application will link at runtime, and any changes to dbaudiolib will be
automatically reflected. 

The third is to use dynamic loading. If you will not be using dynamic 
loading, you can skip to the "Using DBAudiolib Functions" section.  This
method uses a technique that is mostly commonly found in plugin 
architectures. The first few versions of dbaudiolib used this method until
I was enlightened about the runtime linker (method 2).

Quick Explanation of dynamic loading at runtime
===============================================
In order to dynamically load libraries, you need two functions:
dlopen() which will return a "handle" for a requested library
dlsym() - which will return a void * to a requested symbol.

In the worst case scenario, you would need to call dlsym for each 
function or variable that you would like to extract from the libary.
To save time and programming headaches, it is common for a library to 
provide a structure of function pointers for all of its functions, and a 
single function call to retrieve a pointer to that structure. Thus, you
only need to make one call to dlsym().

In DBAudioLib, this structure is as follows:
	typedef struct
	{ 
		int    (*DBAudio_Init)(char * name, int fmt, int rte, int numch,
							   enum channel_type_e type, int chindex);
		int    (*DBAudio_Ready)();
		int    (*DBAudio_Write)(char* buf, int len);
		int    (*DBAudio_Read)(char * buf, int count);
		int    (*DBAudio_Close)();
		int    (*DBAudio_Set_Volume)(int left, int right);
		int    (*DBAudio_Get_Volume)(int *left, int *right);
		int    (*DBAudio_Pause)(int value);
		char * (*DBAudio_Get_Version)();
		char * (*DBAudio_Get_Channel_Name)(char * name);
		int    (*DBAudio_Set_Channel_Name)(char * name);
		enum channel_type_e (*DBAudio_Get_Channel_Type)();
		int    (*DBAudio_Set_Channel_Type)(enum channel_type_e type);
		int    (*DBAudio_Cue_Enabled)();
		int    (*DBAudio_Set_Rate)(int rte);
		int    (*DBAudio_Get_Rate)();
		int    (*DBAudio_Set_Channels)(int numch);
		int    (*DBAudio_Get_Channels)();
		int    (*DBAudio_Set_Format)(int fmt);
		int    (*DBAudio_Get_Format)();
		int    (*DBAudio_Set_Cue)(int flag);
		int    (*DBAudio_Get_Cue)();
		int    (*DBAudio_Get_Bufsize)(int input_bufsize);	
		void   (*DBAudio_perror)(char *str);
		int    (*DBAudio_Set_Message_Handler)(void(*message_handler)(dbfsd_msg msg),int msg_flags);
		int    (*DBAudio_Handle_Message_Queue)();
		int    (* DBAudio_Set_Channel_Flag)(unsigned int flag);
		int    (* DBAudio_Clear_Channel_Flag)(unsigned int flag);
		unsigned int (* DBAudio_Get_Channel_Flags)();

	} DBAudioLibFunctions;


And the function used to retrieve is is:
	
DBAudioLibFunctions * DBAudio_Get_Functions();

Although this guide should be enough for you to link dbaudiolib into your
application, please read the dlopen, dlsym, dlerror, and dlclose man pages.


Step 1: header files
--------------------
There are three headers files necessary to link against and use 
libdbaudiolib.so.1:

#include <dlfcn.h> /* declaration of the dynamic library functions */

#include <dbmix/dbaudiolib.h> /* definitions for DBAudioLib fxns, datatypes
                                 and error codes */
#include <dbmix/dbdebug.h>      /* a couple of dbmix related debug functions
                                 they are not necessary, but are handy =) */

This assume the dbaudiolib.h and dbdebug.h files are in /usr/include/dbmix, 
otherwise copy the files from the include directory in the dbmix 
distribution and reference them locally,

i.e.:
#include "dbaudiolib.h"
#include "dbdebug.h"


Step 2: global variables
------------------------
There are three global variables needed, a handle pointer for the opened
library, a pointer for the DBAudioLibFunctions, and a function pointer to
hold the reference to DBAudio_Get_Functions:

DBAudioLibFunctions * dbaudio;
void * h;
void * (*get_fxns)();


Step 4: Open the library, 
-------------------------
retrieve function pointer to DBAudio_Get_Functions, and retrieve pointer
to function structure.

/* open dbaudiolib with dlopen */
if((h = dlopen("libdbaudiolib.so",RTLD_NOW)) == NULL) 
{
  printf("Failed to open DBAudioLib:: %s\n",dlerror());
  return 1;
}

/* retrieve function pointer to DBAudio_Get_Functions */
if((get_fxns = dlsym(h,"DBAudio_Get_Functions")) == NULL)
{
  printf("Failed to retrieve pntr to DBAudio_Get_Functions: %s\n",dlerror());
  return 1;
}

/* call DBAudio_Get_Functions */
dbaudio = (DBAudioLibFunctions*)get_fxns();


Step 5: Use the DBAudioLibFunctions structure
---------------------------------------------
Use of the function structure is exactly like calling the functions 
themselves, except that you precede the function name with dbaudio->

So the call 
  error = DBAudio_Init("Dbcat",sample_size,sample_rate,numch,type);

becomes:
  error = dbaudio->DBAudio_Init("Dbcat",sample_size,sample_rate,numch,type);

And the call
  count = DBAudio_Write(buf,len)
becomes:
  count = dbaudio->DBAudio_Write(buf,len)

Tada! Simple. For a working example, please check out dbcat.c in the 
DBMix/dbfsd_src directory



DBMix Debugging
===============
DBMix includes two error functions:
void Error(const char* fmt, ...);
void Debug(const char *fmt, ...);

Both accept variable length parameter lists similar to printf(). i.e.:
printf("hello %d %s %x",value,"string",hexvalue);

The implementation of this functions can be found in DBMix/dbfsd_src/debug.c

Debug is controlled by the variable int debug_level. If debug_level > 0, Debug
will output debug messages, otherwise no message will be printed. Specifying the
dbfsd -d option sets debug_level to be 1.

If you are hacking the standard DBMix components, there are a number of developer
helpful things controlled by #ifdef DBMIX_DEBUG sections. DBMIX_DEBUG is not 
defined by default, therefore these sections are not within the stanard 
binaries. To have them included, run ./configure with the --enable-debug option.


Using DBAudiolib Functions
==========================
All dbaudiolib functions behave similarlly in regards to errors. Unless
otherwise noted, they return 0 on success and -1 when an error occurs. 

When an error occurs within dbaudiolib, errno is set to one of the error codes
found within dbaudiolib.h. The problem with this is that perror does not
support these error codes. To solve this, dbaudiolib includes the 
DBAudio_perror() function.  This function behaves like perror, writing a test
explanation of the error to stderr. If the code is unknown (i.e. not a 
dbaudiolib error code), the actual perror function is called to handle it.

Before continuing, please familiarize yourself with the macros and structures
  defined in channel.h and dbaudiolib.h

API Listing

DBAudio_Init

		int    DBAudio_Init(char * name, int fmt, int rte, int numch,
							   enum channel_type_e type, int chindex);

	  Initializes an instance of dbaudiolib by opening communication to dbfsd, 
      and setting channel parameters..  

      If an error occurs errno is set with the proper value and FAILURE 
	  is returned otherwise, returns SUCCESS.

	  Parameters: 
	  fmt   - format of input data (see OSS Programmer's Manual 
	  http://www.opensound.com/pguide/index.html)
	  rte   - input data rate expressed as a whole integer. i.e. 44.1 kHz = 44100
	  numch - number of channels in the input data
	  type  - DBMix channel type, see enum channel_type_e in channel.h
	  chindex - if 0 returns the first available channel, otherwise tries to
                use the channel associated with (chindex -1). If this channel 
                is not free, FAILURE is returned.

	  Pre Condition:
	  - dbaudilib has been linked to the application statically or dynamically.

	  Post Condition
	  - Shared memory channel data created by dbfsd is attached to this process..
	  - From this data, determine the next free/unused channel.  The pointer
	  to this channel is stored in the static global ch variable.
	  - Open communication and signal pipes for communicating with dbfsd

	DBAudio Errors set in errno:
    ERROR_BAD_SAMPLERATE    input samplerate is invalid
    ERROR_BAD_NUMCH         input numch is neither mono nor stereo  
    ERROR_BAD_CHANNEL_ID    requested channel id is out of range
    ERROR_INIT_FAILURE      could not attach shared memory



DBAudio_Ready 

	int DBAudio_Ready();

    If this instance has been initialized and is ready to be written to,
     returns SUCCESS, otherwise returns FAILURE



DBAudio_Write

	int    (*DBAudio_Write)(char* buf, int len);
	
DBAudio_Write behaves similarly to the standard write() function. It is passed
a data buffer and the amount of data within that buffer.  On success it returns
the number of bytes written.

It is within DBAudio_Write that the format conversion and pitch control occurs.
The algorithm has no "memory", and uses an internal buffer of set size for the 
conversions.  If a failure occurs, no data is written to dbfsd.

The drawback of this is that the size of the data buffer given to DBAudio_Write
must be within a certain range for proper operation.  The suggested buffer size
to give to DBAudio_Write is 5120 bytes. Why? The size of a pipe buffer is 4096
bytes on most systems. Writing 5120 insures that the pipe is always full when 
pitches other than 100 are used.

If the data buffer is too big, DBAudio_Write will return FAILURE and set errno 
to be ERROR_TOO_MUCH_DATA.  Decrease your buffer size and try again.

No error is returned when the data buffer is too small, and the data is written
to dbfsd.  Why? For a client that uses an internal looping buffer (xmms), this
error causes data to be dropped at the top of the loop in some situations.  
This in turn causes the audio to skip every few seconds. Becuase the next buffer
in the xmms client should be plenty big enough (another reason for the 5120 byte
size), the skip is avoided.

If the input data buffer is too small, the audio will start skipping when the
pitch is raised above 100%.

It is completely the responsibility of the client to insure that DBAudio_Write is
given enough data to keep the pipe full.  Note that 5120 bytes is the suggested 
size, it is not mandatory. The terminatorX client for example sends 
DBAudio_Write 512 bytes at a time. The reasons for this have to do with tX's 
scratching algorithm. Although 512 << 5120, due to the architecture of 
terminatorX, the write loop is fast enough so that the pipe is always full.


	DBAudio Errors:
    ---------------
    ERROR_BAD_PARAM         input buffer is null, or input lenght < 0
    ERROR_BAD_NUMCH         Audio data is neither mono or stereo
    ERROR_NOT_INITIALIZED   dbaudiolib is not initialized
    ERROR_TOO_MUCH_DATA     Input data is too large for conversion buffers
    ERROR_BAD_FORMAT        OSS audio format is not 16 bit or 8 bit signed data,
                            or 8 bit unsigned data



DBAudio_Read 

	
    int    DBAudio_Read(char * buf, int count);

	Not implemented.


DBAudio_Close

    int     DBAudio_Close()

    Closes this instance and frees all resources. Returns FAILURE if it fails
    to detach shared memory. 


DBAudio_Set_Volume
	
	int DBAudio_Set_Volume(int left, int right);

	left   volume of left audio channel
    right  volume of right audio channel

	sets the volume for the left and right channels for 
	the channel associated with this instance.
	left and right should be within the range 0 <= x <= 100
	


DBAudio_Get_Volume

    int DBAudio_Get_Volume(int *left, int *right);

    returns the volumes associated with the channel for this instance.


DBAudio_Pause

    int  DBAudio_Pause(int value);

    If value is > 0, sets the channels pause flag, 
    otherwise clears the pause flag

	DBAudio Errors:
    ---------------
	ERROR_NOT_INITIALIZED



DBAudio_Get_Version

    char*     DBAudio_Get_Version();

	Returns a character pointer to a globally defined, null terminated string.
    This string IS NOT to be freed by the API user.


DBAudio_Get_Channel_Name

	char* DBAudio_Get_Channel_Name(char* name)

    returns a pointer to the name associated with this channel,
    and also copies the name in to the character buffer
    pointed to by name.
	

	DBAudio Errors:
    ERROR_BAD_PARAM         if name is null
	ERROR_NOT_INITIALIZED   if instance is not initialized
 

DBAudio_Set_Channel_name

	int DBAudio_Set_Channel_Name(char * name)

	Sets the name for this channel to be name.

	DBAudio Errors:
    ERROR_BAD_PARAM         if name is null
	ERROR_NOT_INITIALIZED   if instance is not initialized


DBAudio_Get_Channel_Type

    enum channel_type_e DBAudio_Get_Channel_Type()

	Gets the channel type for this channel. channel_type_e is defined in channel.h

	DBAudio Errors:
	ERROR_NOT_INITIALIZED


DBAudio_Set_Channel_Type

	int DBAudio_Set_Channel_Type(enum channel_type_e type)

	Sets the channel type for this channel.

	DBAudio Errors:
	ERROR_NOT_INITIALIZED
    ERROR_BAD_CHANNELTYPE	requested channel type is not supported


DBAudio_Cue_Enabled 

	int DBAudio_Cue_Enabled()

	if the **system** cue flag is enabled, return true.
	this fucniton *does*not* check to see if cueing for this
	channel is enabled.


DBAudio_Set_Cue

	int DBAudio_Set_Cue(int flag)	 

	if flag is true, set the channels cue flag to be true,
	if flag is false, set the channels cue flag to be false
	else, return failure.

DBAudio_Get_Cue
	 
	int DBAudio_Get_Cue()

	Returnes the value of the cue flag


DBAudio_Get_Rate

    int DBAudio_Get_Rate()

	returns the samplerate for this channel

DBAudio_Set_Rate

    int DBAudio_Set_Rate(int rte)

    Sets the sample rate for this channel to be rte, and modifies the base pitch
    accordingly.

	DBAudio Errors:
    ERROR_BAD_SAMPLERATE   if 8000 < rte < 49000


DBAudio_Set_Channels

	int DBAudio_Set_Channels(int numch)

	Sets the number of audio channels in the input data. This value should be
    either MONO or STEREO as defined in channel.h

	DBAudio Error:
    ERROR_BAD_NUMCH  numch is neither MONO nor STEREO


DBAudio_Get_Channels

    int DBAudio_Get_Channels()

	Returns the value MONO or STEREO to describe the number of audio channels 
    in this DBMix channel.


DBAudio_Set_Format

    int DBAudio_Set_Format(int fmt)

	Set the input format for this channel. Allowed OSS values: 
	AFMT_U8       unsigned 8 bit data
    AFMT_S8       signed 8 bit data 
    AFMT_S16_LE   signed 16 bit little endian data 
    AMFT_S16_BE   signed 16 bit big endian data


DBAudio_Get_Format

    int DBAudio_Get_Format()

    Retrieves the input audio format value for this DBMix channel.


DBAudio_perror

	void DBAudio_perror(char *str)

	Wrapper for the system perror function, and is used in a similar fashion. 
    DBAudio_perror will first check errno against the dbaudiolib error codes. 
    If the error is a dbaudiolib error, the proper descriptive string is output,
    otherwise perror is called. str is a string supplid by the programmer, 
    and is output before the error string, or passed onto perror as appropriate.


DBAudio_Set_Message_Handler

	int DBAudio_Set_Message_Handler(void(*message_handler)(dbfsd_msg msg),
									int msg_flags)

	Sets a application specific signal handler to be called in the event of a 
    DBMix IPC message being recieved by the client. The message_handler 
    parameter is a pointer to a function with protoype:

	 void message_handler(dbfsd_msg msg);

	The msg_flags paramater is an OR'd set of the DBMix message that should be 
    passed to the applications message handler function.

	Thus, if the application wishes to recieve play and stop messages, and 
    defines a app_message_handler function, the set call would look like this:

	DBAudio_Set_Message_Handler(app_message_handler, (DBMSG_PLAY | DBMSG_STOP));

    The possible messages are defined in dbaudiolib.h 
    Note the definition of DBMSG_ALL in case the application wishes to recieve 
    allmessages.

	IMPORTANT: Message Handlingis is turned off by default in DBAudio_Init. 
    You MUST use this function in order for your application to recieve messages.


DBAudio_Handle_Message_Queue

	int DBAudio_Handle_Message_Queue()

	This function checks for any waiting IPC messages and either handles them 
    or calls the application specified message handler.
	
	DBAudio_Write calls this function implicitly. It may be necessary for the
    application to call the function periodically if no data is being output.
    The xmms output plugin implements a thread (or gtk_timeout depending on the
    version) to do this.


DBAudio_Set_Channel_Flag

	int    DBAudio_Set_Channel_Flag(unsigned int flag);

    Sets a flag for this channel. Flags are defined in channel.h
	This flags are used to enable/disable specific capabilities for the
    channel such as:
	is the channel pauseable?
    is it subject to pitch control?
	is it a microphone?

	See dbin.c for examples of how to use these flags.  By default, pause 
    and pitch are enabled while mic is disabled.


DBAudio_Clear_Channel_Flag

	int    DBAudio_Clear_Channel_Flag(unsigned int flag);

	Clears a channel flag for this channel.


DBAudio_Get_Channel_Flags

	unsigned int DBAudio_Get_Channel_Flags();

	Returns an OR'd set of the flags for this channel.