The multi_audio media addon, written by Jerome Duval.

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@2926 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
beveloper
2003-03-17 21:58:35 +00:00
parent 53ea435d7b
commit be4e010170
11 changed files with 3896 additions and 0 deletions
+1
View File
@@ -5,4 +5,5 @@ SubInclude OBOS_TOP src add-ons media media-add-ons reader ;
SubInclude OBOS_TOP src add-ons media media-add-ons writer ;
SubInclude OBOS_TOP src add-ons media media-add-ons legacy ;
SubInclude OBOS_TOP src add-ons media media-add-ons mixer ;
SubInclude OBOS_TOP src add-ons media media-add-ons multi_audio ;
@@ -0,0 +1,9 @@
SubDir OBOS_TOP src add-ons media media-add-ons multi_audio ;
Addon multi_audio.media_addon : media :
MultiAudioAddOn.cpp
MultiAudioDevice.cpp
MultiAudioNode.cpp
;
LinkSharedOSLibs multi_audio.media_addon : be media ;
@@ -0,0 +1,218 @@
/*
* multiaudio replacement media addon for BeOS
*
* Copyright (c) 2002, Jerome Duval ([email protected])
*
* All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <MediaDefs.h>
#include <MediaAddOn.h>
#include <Errors.h>
#include <Node.h>
#include <Mime.h>
#include <StorageDefs.h>
#include <Path.h>
#include <Directory.h>
#include <Entry.h>
#include "MultiAudioNode.h"
#include "MultiAudioAddOn.h"
#include "MultiAudioDevice.h"
#include <limits.h>
#include <stdio.h>
#include <string.h>
#include "debug.h"
// instantiation function
extern "C" _EXPORT BMediaAddOn * make_media_addon(image_id image) {
CALLED();
return new MultiAudioAddOn(image);
}
// -------------------------------------------------------- //
// ctor/dtor
// -------------------------------------------------------- //
MultiAudioAddOn::~MultiAudioAddOn()
{
CALLED();
void *device = NULL;
for ( int32 i = 0; (device = fDevices.ItemAt(i)); i++ )
delete device;
}
MultiAudioAddOn::MultiAudioAddOn(image_id image) :
BMediaAddOn(image),
fDevices()
{
CALLED();
fInitCheckStatus = B_NO_INIT;
if(RecursiveScan("/dev/audio/multi/")!=B_OK)
return;
fInitCheckStatus = B_OK;
}
// -------------------------------------------------------- //
// BMediaAddOn impl
// -------------------------------------------------------- //
status_t MultiAudioAddOn::InitCheck(
const char ** out_failure_text)
{
CALLED();
return B_OK;
}
int32 MultiAudioAddOn::CountFlavors()
{
CALLED();
return fDevices.CountItems();
}
status_t MultiAudioAddOn::GetFlavorAt(
int32 n,
const flavor_info ** out_info)
{
CALLED();
if (out_info == 0) {
fprintf(stderr,"<- B_BAD_VALUE\n");
return B_BAD_VALUE; // we refuse to crash because you were stupid
}
if (n < 0 || n > fDevices.CountItems() - 1) {
fprintf(stderr,"<- B_BAD_INDEX\n");
return B_BAD_INDEX;
}
MultiAudioDevice *device = (MultiAudioDevice *) fDevices.ItemAt(n);
flavor_info * infos = new flavor_info[1];
MultiAudioNode::GetFlavor(&infos[0], n);
infos[0].name = device->MD.friendly_name;
(*out_info) = infos;
return B_OK;
}
BMediaNode * MultiAudioAddOn::InstantiateNodeFor(
const flavor_info * info,
BMessage * config,
status_t * out_error)
{
CALLED();
if (out_error == 0) {
fprintf(stderr,"<- NULL\n");
return 0; // we refuse to crash because you were stupid
}
MultiAudioDevice *device = (MultiAudioDevice*)fDevices.ItemAt(info->internal_id);
if(device == NULL) {
*out_error = B_ERROR;
return NULL;
}
MultiAudioNode * node
= new MultiAudioNode(this,
device->MD.friendly_name,
device,
info->internal_id,
config);
if (node == 0) {
*out_error = B_NO_MEMORY;
fprintf(stderr,"<- B_NO_MEMORY\n");
} else {
*out_error = node->InitCheck();
}
return node;
}
status_t
MultiAudioAddOn::GetConfigurationFor(BMediaNode * your_node, BMessage * into_message)
{
CALLED();
// currently never called by the media kit. Seems it is not implemented.
if (into_message == 0) {
fprintf(stderr,"<- B_BAD_VALUE\n");
return B_BAD_VALUE; // we refuse to crash because you were stupid
}
MultiAudioNode * node = dynamic_cast<MultiAudioNode*>(your_node);
if (node == 0) {
fprintf(stderr,"<- B_BAD_TYPE\n");
return B_BAD_TYPE;
}
return node->GetConfigurationFor(into_message);
}
bool MultiAudioAddOn::WantsAutoStart()
{
CALLED();
return false;
}
status_t MultiAudioAddOn::AutoStart(
int in_count,
BMediaNode ** out_node,
int32 * out_internal_id,
bool * out_has_more)
{
CALLED();
return B_OK;
}
status_t
MultiAudioAddOn::RecursiveScan(char* rootPath, BEntry *rootEntry = NULL)
{
CALLED();
BDirectory root;
if(rootEntry!=NULL)
root.SetTo(rootEntry);
else if(rootPath!=NULL) {
root.SetTo(rootPath);
} else {
PRINT(("Error in MultiAudioAddOn::RecursiveScan null params\n"));
return B_ERROR;
}
BEntry entry;
while(root.GetNextEntry(&entry) > B_ERROR) {
if(entry.IsDirectory()) {
RecursiveScan(rootPath, &entry);
} else {
BPath path;
entry.GetPath(&path);
MultiAudioDevice *device = new MultiAudioDevice(path.Path() + strlen(rootPath), path.Path());
if(device && device->InitCheck() == B_OK)
fDevices.AddItem(device);
}
}
return B_OK;
}
@@ -0,0 +1,76 @@
/*
* multiaudio replacement media addon for BeOS
*
* Copyright (c) 2002, Jerome Duval ([email protected])
*
* All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef _MULTIAUDIOADDON_H
#define _MULTIAUDIOADDON_H
#include <MediaDefs.h>
#include <MediaAddOn.h>
class MultiAudioAddOn :
public BMediaAddOn
{
public:
virtual ~MultiAudioAddOn(void);
explicit MultiAudioAddOn(image_id image);
/**************************/
/* begin from BMediaAddOn */
public:
virtual status_t InitCheck(
const char ** out_failure_text);
virtual int32 CountFlavors(void);
virtual status_t GetFlavorAt(
int32 n,
const flavor_info ** out_info);
virtual BMediaNode * InstantiateNodeFor(
const flavor_info * info,
BMessage * config,
status_t * out_error);
virtual status_t GetConfigurationFor(
BMediaNode * your_node,
BMessage * into_message);
virtual bool WantsAutoStart(void);
virtual status_t AutoStart(
int in_count,
BMediaNode ** out_node,
int32 * out_internal_id,
bool * out_has_more);
/* end from BMediaAddOn */
/************************/
private:
status_t RecursiveScan(char* path, BEntry *rootEntry = NULL);
status_t fInitCheckStatus;
BList fDevices;
};
extern "C" _EXPORT BMediaAddOn *make_media_addon( image_id you );
#endif /* _MULTIAUDIOADDON_H */
@@ -0,0 +1,354 @@
/*
* multiaudio replacement media addon for BeOS
*
* Copyright (c) 2002, Jerome Duval ([email protected])
*
* All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "MultiAudioDevice.h"
#include "debug.h"
#include "driver_io.h"
#include <MediaDefs.h>
#include <string.h>
float SAMPLE_RATES[] = {
8000.0, 11025.0, 12000.0, 16000.0, 22050.0, 24000.0, 32000.0, 44100.0,
48000.0, 64000.0, 88200.0, 96000.0, 176400.0, 192000.0, 384000.0, 1536000.0
};
float MultiAudioDevice::convert_multiaudio_rate_to_media_rate(uint32 rate)
{
uint8 count = 0;
uint8 size = sizeof(SAMPLE_RATES)/sizeof(SAMPLE_RATES[0]);
while(count < size) {
if(rate & 1)
return SAMPLE_RATES[count];
count++;
rate >>= 1;
}
return 0.0;
}
uint32 MultiAudioDevice::convert_media_rate_to_multiaudio_rate(float rate)
{
uint8 count = 0;
uint size = sizeof(SAMPLE_RATES)/sizeof(SAMPLE_RATES[0]);
while(count < size) {
if(rate <= SAMPLE_RATES[count])
return (0x1 << count);
count++;
}
return 0;
}
uint32 MultiAudioDevice::convert_multiaudio_format_to_media_format(uint32 fmt)
{
switch(fmt) {
case B_FMT_FLOAT:
return media_raw_audio_format::B_AUDIO_FLOAT;
case B_FMT_18BIT:
case B_FMT_20BIT:
case B_FMT_24BIT:
case B_FMT_32BIT:
return media_raw_audio_format::B_AUDIO_INT;
case B_FMT_16BIT:
return media_raw_audio_format::B_AUDIO_SHORT;
case B_FMT_8BIT_S:
return media_raw_audio_format::B_AUDIO_CHAR;
case B_FMT_8BIT_U:
return media_raw_audio_format::B_AUDIO_UCHAR;
default:
return 0;
}
}
uint32 MultiAudioDevice::convert_media_format_to_multiaudio_format(uint32 fmt)
{
switch(fmt) {
case media_raw_audio_format::B_AUDIO_FLOAT:
return B_FMT_FLOAT;
case media_raw_audio_format::B_AUDIO_INT:
return B_FMT_32BIT;
case media_raw_audio_format::B_AUDIO_SHORT:
return B_FMT_16BIT;
case media_raw_audio_format::B_AUDIO_CHAR:
return B_FMT_8BIT_S;
case media_raw_audio_format::B_AUDIO_UCHAR:
return B_FMT_8BIT_U;
default:
return 0;
}
}
uint32 MultiAudioDevice::select_multiaudio_rate(uint32 rate)
{
//highest rate
uint32 crate = B_SR_1536000;
while(crate != 0) {
if(rate & crate)
return crate;
crate >>= 1;
}
return 0;
}
uint32 MultiAudioDevice::select_multiaudio_format(uint32 fmt)
{
//highest format
if(fmt & B_FMT_FLOAT) {
return B_FMT_FLOAT;
} else if(fmt & B_FMT_32BIT) {
return B_FMT_32BIT;
} else if(fmt & B_FMT_24BIT) {
return B_FMT_24BIT;
} else if(fmt & B_FMT_20BIT) {
return B_FMT_20BIT;
} else if(fmt & B_FMT_18BIT) {
return B_FMT_18BIT;
} else if(fmt & B_FMT_16BIT) {
return B_FMT_16BIT;
} else if(fmt & B_FMT_8BIT_S) {
return B_FMT_8BIT_S;
} else if(fmt & B_FMT_8BIT_U) {
return B_FMT_8BIT_U;
} else
return 0;
}
MultiAudioDevice::~MultiAudioDevice()
{
CALLED();
if ( fd != 0 ) {
close( fd );
}
}
MultiAudioDevice::MultiAudioDevice(const char* name, const char* path)
{
CALLED();
fInitCheckStatus = B_NO_INIT;
strcpy(fDevice_name, name);
strcpy(fDevice_path, path);
PRINT(("name : %s, path : %s\n", fDevice_name, fDevice_path));
if(InitDriver()!=B_OK)
return;
fInitCheckStatus = B_OK;
}
status_t MultiAudioDevice::InitCheck(void) const
{
CALLED();
return fInitCheckStatus;
}
status_t MultiAudioDevice::InitDriver()
{
multi_channel_enable MCE;
uint32 mce_enable_bits;
int rval, i, num_outputs, num_inputs, num_channels;
CALLED();
//open the device driver for output
fd = open( fDevice_path, O_WRONLY );
if ( fd == 0 ) {
return B_ERROR;
}
//
// Get description
//
MD.info_size = sizeof(MD);
MD.request_channel_count = MAX_CHANNELS;
MD.channels = MCI;
rval = DRIVER_GET_DESCRIPTION(&MD,0);
if (B_OK != rval)
{
fprintf(stderr, "Failed on B_MULTI_GET_DESCRIPTION\n");
return B_ERROR;
}
printf("Friendly name:\t%s\nVendor:\t\t%s\n",
MD.friendly_name,MD.vendor_info);
printf("%ld outputs\t%ld inputs\n%ld out busses\t%ld in busses\n",
MD.output_channel_count,MD.input_channel_count,
MD.output_bus_channel_count,MD.input_bus_channel_count);
printf("\nChannels\n"
"ID\tKind\tDesig\tConnectors\n");
for (i = 0 ; i < (MD.output_channel_count + MD.input_channel_count); i++)
{
printf("%ld\t%d\t0x%lx\t0x%lx\n",MD.channels[i].channel_id,
MD.channels[i].kind,
MD.channels[i].designations,
MD.channels[i].connectors);
}
printf("\n");
printf("Output rates\t\t0x%lx\n",MD.output_rates);
printf("Input rates\t\t0x%lx\n",MD.input_rates);
printf("Max CVSR\t\t%.0f\n",MD.max_cvsr_rate);
printf("Min CVSR\t\t%.0f\n",MD.min_cvsr_rate);
printf("Output formats\t\t0x%lx\n",MD.output_formats);
printf("Input formats\t\t0x%lx\n",MD.input_formats);
printf("Lock sources\t\t0x%lx\n",MD.lock_sources);
printf("Timecode sources\t0x%lx\n",MD.timecode_sources);
printf("Interface flags\t\t0x%lx\n",MD.interface_flags);
printf("Control panel string:\t\t%s\n",MD.control_panel);
printf("\n");
num_outputs = MD.output_channel_count;
num_inputs = MD.input_channel_count;
num_channels = num_outputs + num_inputs;
// Get and set enabled channels
MCE.info_size = sizeof(MCE);
MCE.enable_bits = (uchar *) &mce_enable_bits;
rval = DRIVER_GET_ENABLED_CHANNELS(&MCE, sizeof(MCE));
if (B_OK != rval)
{
fprintf(stderr, "Failed on B_MULTI_GET_ENABLED_CHANNELS len is 0x%lx\n",sizeof(MCE));
return B_ERROR;
}
mce_enable_bits = (1 << num_channels) - 1;
MCE.lock_source = B_MULTI_LOCK_INTERNAL;
rval = DRIVER_SET_ENABLED_CHANNELS(&MCE, 0);
if (B_OK != rval)
{
fprintf(stderr, "Failed on B_MULTI_SET_ENABLED_CHANNELS 0x%p 0x%x\n", MCE.enable_bits, *(MCE.enable_bits));
return B_ERROR;
}
//
// Set the sample rate
//
MFI.info_size = sizeof(MFI);
MFI.output.rate = select_multiaudio_rate(MD.output_rates); //B_SR_48000;
MFI.output.cvsr = 0;
MFI.output.format = select_multiaudio_format(MD.output_formats); //B_FMT_16BIT;
MFI.input.rate = MFI.output.rate;
MFI.input.cvsr = MFI.output.cvsr;
MFI.input.format = MFI.output.format;
rval = DRIVER_SET_GLOBAL_FORMAT(&MFI, 0);
if (B_OK != rval)
{
fprintf(stderr, "Failed on B_MULTI_SET_GLOBAL_FORMAT\n");
return B_ERROR;
}
//
// Get the buffers
//
play_buffer_desc[0] = play_buffer_list0;
play_buffer_desc[1] = play_buffer_list1;
record_buffer_desc[0] = record_buffer_list0;
record_buffer_desc[1] = record_buffer_list1;
MBL.info_size = sizeof(MBL);
MBL.request_playback_buffer_size = 0; //use the default......
MBL.request_playback_buffers = NB_BUFFERS;
MBL.request_playback_channels = num_outputs;
MBL.playback_buffers = (buffer_desc **) play_buffer_desc;
MBL.request_record_buffer_size = 0; //use the default......
MBL.request_record_buffers = NB_BUFFERS;
MBL.request_record_channels = num_inputs;
MBL.record_buffers = (buffer_desc **) record_buffer_desc;
rval = DRIVER_GET_BUFFERS(&MBL, 0);
if (B_OK != rval)
{
fprintf(stderr, "Failed on B_MULTI_GET_BUFFERS\n");
return B_ERROR;
}
for (i = 0; i < MBL.return_playback_buffers; i++)
{
for (int j=0; j < MBL.return_playback_channels; j++)
{
//fPlay[i][j] = (int32 *) MBL.playback_buffers[i][j].base;
PRINT(("MBL.playback_buffers[%d][%d].base: %p\n",
i,j,MBL.playback_buffers[i][j].base));
PRINT(("MBL.playback_buffers[%d][%d].stride: %i\n",
i,j,MBL.playback_buffers[i][j].stride));
}
//memset(MBL.playback_buffers[i][0].base, 0, MBL.return_playback_buffer_size * 4 /*samps to bytes*/);
//PRINT(("Play buffers[%d] size : %li zeroed\n",i, MBL.return_playback_buffer_size * 4));
}
for (i = 0; i < MBL.return_record_buffers; i++)
{
for (int j=0; j < MBL.return_record_channels; j++)
{
/*fRecord[i][j] = (int32 *) MBL.record_buffers[i][j].base;
PRINT(("Record buffers[%d][%d]: %p\n",i,j,fRecord[i][j]));*/
PRINT(("MBL.record_buffers[%d][%d].base: %p\n",
i,j,MBL.record_buffers[i][j].base));
PRINT(("MBL.record_buffers[%d][%d].stride: %i\n",
i,j,MBL.record_buffers[i][j].stride));
}
//memset(MBL.record_buffers[i][0].base, 0, MBL.return_record_buffer_size * 4 /*samps to bytes*/);
//PRINT(("Record buffers[%d] size : %li zeroed\n",i, MBL.return_record_buffer_size * 4));
}
MMCI.info_size = sizeof(MMCI);
MMCI.control_count = MAX_CONTROLS;
MMCI.controls = MMC;
rval = DRIVER_LIST_MIX_CONTROLS(&MMCI, 0);
if (B_OK != rval)
{
fprintf(stderr, "Failed on DRIVER_LIST_MIX_CONTROLS\n");
return B_ERROR;
}
return B_OK;
}
int
MultiAudioDevice::DoBufferExchange(multi_buffer_info *MBI)
{
return DRIVER_BUFFER_EXCHANGE(MBI, 0);
}
int
MultiAudioDevice::DoSetMix(multi_mix_value_info *MMVI)
{
return DRIVER_SET_MIX(MMVI, 0);
}
int
MultiAudioDevice::DoGetMix(multi_mix_value_info *MMVI)
{
return DRIVER_GET_MIX(MMVI, 0);
}
@@ -0,0 +1,88 @@
/*
* multiaudio replacement media addon for BeOS
*
* Copyright (c) 2002, Jerome Duval ([email protected])
*
* All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef _MULTIAUDIODEVICE_H
#define _MULTIAUDIODEVICE_H
#include "multi_audio.h"
#define MAX_CONTROLS 128
#define MAX_CHANNELS 32
#define NB_BUFFERS 2
class MultiAudioDevice
{
protected:
virtual ~MultiAudioDevice(void);
public:
explicit MultiAudioDevice(const char *name, const char* path);
virtual status_t InitCheck(void) const;
static float convert_multiaudio_rate_to_media_rate(uint32 rate);
static uint32 convert_media_rate_to_multiaudio_rate(float rate);
static uint32 convert_multiaudio_format_to_media_format(uint32 fmt);
static uint32 convert_media_format_to_multiaudio_format(uint32 fmt);
static uint32 select_multiaudio_rate(uint32 rate);
static uint32 select_multiaudio_format(uint32 fmt);
int DoBufferExchange(multi_buffer_info *MBI);
int DoSetMix(multi_mix_value_info *MMVI);
int DoGetMix(multi_mix_value_info *MMVI);
private:
status_t InitDriver();
int fd; //file descriptor for hw driver
char fDevice_name[32];
char fDevice_path[32];
public:
multi_description MD;
multi_channel_info MCI[MAX_CHANNELS];
multi_format_info MFI;
multi_buffer_list MBL;
multi_mix_control_info MMCI;
multi_mix_control MMC[MAX_CONTROLS];
/*int32 *fPlay[NB_BUFFERS][MAX_CHANNELS];
int32 *fRecord[NB_BUFFERS][MAX_CHANNELS];*/
buffer_desc play_buffer_list0[MAX_CHANNELS];
buffer_desc play_buffer_list1[MAX_CHANNELS];
buffer_desc *play_buffer_desc[NB_BUFFERS];
buffer_desc record_buffer_list0[MAX_CHANNELS];
buffer_desc record_buffer_list1[MAX_CHANNELS];
buffer_desc *record_buffer_desc[NB_BUFFERS];
private:
status_t fInitCheckStatus;
};
#endif
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,395 @@
/*
* multiaudio replacement media addon for BeOS
*
* Copyright (c) 2002, Jerome Duval ([email protected])
*
* All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef _MULTIAUDIONODE_H
#define _MULTIAUDIONODE_H
#include <MediaDefs.h>
#include <MediaNode.h>
#include <FileInterface.h>
#include <BufferConsumer.h>
#include <BufferProducer.h>
#include <Controllable.h>
#include <MediaEventLooper.h>
#include <TimeSource.h>
#include <Controllable.h>
#include <File.h>
#include <Entry.h>
#include "multi_audio.h"
#include "MultiAudioDevice.h"
/*bool format_is_acceptible(
const media_format & producer_format,
const media_format & consumer_format);*/
class node_input
{
public:
node_input(media_input &input, media_format format);
~node_input();
int32 fChannelId;
media_input fInput;
media_format fPreferredFormat;
media_format fFormat;
uint32 fBufferCycle;
multi_buffer_info fOldMBI;
BBuffer *fBuffer;
};
class node_output
{
public:
node_output(media_output &output, media_format format);
~node_output();
int32 fChannelId;
media_output fOutput;
media_format fPreferredFormat;
media_format fFormat;
BBufferGroup *fBufferGroup;
bool fOutputEnabled;
uint64 fSamplesSent;
volatile uint32 fBufferCycle;
multi_buffer_info fOldMBI;
};
class MultiAudioNode :
public BBufferConsumer,
public BBufferProducer,
public BTimeSource,
public BMediaEventLooper,
public BControllable
{
protected:
virtual ~MultiAudioNode(void);
public:
explicit MultiAudioNode(BMediaAddOn *addon, char* name, MultiAudioDevice *device,
int32 internal_id, BMessage * config);
virtual status_t InitCheck(void) const;
/*************************/
/* begin from BMediaNode */
public:
virtual BMediaAddOn* AddOn(
int32 * internal_id) const; /* Who instantiated you -- or NULL for app class */
protected:
/* These don't return errors; instead, they use the global error condition reporter. */
/* A node is required to have a queue of at least one pending command (plus TimeWarp) */
/* and is recommended to allow for at least one pending command of each type. */
/* Allowing an arbitrary number of outstanding commands might be nice, but apps */
/* cannot depend on that happening. */
virtual void Preroll(void);
public:
virtual status_t HandleMessage(
int32 message,
const void * data,
size_t size);
protected:
virtual void NodeRegistered(void); /* reserved 2 */
virtual status_t RequestCompleted(const media_request_info &info);
virtual void SetTimeSource(BTimeSource *timeSource);
/* end from BMediaNode */
/***********************/
/******************************/
/* begin from BBufferConsumer */
//included from BMediaAddOn
//virtual status_t HandleMessage(
// int32 message,
// const void * data,
// size_t size);
/* Someone, probably the producer, is asking you about this format. Give */
/* your honest opinion, possibly modifying *format. Do not ask upstream */
/* producer about the format, since he's synchronously waiting for your */
/* reply. */
virtual status_t AcceptFormat(
const media_destination & dest,
media_format * format);
virtual status_t GetNextInput(
int32 * cookie,
media_input * out_input);
virtual void DisposeInputCookie(
int32 cookie);
virtual void BufferReceived(
BBuffer * buffer);
virtual void ProducerDataStatus(
const media_destination & for_whom,
int32 status,
bigtime_t at_performance_time);
virtual status_t GetLatencyFor(
const media_destination & for_whom,
bigtime_t * out_latency,
media_node_id * out_timesource);
virtual status_t Connected(
const media_source & producer, /* here's a good place to request buffer group usage */
const media_destination & where,
const media_format & with_format,
media_input * out_input);
virtual void Disconnected(
const media_source & producer,
const media_destination & where);
/* The notification comes from the upstream producer, so he's already cool with */
/* the format; you should not ask him about it in here. */
virtual status_t FormatChanged(
const media_source & producer,
const media_destination & consumer,
int32 change_tag,
const media_format & format);
/* Given a performance time of some previous buffer, retrieve the remembered tag */
/* of the closest (previous or exact) performance time. Set *out_flags to 0; the */
/* idea being that flags can be added later, and the understood flags returned in */
/* *out_flags. */
virtual status_t SeekTagRequested(
const media_destination & destination,
bigtime_t in_target_time,
uint32 in_flags,
media_seek_tag * out_seek_tag,
bigtime_t * out_tagged_time,
uint32 * out_flags);
/* end from BBufferConsumer */
/****************************/
/******************************/
/* begin from BBufferProducer */
virtual status_t FormatSuggestionRequested( media_type type,
int32 quality,
media_format* format);
virtual status_t FormatProposal( const media_source& output,
media_format* format);
virtual status_t FormatChangeRequested( const media_source& source,
const media_destination& destination,
media_format* io_format,
int32* _deprecated_);
virtual status_t GetNextOutput( int32* cookie,
media_output* out_output);
virtual status_t DisposeOutputCookie( int32 cookie);
virtual status_t SetBufferGroup( const media_source& for_source,
BBufferGroup* group);
virtual status_t PrepareToConnect( const media_source& what,
const media_destination& where,
media_format* format,
media_source* out_source,
char* out_name);
virtual void Connect( status_t error,
const media_source& source,
const media_destination& destination,
const media_format& format,
char* io_name);
virtual void Disconnect( const media_source& what,
const media_destination& where);
virtual void LateNoticeReceived( const media_source& what,
bigtime_t how_much,
bigtime_t performance_time);
virtual void EnableOutput( const media_source & what,
bool enabled,
int32* _deprecated_);
virtual void AdditionalBufferRequested( const media_source& source,
media_buffer_id prev_buffer,
bigtime_t prev_time,
const media_seek_tag* prev_tag);
/* end from BBufferProducer */
/****************************/
/*****************/
/* BControllable */
/*****************/
/********************************/
/* start from BMediaEventLooper */
protected:
/* you must override to handle your events! */
/* you should not call HandleEvent directly */
virtual void HandleEvent( const media_timed_event *event,
bigtime_t lateness,
bool realTimeEvent = false);
/* end from BMediaEventLooper */
/******************************/
/********************************/
/* start from BTimeSource */
protected:
virtual void SetRunMode( run_mode mode);
virtual status_t TimeSourceOp( const time_source_op_info &op,
void *_reserved);
/* end from BTimeSource */
/******************************/
/********************************/
/* start from BControllable */
protected:
virtual status_t GetParameterValue( int32 id,
bigtime_t* last_change,
void* value,
size_t* ioSize);
virtual void SetParameterValue( int32 id,
bigtime_t when,
const void* value,
size_t size);
virtual BParameterWeb* MakeParameterWeb();
/* end from BControllable */
/******************************/
protected:
virtual status_t HandleStart(
const media_timed_event *event,
bigtime_t lateness,
bool realTimeEvent = false);
virtual status_t HandleSeek(
const media_timed_event *event,
bigtime_t lateness,
bool realTimeEvent = false);
virtual status_t HandleWarp(
const media_timed_event *event,
bigtime_t lateness,
bool realTimeEvent = false);
virtual status_t HandleStop(
const media_timed_event *event,
bigtime_t lateness,
bool realTimeEvent = false);
virtual status_t HandleBuffer(
const media_timed_event *event,
bigtime_t lateness,
bool realTimeEvent = false);
virtual status_t HandleDataStatus(
const media_timed_event *event,
bigtime_t lateness,
bool realTimeEvent = false);
virtual status_t HandleParameter(
const media_timed_event *event,
bigtime_t lateness,
bool realTimeEvent = false);
public:
static void GetFlavor(flavor_info * outInfo, int32 id);
static void GetFormat(media_format * outFormat);
status_t GetConfigurationFor(BMessage * into_message);
private:
MultiAudioNode( /* private unimplemented */
const MultiAudioNode & clone);
MultiAudioNode & operator=(
const MultiAudioNode & clone);
//void WriteBuffer( BBuffer *buffer, node_input &input );
void WriteZeros(node_input &input, uint32 bufferCycle);
void FillWithZeros(node_input &input);
void FillNextBuffer(node_input &channel, BBuffer* buffer);
static int32 _run_thread_( void *data );
int32 RunThread();
status_t StartThread();
status_t StopThread();
void AllocateBuffers(node_output &channel);
BBuffer* FillNextBuffer( multi_buffer_info &MBI,
node_output &channel);
void UpdateTimeSource(multi_buffer_info &MBI,
multi_buffer_info &oldMBI,
node_input &input);
node_output* FindOutput(media_source source);
node_input* FindInput(media_destination dest);
node_input* FindInput(int32 destinationId);
void ProcessGroup(BParameterGroup *group, int32 index, int32 &nbParameters);
void ProcessMux(BDiscreteParameter *parameter, int32 index);
status_t fInitCheckStatus;
BMediaAddOn *fAddOn;
int32 fId;
//media_input input;
BList fInputs;
bigtime_t fLatency;
BList fOutputs;
media_format fPreferredFormat;
bigtime_t fInternalLatency;
// this is computed from the real (negotiated) chunk size and bit rate,
// not the defaults that are in the parameters
bigtime_t fBufferPeriod;
//volatile uint32 fBufferCycle;
sem_id fBuffer_free;
thread_id fThread;
MultiAudioDevice *fDevice;
//int fd; //file descriptor for hw driver
//char device_name[32];
//multi_description MD;
//multi_format_info MFI;
//multi_buffer_list MBL;
//multi_mix_control_info MMCI;
//multi_mix_control MMC[MAX_CONTROLS];
bool fTimeSourceStarted;
BParameterWeb *fWeb;
};
#endif /* _MULTIAUDIONODE_H */
@@ -0,0 +1,34 @@
#include <stdio.h>
#ifndef NDEBUG
#ifndef DEBUG
#define DEBUG 2
#endif
#if DEBUG >= 1
#define UNIMPLEMENTED() printf("UNIMPLEMENTED %s\n",__PRETTY_FUNCTION__)
#else
#define UNIMPLEMENTED() ((void)0)
#endif
#if DEBUG >= 2
#define BROKEN() printf("BROKEN %s\n",__PRETTY_FUNCTION__)
#else
#define BROKEN() ((void)0)
#endif
#if DEBUG >= 3
#define CALLED() printf("CALLED %s\n",__PRETTY_FUNCTION__)
#else
#define CALLED() ((void)0)
#endif
#else
#define UNIMPLEMENTED() ((void)0)
#define BROKEN() ((void)0)
#define CALLED() ((void)0)
#endif
@@ -0,0 +1,47 @@
/*
* multiaudio replacement media addon for BeOS
*
* Copyright (c) 2002, Jerome Duval ([email protected])
*
* All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef _DRIVER_IO_H
#define _DRIVER_IO_H
#include <unistd.h>
#include <fcntl.h>
#include <Drivers.h>
#include "multi_audio.h"
#define DRIVER_GET_DESCRIPTION(x...) ioctl( fd, B_MULTI_GET_DESCRIPTION, x )
#define DRIVER_GET_ENABLED_CHANNELS(x...) ioctl( fd, B_MULTI_GET_ENABLED_CHANNELS, x )
#define DRIVER_SET_ENABLED_CHANNELS(x...) ioctl( fd, B_MULTI_SET_ENABLED_CHANNELS, x )
#define DRIVER_SET_GLOBAL_FORMAT(x...) ioctl( fd, B_MULTI_SET_GLOBAL_FORMAT, x )
#define DRIVER_GET_BUFFERS(x...) ioctl( fd, B_MULTI_GET_BUFFERS, x )
#define DRIVER_BUFFER_EXCHANGE(x...) ioctl( fd, B_MULTI_BUFFER_EXCHANGE, x )
#define DRIVER_LIST_MIX_CONTROLS(x...) ioctl( fd, B_MULTI_LIST_MIX_CONTROLS, x )
#define DRIVER_SET_MIX(x...) ioctl( fd, B_MULTI_SET_MIX, x )
#define DRIVER_GET_MIX(x...) ioctl( fd, B_MULTI_GET_MIX, x )
#endif
@@ -0,0 +1,699 @@
/* multi_audio.h */
/* Interface description for drivers implementing studio-level audio I/O with */
/* possible auxillary functions (transport, time code, etc). */
/* Copyright © 1998-1999 Be Incorporated. All rights reserved. */
/* This is the first release candidate for the API. Unless we hear feedback that */
/* forces a change before the end of August, we will try to stay binary compatible */
/* with this interface. */
/* Send feedback to [email protected] [1999-07-02] */
#if !defined(_MULTI_AUDIO_H)
#define _MULTI_AUDIO_H
#include <Drivers.h>
#include <Debug.h>
#define B_MULTI_DRIVER_BASE (B_AUDIO_DRIVER_BASE+20)
enum { /* open() modes */
/* O_RDONLY is 0, O_WRONLY is 1, O_RDWR is 2 */
B_MULTI_CONTROL = 3
};
/* ioctl codes */
enum {
/* multi_description */
B_MULTI_GET_DESCRIPTION = B_MULTI_DRIVER_BASE,
/* multi_event_handling */
B_MULTI_GET_EVENT_INFO,
B_MULTI_SET_EVENT_INFO,
B_MULTI_GET_EVENT,
/* multi_channel_enable */
B_MULTI_GET_ENABLED_CHANNELS,
B_MULTI_SET_ENABLED_CHANNELS,
/* multi_format_info */
B_MULTI_GET_GLOBAL_FORMAT,
B_MULTI_SET_GLOBAL_FORMAT, /* always sets for all channels, always implemented */
/* multi_channel_formats */
B_MULTI_GET_CHANNEL_FORMATS,
B_MULTI_SET_CHANNEL_FORMATS, /* only implemented if possible */
/* multi_mix_value_info */
B_MULTI_GET_MIX,
B_MULTI_SET_MIX,
/* multi_mix_channel_info */
B_MULTI_LIST_MIX_CHANNELS,
/* multi_mix_control_info */
B_MULTI_LIST_MIX_CONTROLS,
/* multi_mix_connection_info */
B_MULTI_LIST_MIX_CONNECTIONS,
/* multi_buffer_list */
B_MULTI_GET_BUFFERS, /* Fill out the struct for the first time; doesn't start anything. */
B_MULTI_SET_BUFFERS, /* Set what buffers to use, if the driver supports soft buffers. */
/* bigtime_t */
B_MULTI_SET_START_TIME, /* When to actually start */
/* multi_buffer_info */
B_MULTI_BUFFER_EXCHANGE, /* stop and go are derived from this being called */
B_MULTI_BUFFER_FORCE_STOP, /* force stop of playback */
/* extension protocol */
B_MULTI_LIST_EXTENSIONS, /* get a list of supported extensions */
B_MULTI_GET_EXTENSION, /* get the value of an extension (or return error if not supported) */
B_MULTI_SET_EXTENSION, /* set the value of an extension */
/* multi_mode_list */
B_MULTI_LIST_MODES, /* get a list of possible modes (multi_mode_list * arg) */
B_MULTI_GET_MODE, /* get the current mode (int32 * arg) */
B_MULTI_SET_MODE /* set a new mode (int32 * arg) */
};
/* sample rate values */
/* various fixed sample rates we support (for hard-sync clocked values) */
#define B_SR_8000 0x1
#define B_SR_11025 0x2
#define B_SR_12000 0x4
#define B_SR_16000 0x8
#define B_SR_22050 0x10
#define B_SR_24000 0x20
#define B_SR_32000 0x40
#define B_SR_44100 0x80
#define B_SR_48000 0x100
#define B_SR_64000 0x200
#define B_SR_88200 0x400
#define B_SR_96000 0x800
#define B_SR_176400 0x1000
#define B_SR_192000 0x2000
#define B_SR_384000 0x4000
#define B_SR_1536000 0x10000
/* continuously variable sample rate (typically board-generated) */
#define B_SR_CVSR 0x10000000UL
/* sample rate parameter global to all channels (input and output rates respectively) */
#define B_SR_IS_GLOBAL 0x80000000UL
/* output sample rate locked to input sample rate (output_rates only; the common case!) */
#define B_SR_SAME_AS_INPUT 0x40000000UL
/* format values */
/* signed char */
#define B_FMT_8BIT_S 0x01
/* unsigned char -- this is special case */
#define B_FMT_8BIT_U 0x02
/* traditional 16 bit signed format (host endian) */
#define B_FMT_16BIT 0x10
/* left-adjusted in 32 bit signed word */
#define B_FMT_18BIT 0x20
#define B_FMT_20BIT 0x40
#define B_FMT_24BIT 0x100
#define B_FMT_32BIT 0x1000
/* 32-bit floating point, -1.0 to 1.0 */
#define B_FMT_FLOAT 0x20000
/* 64-bit floating point, -1.0 to 1.0 */
#define B_FMT_DOUBLE 0x40000
/* 80-bit floating point, -1.0 to 1.0 */
#define B_FMT_EXTENDED 0x80000
/* bit stream */
#define B_FMT_BITSTREAM 0x1000000
/* format parameter global to all channels (input and output formats respectively) */
#define B_FMT_IS_GLOBAL 0x80000000UL
/* output format locked to input format (output_formats) */
#define B_FMT_SAME_AS_INPUT 0x40000000UL
/* possible sample lock sources */
#define B_MULTI_LOCK_INPUT_CHANNEL 0x0 /* lock_source_data is channel id */
#define B_MULTI_LOCK_INTERNAL 0x1
#define B_MULTI_LOCK_WORDCLOCK 0x2
#define B_MULTI_LOCK_SUPERCLOCK 0x4
#define B_MULTI_LOCK_LIGHTPIPE 0x8
#define B_MULTI_LOCK_VIDEO 0x10 /* or blackburst */
#define B_MULTI_LOCK_FIRST_CARD 0x20 /* if you have more than one card */
#define B_MULTI_LOCK_MTC 0x40
#define B_MULTI_LOCK_SPDIF 0x80
/* possible timecode sources */
#define B_MULTI_TIMECODE_MTC 0x1
#define B_MULTI_TIMECODE_VTC 0x2
#define B_MULTI_TIMECODE_SMPTE 0x4
#define B_MULTI_TIMECODE_SUPERCLOCK 0x8
#define B_MULTI_TIMECODE_FIREWIRE 0x10
/* interface_flags values */
/* Available functions on this device. */
#define B_MULTI_INTERFACE_PLAYBACK 0x1
#define B_MULTI_INTERFACE_RECORD 0x2
#define B_MULTI_INTERFACE_TRANSPORT 0x4
#define B_MULTI_INTERFACE_TIMECODE 0x8
/* "Soft" buffers means you can change the pointer values and the driver will still be happy. */
#define B_MULTI_INTERFACE_SOFT_PLAY_BUFFERS 0x10000
#define B_MULTI_INTERFACE_SOFT_REC_BUFFERS 0x20000
/* Whether the data stream is interrupted when changing channel enables. */
#define B_MULTI_INTERFACE_CLICKS_WHEN_ENABLING_OUTPUTS 0x40000
#define B_MULTI_INTERFACE_CLICKS_WHEN_ENABLING_INPUTS 0x80000
#define B_CURRENT_INTERFACE_VERSION 0x4502
#define B_MINIMUM_INTERFACE_VERSION 0x4502
typedef struct multi_description multi_description;
typedef struct multi_channel_info multi_channel_info;
struct multi_description {
size_t info_size; /* sizeof(multi_description) */
uint32 interface_version; /* current version of interface that's implemented */
uint32 interface_minimum; /* minimum version required to understand driver */
char friendly_name[32]; /* name displayed to user (C string) */
char vendor_info[32]; /* name used internally by vendor (C string) */
int32 output_channel_count;
int32 input_channel_count;
int32 output_bus_channel_count;
int32 input_bus_channel_count;
int32 aux_bus_channel_count;
int32 request_channel_count; /* how many channel_infos are there */
multi_channel_info *
channels;
uint32 output_rates;
uint32 input_rates;
float min_cvsr_rate;
float max_cvsr_rate;
uint32 output_formats;
uint32 input_formats;
uint32 lock_sources;
uint32 timecode_sources;
uint32 interface_flags;
bigtime_t start_latency; /* how much in advance driver needs SET_START_TIME */
uint32 _reserved_[11];
char control_panel[64]; /* MIME type of control panel application */
};
#if !defined(_MEDIA_DEFS_H) /* enum in MediaDefs.h */
/* designation values */
/* mono channels have no designation */
#define B_CHANNEL_LEFT 0x1
#define B_CHANNEL_RIGHT 0x2
#define B_CHANNEL_CENTER 0x4 /* 5.1+ or fake surround */
#define B_CHANNEL_SUB 0x8 /* 5.1+ */
#define B_CHANNEL_REARLEFT 0x10 /* quad surround or 5.1+ */
#define B_CHANNEL_REARRIGHT 0x20 /* quad surround or 5.1+ */
#define B_CHANNEL_FRONT_LEFT_CENTER 0x40
#define B_CHANNEL_FRONT_RIGHT_CENTER 0x80
#define B_CHANNEL_BACK_CENTER 0x100 /* 6.1 or fake surround */
#define B_CHANNEL_SIDE_LEFT 0x200
#define B_CHANNEL_SIDE_RIGHT 0x400
#define B_CHANNEL_TOP_CENTER 0x800
#define B_CHANNEL_TOP_FRONT_LEFT 0x1000
#define B_CHANNEL_TOP_FRONT_CENTER 0x2000
#define B_CHANNEL_TOP_FRONT_RIGHT 0x4000
#define B_CHANNEL_TOP_BACK_LEFT 0x8000
#define B_CHANNEL_TOP_BACK_CENTER 0x10000
#define B_CHANNEL_TOP_BACK_RIGHT 0x20000
#endif
#define B_CHANNEL_MONO_BUS 0x4000000
#define B_CHANNEL_STEREO_BUS 0x2000000 /* + left/right */
#define B_CHANNEL_SURROUND_BUS 0x1000000 /* multichannel */
/* If you have interactions where some inputs can not be used when some */
/* outputs are used, mark both inputs and outputs with this flag. */
#define B_CHANNEL_INTERACTION 0x80000000UL
/* If input channel #n is simplexed with output channel #n, they should both */
/* have this flag set (different from the previous flag, which is more vague). */
#define B_CHANNEL_SIMPLEX 0x40000000UL
/* connector values */
/* analog connectors */
#define B_CHANNEL_RCA 0x1
#define B_CHANNEL_XLR 0x2
#define B_CHANNEL_TRS 0x4
#define B_CHANNEL_QUARTER_INCH_MONO 0x8
#define B_CHANNEL_MINI_JACK_STEREO 0x10
#define B_CHANNEL_QUARTER_INCH_STEREO 0x20
#define B_CHANNEL_ANALOG_HEADER 0x100 /* internal on card */
#define B_CHANNEL_SNAKE 0x200 /* or D-sub */
/* digital connectors (stereo) */
#define B_CHANNEL_OPTICAL_SPDIF 0x1000
#define B_CHANNEL_COAX_SPDIF 0x2000
#define B_CHANNEL_COAX_EBU 0x4000
#define B_CHANNEL_XLR_EBU 0x8000
#define B_CHANNEL_TRS_EBU 0x10000
#define B_CHANNEL_SPDIF_HEADER 0x20000 /* internal on card */
/* multi-channel digital connectors */
#define B_CHANNEL_LIGHTPIPE 0x100000
#define B_CHANNEL_TDIF 0x200000
#define B_CHANNEL_FIREWIRE 0x400000
#define B_CHANNEL_USB 0x800000
/* If you have multiple output connectors, only one of which can */
/* be active at a time. */
#define B_CHANNEL_EXCLUSIVE_SELECTION 0x80000000UL
typedef enum {
B_MULTI_NO_CHANNEL_KIND,
B_MULTI_OUTPUT_CHANNEL = 0x1,
B_MULTI_INPUT_CHANNEL = 0x2,
B_MULTI_OUTPUT_BUS = 0x4,
B_MULTI_INPUT_BUS = 0x8,
B_MULTI_AUX_BUS = 0x10
} channel_kind;
struct multi_channel_info {
int32 channel_id;
channel_kind kind;
uint32 designations;
uint32 connectors;
uint32 _reserved_[4];
};
/* Constants */
#define B_MULTI_EVENT_MINMAX 16
/* Event flags/masks */
#define B_MULTI_EVENT_TRANSPORT 0x40000000UL
#define B_MULTI_EVENT_HAS_TIMECODE 0x80000000UL
/* possible transport events */
#define B_MULTI_EVENT_NONE 0x00000000UL
#define B_MULTI_EVENT_START 0x40010000UL
#define B_MULTI_EVENT_LOCATION 0x40020000UL /* location when shuttling or locating */
#define B_MULTI_EVENT_SHUTTLING 0x40040000UL
#define B_MULTI_EVENT_STOP 0x40080000UL
#define B_MULTI_EVENT_RECORD 0x40100000UL
#define B_MULTI_EVENT_PAUSE 0x40200000UL
#define B_MULTI_EVENT_RUNNING 0x40400000UL /* location when running */
/* possible device events */
enum {
B_MULTI_EVENT_STARTED = 0x1,
B_MULTI_EVENT_STOPPED = 0x2,
B_MULTI_EVENT_CHANNEL_FORMAT_CHANGED= 0x4,
B_MULTI_EVENT_BUFFER_OVERRUN = 0x8,
B_MULTI_EVENT_SIGNAL_LOST = 0x10,
B_MULTI_EVENT_SIGNAL_DETECTED = 0x20,
B_MULTI_EVENT_CLOCK_LOST = 0x40,
B_MULTI_EVENT_CLOCK_DETECTED = 0x80,
B_MULTI_EVENT_NEW_MODE = 0x100,
B_MULTI_EVENT_CONTROL_CHANGED = 0x200
};
typedef struct multi_get_event_info multi_get_event_info;
struct multi_get_event_info {
size_t info_size; /* sizeof(multi_get_event_info) */
uint32 supported_mask; /* what events h/w supports */
uint32 current_mask; /* current driver value */
uint32 queue_size; /* current queue size */
uint32 event_count; /* number of events currently in queue*/
uint32 _reserved[3];
};
typedef struct multi_set_event_info multi_set_event_info;
struct multi_set_event_info {
size_t info_size; /* sizeof(multi_set_event_info) */
uint32 in_mask; /* what events to wait for */
int32 semaphore; /* semaphore app will wait on */
uint32 queue_size; /* minimum number of events to save */
uint32 _reserved[4];
};
typedef struct multi_get_event multi_get_event;
struct multi_get_event {
size_t info_size; /* sizeof(multi_get_event) */
uint32 event;
bigtime_t timestamp; /* real time at which event was received */
int32 count; /* used for configuration events */
union {
int32 channels[100];
uint32 clocks;
int32 mode;
int32 controls[100];
struct { /* transport event */
float out_rate; /* what rate it's now playing at */
int32 out_hours; /* location at the time given */
int32 out_minutes;
int32 out_seconds;
int32 out_frames;
}transport;
char _reserved_[400];
#if defined(__cplusplus)
};
#else
} u;
#endif
uint32 _reserved_1[10];
};
typedef struct multi_channel_enable multi_channel_enable;
struct multi_channel_enable {
size_t info_size; /* sizeof(multi_channel_enable) */
/* this must have bytes for all channels (see multi_description) */
/* channel 0 is lowest bit of first byte */
uchar * enable_bits;
uint32 lock_source;
int32 lock_data;
uint32 timecode_source;
uint32 * connectors; /* which connector(s) is/are active, per channel */
};
#include <stdio.h>
#if defined(__cplusplus)
inline void B_SET_CHANNEL(void * bits, int channel, bool value)
{
ASSERT(channel>=0);
(((uchar *)(bits))[((channel)&0x7fff)>>3] =
(((uchar *)(bits))[((channel)&0x7fff)>>3] & ~(1<<((channel)&0x7))) |
((value) ? (1<<((channel)&0x7)) : 0));
}
inline bool B_TEST_CHANNEL(const void * bits, int channel)
{
return ((((uchar *)(bits))[((channel)&0x7fff)>>3] >> ((channel)&0x7)) & 1);
}
#else
#define B_SET_CHANNEL(bits, channel, value) \
ASSERT(channel>=0); \
(((uchar *)(bits))[((channel)&0x7fff)>>3] = \
(((uchar *)(bits))[((channel)&0x7fff)>>3] & ~(1<<((channel)&0x7))) | \
((value) ? (1<<((channel)&0x7)) : 0))
#define B_TEST_CHANNEL(bits, channel) \
((((uchar *)(bits))[((channel)&0x7fff)>>3] >> ((channel)&0x7)) & 1)
#endif
typedef struct multi_channel_formats multi_channel_formats;
typedef struct multi_format_info multi_format_info;
typedef struct _multi_format _multi_format;
struct _multi_format {
uint32 rate;
float cvsr;
uint32 format;
uint32 _reserved_[3];
};
enum { /* timecode kinds */
B_MULTI_NO_TIMECODE,
B_MULTI_TIMECODE_30, /* MIDI */
B_MULTI_TIMECODE_30_DROP_2, /* NTSC */
B_MULTI_TIMECODE_30_DROP_4, /* Brazil */
B_MULTI_TIMECODE_25, /* PAL */
B_MULTI_TIMECODE_24 /* Film */
};
struct multi_format_info {
size_t info_size; /* sizeof(multi_format_info) */
bigtime_t output_latency;
bigtime_t input_latency;
int32 timecode_kind;
uint32 _reserved_[7];
_multi_format input;
_multi_format output;
};
struct multi_channel_formats {
size_t info_size; /* sizeof(multi_channel_formats) */
int32 request_channel_count;
int32 request_first_channel;
int32 returned_channel_count;
int32 timecode_kind;
int32 _reserved_[4];
_multi_format *
channels;
bigtime_t * latencies; /* DMA/hardware latencies; client calculates for buffers */
};
typedef struct multi_mix_value multi_mix_value;
struct multi_mix_value {
int32 id;
union {
float gain;
uint32 mux; /* bitmask of mux points */
bool enable;
uint32 _reserved_[2];
#if defined(__cplusplus)
};
#else
} u;
#endif
int32 ramp;
uint32 _reserved_2[2];
};
typedef struct multi_mix_value_info multi_mix_value_info;
struct multi_mix_value_info {
size_t info_size; /* sizeof(multi_mix_value_info) */
int32 item_count;
multi_mix_value *
values;
int32 at_frame; /* time at which to start the change */
};
// only one of these should be set
#define B_MULTI_MIX_JUNCTION 0x1
#define B_MULTI_MIX_GAIN 0x2
#define B_MULTI_MIX_MUX 0x4
#define B_MULTI_MIX_ENABLE 0x8
#define B_MULTI_MIX_GROUP 0x10
#define B_MULTI_MIX_KIND_MASK 0xffff
#define B_MULTI_MIX_MUX_VALUE 0x0104
// any combination of these can be set
#define B_MULTI_MIX_RAMP 0x10000
enum strind_id {
S_null = 0, S_OUTPUT, S_INPUT, S_SETUP, S_TONE_CONTROL, S_EXTENDED_SETUP,
S_ENHANDED_SETUP, S_MASTER, S_BEEP, S_PHONE, S_MIC, S_LINE, S_CD, S_VIDEO,
S_AUX, S_WAVE, S_GAIN, S_LEVEL, S_VOLUME, S_MUTE, S_ENABLE, S_STEREO_MIX,
S_MONO_MIX, S_OUTPUT_STEREO_MIX, S_OUTPUT_MONO_MIX, S_OUTPUT_BASS,
S_OUTPUT_TREBLE, S_OUTPUT_3D_CENTER, S_OUTPUT_3D_DEPTH,
S_USERID = 1000000
};
typedef struct multi_mix_control multi_mix_control;
struct multi_mix_control {
int32 id; /* unique for device -- not same id as any channel/bus ! */
uint32 flags; /* including kind */
int32 master; /* or 0 if it's not slaved */
union {
struct {
float min_gain; /* dB */
float max_gain; /* dB */
float granularity; /* dB */
} gain;
struct {
uint32 _reserved;
} mux;
struct {
uint32 _reserved;
} enable;
uint32 _reserved[12];
#if defined(__cplusplus)
};
#else
} u;
#endif
enum strind_id string; /* string id (S_null : use name) */
int32 parent; /* parent id */
char name[48];
};
typedef struct multi_mix_channel_info multi_mix_channel_info;
struct multi_mix_channel_info {
size_t info_size; /* sizeof(multi_mix_channel_info) */
int32 channel_count;
int32 * channels; /* allocated by caller, lists requested channels */
int32 max_count; /* in: control ids per channel */
int32 actual_count; /* out: actual max # controls for any individual requested channel */
int32 ** controls;
};
typedef struct multi_mix_control_info multi_mix_control_info;
struct multi_mix_control_info {
size_t info_size; /* sizeof(multi_mix_control_info) */
int32 control_count; /* in: number of controls */
multi_mix_control *
controls; /* allocated by caller, returns control description for each */
};
typedef struct multi_mix_connection multi_mix_connection;
struct multi_mix_connection {
int32 from;
int32 to;
uint32 _reserved_[2];
};
typedef struct multi_mix_connection_info multi_mix_connection_info;
struct multi_mix_connection_info {
size_t info_size;
int32 max_count; /* in: available space */
int32 actual_count; /* out: actual count */
multi_mix_connection *
connections; /* allocated by caller, returns connections */
};
/* possible flags values for what is available (in and out) */
#define B_MULTI_BUFFER_PLAYBACK 0x1
#define B_MULTI_BUFFER_RECORD 0x2
#define B_MULTI_BUFFER_METERING 0x4
#define B_MULTI_BUFFER_TIMECODE 0x40000
typedef struct multi_buffer_list multi_buffer_list;
typedef struct buffer_desc buffer_desc;
/* This struct is used to query the driver about what buffers it will use, */
/* and to tell it what buffers to use if it supports soft buffers. */
struct multi_buffer_list {
size_t info_size; /* sizeof(multi_buffer_list) */
uint32 flags;
int32 request_playback_buffers;
int32 request_playback_channels;
uint32 request_playback_buffer_size; /* frames per buffer */
int32 return_playback_buffers; /* playback_buffers[b][] */
int32 return_playback_channels; /* playback_buffers[][c] */
uint32 return_playback_buffer_size; /* frames */
buffer_desc ** playback_buffers;
void * _reserved_1;
int32 request_record_buffers;
int32 request_record_channels;
uint32 request_record_buffer_size; /* frames per buffer */
int32 return_record_buffers;
int32 return_record_channels;
uint32 return_record_buffer_size; /* frames */
buffer_desc ** record_buffers;
void * _reserved_2;
};
struct buffer_desc {
char * base; /* pointer to first sample for channel for buffer */
size_t stride; /* offset to next sample */
uint32 _reserved_[2];
};
/* This struct is used when actually queuing data to be played, and/or */
/* receiving data from a recorder. */
typedef struct multi_buffer_info multi_buffer_info;
struct multi_buffer_info {
size_t info_size; /* sizeof(multi_buffer_info) */
uint32 flags;
bigtime_t played_real_time;
bigtime_t played_frames_count;
int32 _reserved_0;
int32 playback_buffer_cycle;
bigtime_t recorded_real_time;
bigtime_t recorded_frames_count;
int32 _reserved_1;
int32 record_buffer_cycle;
int32 meter_channel_count;
char * meters_peak; /* in the same format as the data; allocated by caller */
char * meters_average; /* in the same format as the data; allocated by caller */
/* timecode sent and received at buffer swap */
int32 hours;
int32 minutes;
int32 seconds;
int32 tc_frames; /* for timecode frames as opposed to sample frames */
int32 at_frame_delta; /* how far into buffer (or before buffer for negative) */
};
typedef struct multi_mode_info multi_mode_info;
typedef struct multi_mode_list multi_mode_list;
struct multi_mode_list {
size_t info_size; /* sizeof(multi_mode_list) */
int32 in_request_count;
int32 out_actual_count;
int32 out_current_mode;
multi_mode_info *
io_modes;
};
struct multi_mode_info {
int32 mode_id;
uint32 flags;
char mode_name[64];
int32 input_channel_count;
int32 output_channel_count;
float best_frame_rate_in;
float best_frame_rate_out;
uint32 sample_formats_in;
uint32 sample_formats_out;
char _reserved[160];
};
/* This extension protocol can grow however much you want. */
/* Good extensions should be put into this header; really */
/* good extensions should become part of the regular API. */
/* For developer-developed extensions, use all lowercase */
/* and digits (no upper case). If we then bless a third- */
/* party extension, we can just upper-case the selector. */
typedef struct multi_extension_list multi_extension_list;
typedef struct multi_extension_info multi_extension_info;
struct multi_extension_info {
uint32 code;
uint32 flags;
char name[24];
};
#define B_MULTI_MAX_EXTENSION_COUNT 31
struct multi_extension_list { /* MULTI_LIST_EXTENSIONS */
size_t info_size; /* sizeof(multi_extension_list) */
uint32 max_count;
int32 actual_count; /* return # of actual extensions */
multi_extension_info *
extensions; /* allocated by caller */
};
typedef struct multi_extension_cmd multi_extension_cmd;
struct multi_extension_cmd { /* MULTI_GET_EXTENSION and MULTI_SET_EXTENSION */
size_t info_size; /* sizeof(multi_extension_cmd) */
uint32 code;
uint32 _reserved_1;
void * in_data;
size_t in_size;
void * out_data;
size_t out_size;
};
enum {
B_MULTI_EX_CLOCK_GENERATION = 'CLGE',
B_MULTI_EX_DIGITAL_FORMAT = 'DIFO',
B_MULTI_EX_OUTPUT_NOMINAL = 'OUNO',
B_MULTI_EX_INPUT_NOMINAL = 'INNO'
};
typedef struct multi_ex_clock_generation multi_ex_clock_generation;
struct multi_ex_clock_generation {
int32 channel; /* if specific, or -1 for all */
uint32 clock; /* WORDCLOCK or SUPERCLOCK, typically */
};
typedef struct multi_ex_digital_format multi_ex_digital_format;
struct multi_ex_digital_format {
int32 channel; /* if specific, or -1 for all */
uint32 format; /* B_CHANNEL_*_SPDIF or B_CHANNEL_*_EBU */
};
enum {
B_MULTI_NOMINAL_MINUS_10 = 1,
B_MULTI_NOMINAL_PLUS_4
};
typedef struct multi_ex_nominal_level multi_ex_nominal_level;
struct multi_ex_nominal_level {
int32 channel; /* if specific, or -1 for all */
int32 level;
};
#endif /* _MULTI_AUDIO_H */