* Moved general multi_audio functions into their own file MultiAudioUtility.cpp;
they don't really belong to the MultiAudioDevice class. * Major coding style cleanup, part I - no functional change, I hope :-) git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@24578 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -12,6 +12,7 @@ Addon hmulti_audio.media_addon :
|
|||||||
MultiAudioAddOn.cpp
|
MultiAudioAddOn.cpp
|
||||||
MultiAudioDevice.cpp
|
MultiAudioDevice.cpp
|
||||||
MultiAudioNode.cpp
|
MultiAudioNode.cpp
|
||||||
|
MultiAudioUtility.cpp
|
||||||
: be media
|
: be media
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|||||||
@@ -26,15 +26,18 @@
|
|||||||
|
|
||||||
#define MULTI_SAVE
|
#define MULTI_SAVE
|
||||||
|
|
||||||
// instantiation function
|
|
||||||
extern "C" _EXPORT BMediaAddOn * make_media_addon(image_id image) {
|
//! instantiation function
|
||||||
|
extern "C" BMediaAddOn*
|
||||||
|
make_media_addon(image_id image)
|
||||||
|
{
|
||||||
CALLED();
|
CALLED();
|
||||||
return new MultiAudioAddOn(image);
|
return new MultiAudioAddOn(image);
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------- //
|
|
||||||
// ctor/dtor
|
// #pragma mark -
|
||||||
// -------------------------------------------------------- //
|
|
||||||
|
|
||||||
MultiAudioAddOn::~MultiAudioAddOn()
|
MultiAudioAddOn::~MultiAudioAddOn()
|
||||||
{
|
{
|
||||||
@@ -47,8 +50,9 @@ MultiAudioAddOn::~MultiAudioAddOn()
|
|||||||
SaveSettings();
|
SaveSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
MultiAudioAddOn::MultiAudioAddOn(image_id image) :
|
|
||||||
BMediaAddOn(image),
|
MultiAudioAddOn::MultiAudioAddOn(image_id image)
|
||||||
|
: BMediaAddOn(image),
|
||||||
fDevices()
|
fDevices()
|
||||||
{
|
{
|
||||||
CALLED();
|
CALLED();
|
||||||
@@ -66,80 +70,78 @@ MultiAudioAddOn::MultiAudioAddOn(image_id image) :
|
|||||||
// BMediaAddOn impl
|
// BMediaAddOn impl
|
||||||
// -------------------------------------------------------- //
|
// -------------------------------------------------------- //
|
||||||
|
|
||||||
status_t MultiAudioAddOn::InitCheck(
|
status_t
|
||||||
const char ** out_failure_text)
|
MultiAudioAddOn::InitCheck(const char** _failureText)
|
||||||
{
|
{
|
||||||
CALLED();
|
CALLED();
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32 MultiAudioAddOn::CountFlavors()
|
|
||||||
|
int32
|
||||||
|
MultiAudioAddOn::CountFlavors()
|
||||||
{
|
{
|
||||||
CALLED();
|
CALLED();
|
||||||
return fDevices.CountItems();
|
return fDevices.CountItems();
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t MultiAudioAddOn::GetFlavorAt(
|
|
||||||
int32 n,
|
status_t
|
||||||
const flavor_info ** out_info)
|
MultiAudioAddOn::GetFlavorAt(int32 n, const flavor_info** _info)
|
||||||
{
|
{
|
||||||
CALLED();
|
CALLED();
|
||||||
if (out_info == 0) {
|
if (_info == NULL)
|
||||||
fprintf(stderr, "<- B_BAD_VALUE\n");
|
return B_BAD_VALUE;
|
||||||
return B_BAD_VALUE; // we refuse to crash because you were stupid
|
|
||||||
}
|
MultiAudioDevice* device = (MultiAudioDevice*)fDevices.ItemAt(n);
|
||||||
if (n < 0 || n > fDevices.CountItems() - 1) {
|
if (device == NULL)
|
||||||
fprintf(stderr, "<- B_BAD_INDEX\n");
|
|
||||||
return B_BAD_INDEX;
|
return B_BAD_INDEX;
|
||||||
}
|
|
||||||
|
|
||||||
MultiAudioDevice *device = (MultiAudioDevice *) fDevices.ItemAt(n);
|
flavor_info* info = new (std::nothrow) flavor_info;
|
||||||
|
if (info == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
flavor_info * infos = new flavor_info[1];
|
MultiAudioNode::GetFlavor(info, n);
|
||||||
MultiAudioNode::GetFlavor(&infos[0], n);
|
info->name = (char*)device->Description().friendly_name;
|
||||||
infos[0].name = device->MD.friendly_name;
|
|
||||||
(*out_info) = infos;
|
*_info = info;
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
BMediaNode * MultiAudioAddOn::InstantiateNodeFor(
|
|
||||||
const flavor_info * info,
|
BMediaNode*
|
||||||
BMessage * config,
|
MultiAudioAddOn::InstantiateNodeFor(const flavor_info* info, BMessage* config,
|
||||||
status_t * out_error)
|
status_t* _error)
|
||||||
{
|
{
|
||||||
CALLED();
|
CALLED();
|
||||||
if (out_error == 0) {
|
if (_error == NULL)
|
||||||
fprintf(stderr, "<- NULL\n");
|
return NULL;
|
||||||
return 0; // we refuse to crash because you were stupid
|
|
||||||
}
|
|
||||||
|
|
||||||
MultiAudioDevice *device = (MultiAudioDevice*)fDevices.ItemAt(info->internal_id);
|
MultiAudioDevice* device = (MultiAudioDevice*)fDevices.ItemAt(
|
||||||
|
info->internal_id);
|
||||||
if (device == NULL) {
|
if (device == NULL) {
|
||||||
*out_error = B_ERROR;
|
*_error = B_ERROR;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MULTI_SAVE
|
#ifdef MULTI_SAVE
|
||||||
if (fSettings.FindMessage(device->MD.friendly_name, config) == B_OK) {
|
if (fSettings.FindMessage(device->Description().friendly_name, config)
|
||||||
fSettings.RemoveData(device->MD.friendly_name);
|
== B_OK) {
|
||||||
|
fSettings.RemoveData(device->Description().friendly_name);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
MultiAudioNode * node =
|
MultiAudioNode* node = new (std::nothrow) MultiAudioNode(this,
|
||||||
new MultiAudioNode(this,
|
device->Description().friendly_name, device, info->internal_id, config);
|
||||||
device->MD.friendly_name,
|
if (node == NULL)
|
||||||
device,
|
*_error = B_NO_MEMORY;
|
||||||
info->internal_id,
|
else
|
||||||
config);
|
*_error = node->InitCheck();
|
||||||
if (node == 0) {
|
|
||||||
*out_error = B_NO_MEMORY;
|
|
||||||
fprintf(stderr, "<- B_NO_MEMORY\n");
|
|
||||||
} else {
|
|
||||||
*out_error = node->InitCheck();
|
|
||||||
}
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
MultiAudioAddOn::GetConfigurationFor(BMediaNode * your_node, BMessage * into_message)
|
MultiAudioAddOn::GetConfigurationFor(BMediaNode * your_node, BMessage * into_message)
|
||||||
{
|
{
|
||||||
@@ -172,47 +174,48 @@ MultiAudioAddOn::GetConfigurationFor(BMediaNode * your_node, BMessage * into_mes
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool MultiAudioAddOn::WantsAutoStart()
|
bool
|
||||||
|
MultiAudioAddOn::WantsAutoStart()
|
||||||
{
|
{
|
||||||
CALLED();
|
CALLED();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t MultiAudioAddOn::AutoStart(
|
|
||||||
int in_count,
|
status_t
|
||||||
BMediaNode ** out_node,
|
MultiAudioAddOn::AutoStart(int count, BMediaNode** _node, int32* _internalID,
|
||||||
int32 * out_internal_id,
|
bool* _hasMore)
|
||||||
bool * out_has_more)
|
|
||||||
{
|
{
|
||||||
CALLED();
|
CALLED();
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
MultiAudioAddOn::RecursiveScan(char* rootPath, BEntry *rootEntry)
|
MultiAudioAddOn::RecursiveScan(char* rootPath, BEntry* rootEntry)
|
||||||
{
|
{
|
||||||
CALLED();
|
CALLED();
|
||||||
|
|
||||||
BDirectory root;
|
BDirectory root;
|
||||||
if (rootEntry != NULL)
|
if (rootEntry != NULL)
|
||||||
root.SetTo(rootEntry);
|
root.SetTo(rootEntry);
|
||||||
else if (rootPath != NULL) {
|
else if (rootPath != NULL)
|
||||||
root.SetTo(rootPath);
|
root.SetTo(rootPath);
|
||||||
} else {
|
else {
|
||||||
PRINT(("Error in MultiAudioAddOn::RecursiveScan null params\n"));
|
PRINT(("Error in MultiAudioAddOn::RecursiveScan() null params\n"));
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
BEntry entry;
|
BEntry entry;
|
||||||
|
|
||||||
while (root.GetNextEntry(&entry) > B_ERROR) {
|
while (root.GetNextEntry(&entry) > B_ERROR) {
|
||||||
|
|
||||||
if (entry.IsDirectory()) {
|
if (entry.IsDirectory()) {
|
||||||
RecursiveScan(rootPath, &entry);
|
RecursiveScan(rootPath, &entry);
|
||||||
} else {
|
} else {
|
||||||
BPath path;
|
BPath path;
|
||||||
entry.GetPath(&path);
|
entry.GetPath(&path);
|
||||||
MultiAudioDevice *device = new MultiAudioDevice(path.Path() + strlen(rootPath), path.Path());
|
MultiAudioDevice *device = new MultiAudioDevice(path.Path()
|
||||||
|
+ strlen(rootPath), path.Path());
|
||||||
if (device) {
|
if (device) {
|
||||||
if (device->InitCheck() == B_OK)
|
if (device->InitCheck() == B_OK)
|
||||||
fDevices.AddItem(device);
|
fDevices.AddItem(device);
|
||||||
@@ -227,7 +230,7 @@ MultiAudioAddOn::RecursiveScan(char* rootPath, BEntry *rootEntry)
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
MultiAudioAddOn::SaveSettings(void)
|
MultiAudioAddOn::SaveSettings()
|
||||||
{
|
{
|
||||||
CALLED();
|
CALLED();
|
||||||
BPath path;
|
BPath path;
|
||||||
@@ -241,7 +244,7 @@ MultiAudioAddOn::SaveSettings(void)
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
MultiAudioAddOn::LoadSettings(void)
|
MultiAudioAddOn::LoadSettings()
|
||||||
{
|
{
|
||||||
CALLED();
|
CALLED();
|
||||||
fSettings.MakeEmpty();
|
fSettings.MakeEmpty();
|
||||||
|
|||||||
@@ -3,343 +3,232 @@
|
|||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "MultiAudioDevice.h"
|
#include "MultiAudioDevice.h"
|
||||||
#include "debug.h"
|
|
||||||
#include "driver_io.h"
|
|
||||||
#include <MediaDefs.h>
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
float SAMPLE_RATES[] = {
|
#include <MediaDefs.h>
|
||||||
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
|
#include "debug.h"
|
||||||
};
|
#include "MultiAudioUtility.h"
|
||||||
|
|
||||||
|
|
||||||
float MultiAudioDevice::convert_multiaudio_rate_to_media_rate(uint32 rate)
|
using namespace MultiAudio;
|
||||||
|
|
||||||
|
|
||||||
|
MultiAudioDevice::MultiAudioDevice(const char* name, const char* path)
|
||||||
{
|
{
|
||||||
uint8 count = 0;
|
CALLED();
|
||||||
uint8 size = sizeof(SAMPLE_RATES) / sizeof(SAMPLE_RATES[0]);
|
|
||||||
while (count < size) {
|
strlcpy(fPath, path, B_PATH_NAME_LENGTH);
|
||||||
if (rate & 1)
|
PRINT(("name: %s, path: %s\n", name, fPath));
|
||||||
return SAMPLE_RATES[count];
|
|
||||||
count++;
|
fInitStatus = _InitDriver();
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int16 MultiAudioDevice::convert_multiaudio_format_to_valid_bits(uint32 fmt)
|
|
||||||
{
|
|
||||||
switch (fmt) {
|
|
||||||
case B_FMT_18BIT:
|
|
||||||
return 18;
|
|
||||||
case B_FMT_20BIT:
|
|
||||||
return 20;
|
|
||||||
case B_FMT_24BIT:
|
|
||||||
return 24;
|
|
||||||
case B_FMT_32BIT:
|
|
||||||
return 32;
|
|
||||||
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()
|
MultiAudioDevice::~MultiAudioDevice()
|
||||||
{
|
{
|
||||||
CALLED();
|
CALLED();
|
||||||
if (fd != 0) {
|
if (fDevice >= 0)
|
||||||
close(fd);
|
close(fDevice);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
status_t
|
||||||
|
MultiAudioDevice::InitCheck() const
|
||||||
{
|
{
|
||||||
CALLED();
|
CALLED();
|
||||||
return fInitCheckStatus;
|
return fInitStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t MultiAudioDevice::InitDriver()
|
status_t
|
||||||
|
MultiAudioDevice::_InitDriver()
|
||||||
{
|
{
|
||||||
multi_channel_enable MCE;
|
int num_outputs, num_inputs, num_channels;
|
||||||
uint32 mce_enable_bits;
|
|
||||||
int rval, i, num_outputs, num_inputs, num_channels;
|
|
||||||
|
|
||||||
CALLED();
|
CALLED();
|
||||||
|
|
||||||
//open the device driver for output
|
// open the device driver
|
||||||
fd = open(fDevice_path, O_WRONLY);
|
|
||||||
|
|
||||||
if (fd == -1) {
|
fDevice = open(fPath, O_WRONLY);
|
||||||
fprintf(stderr, "Failed to open %s: %s\n", fDevice_path, strerror(errno));
|
if (fDevice == -1) {
|
||||||
|
fprintf(stderr, "Failed to open %s: %s\n", fPath, strerror(errno));
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// Get description
|
// Get description
|
||||||
//
|
|
||||||
MD.info_size = sizeof(MD);
|
fDescription.info_size = sizeof(fDescription);
|
||||||
MD.request_channel_count = MAX_CHANNELS;
|
fDescription.request_channel_count = MAX_CHANNELS;
|
||||||
MD.channels = MCI;
|
fDescription.channels = fChannelInfo;
|
||||||
rval = DRIVER_GET_DESCRIPTION(&MD, 0);
|
status_t status = get_description(fDevice, &fDescription);
|
||||||
if (B_OK != rval)
|
if (status != B_OK) {
|
||||||
{
|
fprintf(stderr, "Failed on B_MULTI_GET_DESCRIPTION: %s\n",
|
||||||
fprintf(stderr, "Failed on B_MULTI_GET_DESCRIPTION\n");
|
strerror(status));
|
||||||
return B_ERROR;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
PRINT(("Friendly name:\t%s\nVendor:\t\t%s\n",
|
PRINT(("Friendly name:\t%s\nVendor:\t\t%s\n",
|
||||||
MD.friendly_name, MD.vendor_info));
|
fDescription.friendly_name, fDescription.vendor_info));
|
||||||
PRINT(("%ld outputs\t%ld inputs\n%ld out busses\t%ld in busses\n",
|
PRINT(("%ld outputs\t%ld inputs\n%ld out busses\t%ld in busses\n",
|
||||||
MD.output_channel_count, MD.input_channel_count,
|
fDescription.output_channel_count, fDescription.input_channel_count,
|
||||||
MD.output_bus_channel_count, MD.input_bus_channel_count));
|
fDescription.output_bus_channel_count,
|
||||||
|
fDescription.input_bus_channel_count));
|
||||||
PRINT(("\nChannels\n"
|
PRINT(("\nChannels\n"
|
||||||
"ID\tKind\tDesig\tConnectors\n"));
|
"ID\tKind\tDesig\tConnectors\n"));
|
||||||
|
|
||||||
for (i = 0 ; i < (MD.output_channel_count + MD.input_channel_count); i++)
|
for (int32 i = 0; i < fDescription.output_channel_count
|
||||||
{
|
+ fDescription.input_channel_count; i++) {
|
||||||
PRINT(("%ld\t%d\t0x%lx\t0x%lx\n", MD.channels[i].channel_id,
|
PRINT(("%ld\t%d\t0x%lx\t0x%lx\n", fDescription.channels[i].channel_id,
|
||||||
MD.channels[i].kind,
|
fDescription.channels[i].kind,
|
||||||
MD.channels[i].designations,
|
fDescription.channels[i].designations,
|
||||||
MD.channels[i].connectors));
|
fDescription.channels[i].connectors));
|
||||||
}
|
}
|
||||||
PRINT(("\n"));
|
PRINT(("\n"));
|
||||||
|
|
||||||
PRINT(("Output rates\t\t0x%lx\n", MD.output_rates));
|
PRINT(("Output rates\t\t0x%lx\n", fDescription.output_rates));
|
||||||
PRINT(("Input rates\t\t0x%lx\n", MD.input_rates));
|
PRINT(("Input rates\t\t0x%lx\n", fDescription.input_rates));
|
||||||
PRINT(("Max CVSR\t\t%.0f\n", MD.max_cvsr_rate));
|
PRINT(("Max CVSR\t\t%.0f\n", fDescription.max_cvsr_rate));
|
||||||
PRINT(("Min CVSR\t\t%.0f\n", MD.min_cvsr_rate));
|
PRINT(("Min CVSR\t\t%.0f\n", fDescription.min_cvsr_rate));
|
||||||
PRINT(("Output formats\t\t0x%lx\n", MD.output_formats));
|
PRINT(("Output formats\t\t0x%lx\n", fDescription.output_formats));
|
||||||
PRINT(("Input formats\t\t0x%lx\n", MD.input_formats));
|
PRINT(("Input formats\t\t0x%lx\n", fDescription.input_formats));
|
||||||
PRINT(("Lock sources\t\t0x%lx\n", MD.lock_sources));
|
PRINT(("Lock sources\t\t0x%lx\n", fDescription.lock_sources));
|
||||||
PRINT(("Timecode sources\t0x%lx\n", MD.timecode_sources));
|
PRINT(("Timecode sources\t0x%lx\n", fDescription.timecode_sources));
|
||||||
PRINT(("Interface flags\t\t0x%lx\n", MD.interface_flags));
|
PRINT(("Interface flags\t\t0x%lx\n", fDescription.interface_flags));
|
||||||
PRINT(("Control panel string:\t\t%s\n", MD.control_panel));
|
PRINT(("Control panel string:\t\t%s\n", fDescription.control_panel));
|
||||||
PRINT(("\n"));
|
PRINT(("\n"));
|
||||||
|
|
||||||
num_outputs = MD.output_channel_count;
|
num_outputs = fDescription.output_channel_count;
|
||||||
num_inputs = MD.input_channel_count;
|
num_inputs = fDescription.input_channel_count;
|
||||||
num_channels = num_outputs + num_inputs;
|
num_channels = num_outputs + num_inputs;
|
||||||
|
|
||||||
// Get and set enabled channels
|
// Get and set enabled channels
|
||||||
MCE.info_size = sizeof(MCE);
|
|
||||||
MCE.enable_bits = (uchar *) & mce_enable_bits;
|
multi_channel_enable enable;
|
||||||
rval = DRIVER_GET_ENABLED_CHANNELS(&MCE, sizeof(MCE));
|
uint32 enableBits;
|
||||||
if (B_OK != rval)
|
enable.info_size = sizeof(enable);
|
||||||
{
|
enable.enable_bits = (uchar*)&enableBits;
|
||||||
fprintf(stderr, "Failed on B_MULTI_GET_ENABLED_CHANNELS len is 0x%lx\n", sizeof(MCE));
|
|
||||||
return B_ERROR;
|
status = get_enabled_channels(fDevice, &enable);
|
||||||
|
if (status != B_OK) {
|
||||||
|
fprintf(stderr, "Failed on B_MULTI_GET_ENABLED_CHANNELS: %s\n",
|
||||||
|
strerror(status));
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
mce_enable_bits = (1 << num_channels) - 1;
|
enableBits = (1 << num_channels) - 1;
|
||||||
MCE.lock_source = B_MULTI_LOCK_INTERNAL;
|
enable.lock_source = B_MULTI_LOCK_INTERNAL;
|
||||||
rval = DRIVER_SET_ENABLED_CHANNELS(&MCE, 0);
|
|
||||||
if (B_OK != rval)
|
status = set_enabled_channels(fDevice, &enable);
|
||||||
{
|
if (status != B_OK) {
|
||||||
fprintf(stderr, "Failed on B_MULTI_SET_ENABLED_CHANNELS 0x%p 0x%x\n", MCE.enable_bits, *(MCE.enable_bits));
|
fprintf(stderr, "Failed on B_MULTI_SET_ENABLED_CHANNELS 0x%x: %s\n",
|
||||||
return B_ERROR;
|
*enable.enable_bits, strerror(status));
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// Set the sample rate
|
// Set the sample rate
|
||||||
//
|
|
||||||
MFI.info_size = sizeof(MFI);
|
fFormatInfo.info_size = sizeof(multi_format_info);
|
||||||
MFI.output.rate = select_multiaudio_rate(MD.output_rates);
|
fFormatInfo.output.rate = select_sample_rate(fDescription.output_rates);
|
||||||
MFI.output.cvsr = 0;
|
fFormatInfo.output.cvsr = 0;
|
||||||
MFI.output.format = select_multiaudio_format(MD.output_formats);
|
fFormatInfo.output.format = select_format(fDescription.output_formats);
|
||||||
MFI.input.rate = MFI.output.rate;
|
fFormatInfo.input.rate = select_sample_rate(fDescription.input_rates);
|
||||||
MFI.input.cvsr = MFI.output.cvsr;
|
fFormatInfo.input.cvsr = fFormatInfo.output.cvsr;
|
||||||
MFI.input.format = MFI.output.format;
|
fFormatInfo.input.format = select_format(fDescription.input_formats);
|
||||||
rval = DRIVER_SET_GLOBAL_FORMAT(&MFI, 0);
|
|
||||||
if (B_OK != rval)
|
status = set_global_format(fDevice, &fFormatInfo);
|
||||||
{
|
if (status != B_OK) {
|
||||||
fprintf(stderr, "Failed on B_MULTI_SET_GLOBAL_FORMAT\n");
|
fprintf(stderr, "Failed on B_MULTI_SET_GLOBAL_FORMAT: %s\n",
|
||||||
return B_ERROR;
|
strerror(status));
|
||||||
|
#if 0
|
||||||
|
}
|
||||||
|
|
||||||
|
status = get_global_format(fDevice, &fFormatInfo);
|
||||||
|
if (status != B_OK) {
|
||||||
|
fprintf(stderr, "Failed on B_MULTI_GET_GLOBAL_FORMAT: %s\n",
|
||||||
|
strerror(status));
|
||||||
|
#endif
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// Get the buffers
|
// Get the buffers
|
||||||
//
|
|
||||||
for (i = 0; i < NB_BUFFERS; i++) {
|
for (uint32 i = 0; i < MAX_BUFFERS; i++) {
|
||||||
play_buffer_desc[i] = &play_buffer_list[i * MAX_CHANNELS];
|
fPlayBuffers[i] = &fPlayBufferList[i * MAX_CHANNELS];
|
||||||
record_buffer_desc[i] = &record_buffer_list[i * MAX_CHANNELS];
|
fRecordBuffers[i] = &fRecordBufferList[i * MAX_CHANNELS];
|
||||||
}
|
}
|
||||||
MBL.info_size = sizeof(MBL);
|
fBufferList.info_size = sizeof(multi_buffer_list);
|
||||||
MBL.request_playback_buffer_size = 0; //use the default......
|
fBufferList.request_playback_buffer_size = 0;
|
||||||
MBL.request_playback_buffers = NB_BUFFERS;
|
// use the default...
|
||||||
MBL.request_playback_channels = num_outputs;
|
fBufferList.request_playback_buffers = MAX_BUFFERS;
|
||||||
MBL.playback_buffers = (buffer_desc **) play_buffer_desc;
|
fBufferList.request_playback_channels = num_outputs;
|
||||||
MBL.request_record_buffer_size = 0; //use the default......
|
fBufferList.playback_buffers = (buffer_desc **) fPlayBuffers;
|
||||||
MBL.request_record_buffers = NB_BUFFERS;
|
fBufferList.request_record_buffer_size = 0;
|
||||||
MBL.request_record_channels = num_inputs;
|
// use the default...
|
||||||
MBL.record_buffers = (buffer_desc **) record_buffer_desc;
|
fBufferList.request_record_buffers = MAX_BUFFERS;
|
||||||
|
fBufferList.request_record_channels = num_inputs;
|
||||||
|
fBufferList.record_buffers = /*(buffer_desc **)*/ fRecordBuffers;
|
||||||
|
|
||||||
rval = DRIVER_GET_BUFFERS(&MBL, 0);
|
status = get_buffers(fDevice, &fBufferList);
|
||||||
|
if (status != B_OK) {
|
||||||
if (B_OK != rval)
|
fprintf(stderr, "Failed on B_MULTI_GET_BUFFERS: %s\n",
|
||||||
{
|
strerror(status));
|
||||||
fprintf(stderr, "Failed on B_MULTI_GET_BUFFERS\n");
|
return status;
|
||||||
return B_ERROR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < MBL.return_playback_buffers; i++)
|
for (int32 i = 0; i < fBufferList.return_playback_buffers; i++) {
|
||||||
for (int j = 0; j < MBL.return_playback_channels; j++) {
|
for (int32 j = 0; j < fBufferList.return_playback_channels; j++) {
|
||||||
PRINT(("MBL.playback_buffers[%d][%d].base: %p\n",
|
PRINT(("fBufferList.playback_buffers[%d][%d].base: %p\n",
|
||||||
i, j, MBL.playback_buffers[i][j].base));
|
i, j, fBufferList.playback_buffers[i][j].base));
|
||||||
PRINT(("MBL.playback_buffers[%d][%d].stride: %i\n",
|
PRINT(("fBufferList.playback_buffers[%d][%d].stride: %i\n",
|
||||||
i, j, MBL.playback_buffers[i][j].stride));
|
i, j, fBufferList.playback_buffers[i][j].stride));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < MBL.return_record_buffers; i++)
|
for (int32 i = 0; i < fBufferList.return_record_buffers; i++) {
|
||||||
for (int j = 0; j < MBL.return_record_channels; j++) {
|
for (int32 j = 0; j < fBufferList.return_record_channels; j++) {
|
||||||
PRINT(("MBL.record_buffers[%d][%d].base: %p\n",
|
PRINT(("fBufferList.record_buffers[%d][%d].base: %p\n",
|
||||||
i, j, MBL.record_buffers[i][j].base));
|
i, j, fBufferList.record_buffers[i][j].base));
|
||||||
PRINT(("MBL.record_buffers[%d][%d].stride: %i\n",
|
PRINT(("fBufferList.record_buffers[%d][%d].stride: %i\n",
|
||||||
i, j, MBL.record_buffers[i][j].stride));
|
i, j, fBufferList.record_buffers[i][j].stride));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MMCI.info_size = sizeof(MMCI);
|
fMixControlInfo.info_size = sizeof(fMixControlInfo);
|
||||||
MMCI.control_count = MAX_CONTROLS;
|
fMixControlInfo.control_count = MAX_CONTROLS;
|
||||||
MMCI.controls = MMC;
|
fMixControlInfo.controls = fMixControl;
|
||||||
|
|
||||||
rval = DRIVER_LIST_MIX_CONTROLS(&MMCI, 0);
|
status = list_mix_controls(fDevice, &fMixControlInfo);
|
||||||
|
if (status != B_OK) {
|
||||||
if (B_OK != rval)
|
fprintf(stderr, "Failed on DRIVER_LIST_MIX_CONTROLS: %s\n",
|
||||||
{
|
strerror(status));
|
||||||
fprintf(stderr, "Failed on DRIVER_LIST_MIX_CONTROLS\n");
|
return status;
|
||||||
return B_ERROR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
MultiAudioDevice::DoBufferExchange(multi_buffer_info *MBI)
|
status_t
|
||||||
|
MultiAudioDevice::DoBufferExchange(multi_buffer_info *info)
|
||||||
{
|
{
|
||||||
return DRIVER_BUFFER_EXCHANGE(MBI, 0);
|
return buffer_exchange(fDevice, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
MultiAudioDevice::DoSetMix(multi_mix_value_info *MMVI)
|
status_t
|
||||||
|
MultiAudioDevice::DoSetMix(multi_mix_value_info *info)
|
||||||
{
|
{
|
||||||
return DRIVER_SET_MIX(MMVI, 0);
|
return set_mix(fDevice, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
MultiAudioDevice::DoGetMix(multi_mix_value_info *MMVI)
|
status_t
|
||||||
|
MultiAudioDevice::DoGetMix(multi_mix_value_info *info)
|
||||||
{
|
{
|
||||||
return DRIVER_GET_MIX(MMVI, 0);
|
return get_mix(fDevice, info);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,59 +2,54 @@
|
|||||||
* Copyright (c) 2002-2007, Jerome Duval ([email protected])
|
* Copyright (c) 2002-2007, Jerome Duval ([email protected])
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
#ifndef MULTI_AUDIO_DEVICE_H
|
||||||
|
#define MULTI_AUDIO_DEVICE_H
|
||||||
|
|
||||||
#ifndef _MULTIAUDIODEVICE_H
|
|
||||||
#define _MULTIAUDIODEVICE_H
|
|
||||||
|
|
||||||
#include "hmulti_audio.h"
|
#include "hmulti_audio.h"
|
||||||
|
|
||||||
|
|
||||||
#define MAX_CONTROLS 128
|
#define MAX_CONTROLS 128
|
||||||
#define MAX_CHANNELS 32
|
#define MAX_CHANNELS 32
|
||||||
#define NB_BUFFERS 32
|
#define MAX_BUFFERS 32
|
||||||
|
|
||||||
class MultiAudioDevice
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit MultiAudioDevice(const char *name, const char* path);
|
|
||||||
virtual ~MultiAudioDevice(void);
|
|
||||||
|
|
||||||
virtual status_t InitCheck(void) const;
|
class MultiAudioDevice {
|
||||||
|
public:
|
||||||
|
MultiAudioDevice(const char* name, const char* path);
|
||||||
|
~MultiAudioDevice();
|
||||||
|
|
||||||
static float convert_multiaudio_rate_to_media_rate(uint32 rate);
|
status_t InitCheck() const;
|
||||||
static uint32 convert_media_rate_to_multiaudio_rate(float rate);
|
|
||||||
static uint32 convert_multiaudio_format_to_media_format(uint32 fmt);
|
|
||||||
static int16 convert_multiaudio_format_to_valid_bits(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);
|
const multi_description& Description() const { return fDescription; }
|
||||||
int DoSetMix(multi_mix_value_info *MMVI);
|
const multi_format_info& FormatInfo() const { return fFormatInfo; }
|
||||||
int DoGetMix(multi_mix_value_info *MMVI);
|
const multi_buffer_list& BufferList() const { return fBufferList; }
|
||||||
|
const multi_mix_control_info& MixControlInfo() const
|
||||||
|
{ return fMixControlInfo; }
|
||||||
|
|
||||||
private:
|
status_t DoBufferExchange(multi_buffer_info* bufferInfo);
|
||||||
status_t InitDriver();
|
status_t DoSetMix(multi_mix_value_info* mixValueInfo);
|
||||||
|
status_t DoGetMix(multi_mix_value_info* mixValueInfo);
|
||||||
|
|
||||||
int fd; //file descriptor for hw driver
|
private:
|
||||||
char fDevice_name[32];
|
status_t _InitDriver();
|
||||||
char fDevice_path[32];
|
|
||||||
|
|
||||||
public:
|
status_t fInitStatus;
|
||||||
multi_description MD;
|
int fDevice;
|
||||||
multi_channel_info MCI[MAX_CHANNELS];
|
char fPath[B_PATH_NAME_LENGTH];
|
||||||
multi_format_info MFI;
|
|
||||||
multi_buffer_list MBL;
|
|
||||||
|
|
||||||
multi_mix_control_info MMCI;
|
multi_description fDescription;
|
||||||
multi_mix_control MMC[MAX_CONTROLS];
|
multi_channel_info fChannelInfo[MAX_CHANNELS];
|
||||||
|
multi_format_info fFormatInfo;
|
||||||
|
multi_buffer_list fBufferList;
|
||||||
|
|
||||||
buffer_desc play_buffer_list[NB_BUFFERS * MAX_CHANNELS];
|
multi_mix_control_info fMixControlInfo;
|
||||||
buffer_desc record_buffer_list[NB_BUFFERS * MAX_CHANNELS];
|
multi_mix_control fMixControl[MAX_CONTROLS];
|
||||||
buffer_desc *play_buffer_desc[NB_BUFFERS];
|
|
||||||
buffer_desc *record_buffer_desc[NB_BUFFERS];
|
|
||||||
|
|
||||||
private:
|
buffer_desc fPlayBufferList[MAX_BUFFERS * MAX_CHANNELS];
|
||||||
status_t fInitCheckStatus;
|
buffer_desc fRecordBufferList[MAX_BUFFERS * MAX_CHANNELS];
|
||||||
|
buffer_desc* fPlayBuffers[MAX_BUFFERS];
|
||||||
|
buffer_desc* fRecordBuffers[MAX_BUFFERS];
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif // MULTI_AUDIO_DEVICE_H
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -27,8 +27,7 @@
|
|||||||
const media_format & consumer_format);*/
|
const media_format & consumer_format);*/
|
||||||
|
|
||||||
|
|
||||||
class node_input
|
class node_input {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
node_input(media_input &input, media_format format);
|
node_input(media_input &input, media_format format);
|
||||||
~node_input();
|
~node_input();
|
||||||
@@ -42,8 +41,7 @@ class node_input
|
|||||||
BBuffer *fBuffer;
|
BBuffer *fBuffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
class node_output
|
class node_output {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
node_output(media_output &output, media_format format);
|
node_output(media_output &output, media_format format);
|
||||||
~node_output();
|
~node_output();
|
||||||
@@ -60,47 +58,38 @@ class node_output
|
|||||||
multi_buffer_info fOldMBI;
|
multi_buffer_info fOldMBI;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MultiAudioNode :
|
class MultiAudioNode : public BBufferConsumer, public BBufferProducer,
|
||||||
public BBufferConsumer,
|
public BTimeSource, public BMediaEventLooper, public BControllable {
|
||||||
public BBufferProducer,
|
protected:
|
||||||
public BTimeSource,
|
virtual ~MultiAudioNode(void);
|
||||||
public BMediaEventLooper,
|
|
||||||
public BControllable
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
virtual ~MultiAudioNode(void);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
explicit MultiAudioNode(BMediaAddOn* addon, const char* name,
|
||||||
|
MultiAudioDevice* device, int32 internalID, BMessage* config);
|
||||||
|
|
||||||
explicit MultiAudioNode(BMediaAddOn *addon, char* name, MultiAudioDevice *device,
|
virtual status_t InitCheck(void) const;
|
||||||
int32 internal_id, BMessage * config);
|
|
||||||
|
|
||||||
virtual status_t InitCheck(void) const;
|
|
||||||
|
|
||||||
/*************************/
|
/*************************/
|
||||||
/* begin from BMediaNode */
|
/* begin from BMediaNode */
|
||||||
public:
|
public:
|
||||||
virtual BMediaAddOn* AddOn(
|
virtual BMediaAddOn* AddOn(int32* internalID) const;
|
||||||
int32 * internal_id) const; /* Who instantiated you -- or NULL for app class */
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/* These don't return errors; instead, they use the global error condition reporter. */
|
/* 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) */
|
/* 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. */
|
/* 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 */
|
/* Allowing an arbitrary number of outstanding commands might be nice, but apps */
|
||||||
/* cannot depend on that happening. */
|
/* cannot depend on that happening. */
|
||||||
virtual void Preroll(void);
|
virtual void Preroll(void);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual status_t HandleMessage(
|
virtual status_t HandleMessage(int32 message, const void* data,
|
||||||
int32 message,
|
size_t size);
|
||||||
const void * data,
|
|
||||||
size_t size);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void NodeRegistered(void); /* reserved 2 */
|
virtual void NodeRegistered();
|
||||||
virtual status_t RequestCompleted(const media_request_info &info);
|
virtual status_t RequestCompleted(const media_request_info &info);
|
||||||
virtual void SetTimeSource(BTimeSource *timeSource);
|
virtual void SetTimeSource(BTimeSource *timeSource);
|
||||||
|
|
||||||
/* end from BMediaNode */
|
/* end from BMediaNode */
|
||||||
/***********************/
|
/***********************/
|
||||||
@@ -108,61 +97,28 @@ class MultiAudioNode :
|
|||||||
/******************************/
|
/******************************/
|
||||||
/* begin from BBufferConsumer */
|
/* begin from BBufferConsumer */
|
||||||
|
|
||||||
//included from BMediaAddOn
|
virtual status_t AcceptFormat(const media_destination& dest,
|
||||||
//virtual status_t HandleMessage(
|
media_format* format);
|
||||||
// int32 message,
|
virtual status_t GetNextInput(int32* cookie, media_input* input);
|
||||||
// const void * data,
|
virtual void DisposeInputCookie(int32 cookie);
|
||||||
// size_t size);
|
virtual void BufferReceived(BBuffer* buffer);
|
||||||
|
virtual void ProducerDataStatus(const media_destination& forWhom,
|
||||||
|
int32 status, bigtime_t atPerformanceTime);
|
||||||
|
virtual status_t GetLatencyFor(const media_destination& forWhom,
|
||||||
|
bigtime_t* latency, media_node_id* timeSource);
|
||||||
|
virtual status_t Connected(const media_source& producer,
|
||||||
|
const media_destination& where,
|
||||||
|
const media_format& withFormat, media_input* input);
|
||||||
|
virtual void Disconnected(const media_source& producer,
|
||||||
|
const media_destination& where);
|
||||||
|
virtual status_t FormatChanged(const media_source& producer,
|
||||||
|
const media_destination& consumer, int32 changeTag,
|
||||||
|
const media_format& format);
|
||||||
|
|
||||||
/* Someone, probably the producer, is asking you about this format. Give */
|
virtual status_t SeekTagRequested(const media_destination& destination,
|
||||||
/* your honest opinion, possibly modifying *format. Do not ask upstream */
|
bigtime_t targetTime, uint32 flags,
|
||||||
/* producer about the format, since he's synchronously waiting for your */
|
media_seek_tag* _seekTag, bigtime_t* _taggedTime,
|
||||||
/* reply. */
|
uint32* _flags);
|
||||||
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 */
|
/* end from BBufferConsumer */
|
||||||
/****************************/
|
/****************************/
|
||||||
|
|||||||
@@ -0,0 +1,235 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2008, Axel Dörfler, [email protected].
|
||||||
|
* Copyright (c) 2002-2007, Jerome Duval ([email protected])
|
||||||
|
*
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "MultiAudioUtility.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <MediaDefs.h>
|
||||||
|
|
||||||
|
|
||||||
|
const float kSampleRates[] = {
|
||||||
|
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
|
||||||
|
};
|
||||||
|
const uint32 kSampleRateCount = sizeof(kSampleRates) / sizeof(kSampleRates[0]);
|
||||||
|
|
||||||
|
|
||||||
|
template<typename T> static status_t
|
||||||
|
call_driver(int device, int32 op, T* data)
|
||||||
|
{
|
||||||
|
if (ioctl(device, op, data, sizeof(T)) != 0)
|
||||||
|
return errno;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
namespace MultiAudio {
|
||||||
|
|
||||||
|
|
||||||
|
float
|
||||||
|
convert_to_sample_rate(uint32 rate)
|
||||||
|
{
|
||||||
|
for (uint32 i = 0; i < kSampleRateCount; i++) {
|
||||||
|
if (rate & 1)
|
||||||
|
return kSampleRates[i];
|
||||||
|
|
||||||
|
rate >>= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32
|
||||||
|
convert_from_sample_rate(float rate)
|
||||||
|
{
|
||||||
|
for (uint32 i = 0; i < kSampleRateCount; i++) {
|
||||||
|
if (rate <= kSampleRates[i])
|
||||||
|
return 1 << i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32
|
||||||
|
convert_to_media_format(uint32 format)
|
||||||
|
{
|
||||||
|
switch (format) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int16
|
||||||
|
convert_to_valid_bits(uint32 format)
|
||||||
|
{
|
||||||
|
switch (format) {
|
||||||
|
case B_FMT_18BIT:
|
||||||
|
return 18;
|
||||||
|
case B_FMT_20BIT:
|
||||||
|
return 20;
|
||||||
|
case B_FMT_24BIT:
|
||||||
|
return 24;
|
||||||
|
case B_FMT_32BIT:
|
||||||
|
return 32;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32
|
||||||
|
convert_from_media_format(uint32 format)
|
||||||
|
{
|
||||||
|
switch (format) {
|
||||||
|
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
|
||||||
|
select_sample_rate(uint32 rate)
|
||||||
|
{
|
||||||
|
// highest rate
|
||||||
|
uint32 crate = B_SR_1536000;
|
||||||
|
while (crate != 0) {
|
||||||
|
if (rate & crate)
|
||||||
|
return crate;
|
||||||
|
crate >>= 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32
|
||||||
|
select_format(uint32 format)
|
||||||
|
{
|
||||||
|
// best format
|
||||||
|
if (format & B_FMT_FLOAT)
|
||||||
|
return B_FMT_FLOAT;
|
||||||
|
if (format & B_FMT_32BIT)
|
||||||
|
return B_FMT_32BIT;
|
||||||
|
if (format & B_FMT_24BIT)
|
||||||
|
return B_FMT_24BIT;
|
||||||
|
if (format & B_FMT_20BIT)
|
||||||
|
return B_FMT_20BIT;
|
||||||
|
if (format & B_FMT_18BIT)
|
||||||
|
return B_FMT_18BIT;
|
||||||
|
if (format & B_FMT_16BIT)
|
||||||
|
return B_FMT_16BIT;
|
||||||
|
if (format & B_FMT_8BIT_S)
|
||||||
|
return B_FMT_8BIT_S;
|
||||||
|
if (format & B_FMT_8BIT_U)
|
||||||
|
return B_FMT_8BIT_U;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
get_description(int device, multi_description* description)
|
||||||
|
{
|
||||||
|
return call_driver(device, B_MULTI_GET_DESCRIPTION, description);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
get_enabled_channels(int device, multi_channel_enable* enable)
|
||||||
|
{
|
||||||
|
return call_driver(device, B_MULTI_GET_ENABLED_CHANNELS, enable);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
set_enabled_channels(int device, multi_channel_enable* enable)
|
||||||
|
{
|
||||||
|
return call_driver(device, B_MULTI_SET_ENABLED_CHANNELS, enable);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
get_global_format(int device, multi_format_info* info)
|
||||||
|
{
|
||||||
|
return call_driver(device, B_MULTI_GET_GLOBAL_FORMAT, info);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
set_global_format(int device, multi_format_info* info)
|
||||||
|
{
|
||||||
|
return call_driver(device, B_MULTI_SET_GLOBAL_FORMAT, info);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
get_buffers(int device, multi_buffer_list* list)
|
||||||
|
{
|
||||||
|
return call_driver(device, B_MULTI_GET_BUFFERS, list);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
buffer_exchange(int device, multi_buffer_info* info)
|
||||||
|
{
|
||||||
|
return call_driver(device, B_MULTI_BUFFER_EXCHANGE, info);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
list_mix_controls(int device, multi_mix_control_info* info)
|
||||||
|
{
|
||||||
|
return call_driver(device, B_MULTI_LIST_MIX_CONTROLS, info);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
get_mix(int device, multi_mix_value_info* info)
|
||||||
|
{
|
||||||
|
return call_driver(device, B_MULTI_GET_MIX, info);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
set_mix(int device, multi_mix_value_info* info)
|
||||||
|
{
|
||||||
|
return call_driver(device, B_MULTI_SET_MIX, info);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace MultiAudio
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2008, Axel Dörfler, [email protected].
|
||||||
|
* Copyright (c) 2002-2007, Jerome Duval ([email protected])
|
||||||
|
*
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef MULTI_AUDIO_UTILITY_H
|
||||||
|
#define MULTI_AUDIO_UTILITY_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "hmulti_audio.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace MultiAudio {
|
||||||
|
|
||||||
|
// sample rate & format conversion
|
||||||
|
float convert_to_sample_rate(uint32 rate);
|
||||||
|
uint32 convert_from_sample_rate(float rate);
|
||||||
|
uint32 convert_to_media_format(uint32 format);
|
||||||
|
int16 convert_to_valid_bits(uint32 format);
|
||||||
|
uint32 convert_from_media_format(uint32 format);
|
||||||
|
uint32 select_sample_rate(uint32 rate);
|
||||||
|
uint32 select_format(uint32 format);
|
||||||
|
|
||||||
|
// device driver interface
|
||||||
|
status_t get_description(int device, multi_description* description);
|
||||||
|
|
||||||
|
status_t get_enabled_channels(int device, multi_channel_enable* enable);
|
||||||
|
status_t set_enabled_channels(int device, multi_channel_enable* enable);
|
||||||
|
|
||||||
|
status_t get_global_format(int device, multi_format_info* info);
|
||||||
|
status_t set_global_format(int device, multi_format_info* info);
|
||||||
|
status_t get_buffers(int device, multi_buffer_list* list);
|
||||||
|
status_t buffer_exchange(int device, multi_buffer_info* info);
|
||||||
|
|
||||||
|
status_t list_mix_controls(int device, multi_mix_control_info* info);
|
||||||
|
status_t get_mix(int device, multi_mix_value_info* info);
|
||||||
|
status_t set_mix(int device, multi_mix_value_info* info);
|
||||||
|
|
||||||
|
} // namespace MultiAudio
|
||||||
|
|
||||||
|
#endif // MULTI_AUDIO_UTILITY_H
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
/*
|
|
||||||
* multiaudio replacement media addon for BeOS
|
|
||||||
*
|
|
||||||
* Copyright (c) 2002, Jerome Duval ([email protected])
|
|
||||||
* Distributed under the terms of the MIT License.
|
|
||||||
*/
|
|
||||||
#ifndef _DRIVER_IO_H
|
|
||||||
#define _DRIVER_IO_H
|
|
||||||
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <Drivers.h>
|
|
||||||
#include "hmulti_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
|
|
||||||
Reference in New Issue
Block a user