work in progress

changed name
initial mixer interface


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@12164 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Jérôme Duval 2005-03-30 18:58:43 +00:00
parent b85392f078
commit c900253170
4 changed files with 299 additions and 30 deletions

View File

@ -125,7 +125,7 @@ extern char * pStatusStrs[ECHOSTATUS_LAST];
status_t
echo_stream_set_audioparms(echo_stream *stream, uint8 channels,
uint8 bitsPerSample, uint32 sample_rate)
uint8 bitsPerSample, uint32 sample_rate, uint8 index)
{
int32 i;
uint8 sample_size, frame_size;
@ -145,7 +145,7 @@ echo_stream_set_audioparms(echo_stream *stream, uint8 channels,
}
open_params.bIsCyclic = TRUE;
open_params.Pipe.nPipe = 0;
open_params.Pipe.nPipe = index;
open_params.Pipe.bIsInput = stream->use == ECHO_USE_RECORD ? TRUE : FALSE;
open_params.Pipe.wInterleave = channels;
open_params.ProcessId = NULL;
@ -153,7 +153,7 @@ echo_stream_set_audioparms(echo_stream *stream, uint8 channels,
status = stream->card->pEG->OpenAudio(&open_params, &stream->pipe);
if(status!=ECHOSTATUS_OK) {
PRINT(("echo_stream_set_audioparms : OpenAudio failed\n"));
PRINT(("  status: %s \n", pStatusStrs[status]));
PRINT((" status: %s \n", pStatusStrs[status]));
return B_ERROR;
}
@ -161,7 +161,7 @@ echo_stream_set_audioparms(echo_stream *stream, uint8 channels,
status = stream->card->pEG->VerifyAudioOpen(stream->pipe);
if(status!=ECHOSTATUS_OK) {
PRINT(("echo_stream_set_audioparms : VerifyAudioOpen failed\n"));
PRINT(("  status: %s \n", pStatusStrs[status]));
PRINT((" status: %s \n", pStatusStrs[status]));
return B_ERROR;
}
@ -178,14 +178,14 @@ echo_stream_set_audioparms(echo_stream *stream, uint8 channels,
status = stream->card->pEG->QueryAudioFormat(stream->pipe, &format_params);
if(status!=ECHOSTATUS_OK) {
PRINT(("echo_stream_set_audioparms : bad format when querying\n"));
PRINT(("  status: %s \n", pStatusStrs[status]));
PRINT((" status: %s \n", pStatusStrs[status]));
return B_ERROR;
}
status = stream->card->pEG->SetAudioFormat(stream->pipe, &format_params);
if(status!=ECHOSTATUS_OK) {
PRINT(("echo_stream_set_audioparms : bad format when setting\n"));
PRINT(("  status: %s \n", pStatusStrs[status]));
PRINT((" status: %s \n", pStatusStrs[status]));
return B_ERROR;
}
@ -193,7 +193,7 @@ echo_stream_set_audioparms(echo_stream *stream, uint8 channels,
status = stream->card->pEG->QueryAudioSampleRate(sample_rate);
if(status!=ECHOSTATUS_OK) {
PRINT(("echo_stream_set_audioparms : bad sample rate when querying\n"));
PRINT(("  status: %s \n", pStatusStrs[status]));
PRINT((" status: %s \n", pStatusStrs[status]));
return B_ERROR;
}
@ -393,6 +393,18 @@ int32 echo_int(void *arg)
return B_INVOKE_SCHEDULER;
}
/* dumps card capabilities */
void
echo_dump_caps(echo_dev *card)
{
PECHOGALS_CAPS caps = &card->caps;
PRINT(("name: %s\n", caps->szName));
PRINT(("out pipes: %d, in pipes: %d, out busses: %d, in busses: %d, out midi: %d, in midi: %d\n",
caps->wNumPipesOut, caps->wNumPipesIn, caps->wNumBussesOut, caps->wNumBussesIn, caps->wNumMidiOut, caps->wNumMidiIn));
}
/* detect presence of our hardware */
status_t
init_hardware(void)
@ -532,6 +544,7 @@ echo_setup(echo_dev * card)
{
status_t err = B_OK;
unsigned char cmd;
char *name;
PRINT(("echo_setup(%p)\n", card));
@ -551,32 +564,41 @@ echo_setup(echo_dev * card)
#ifdef ECHOGALS_FAMILY
case DARLA:
card->pEG = new CDarla(card->pOSS);
name = "Echo Darla";
break;
case GINA:
card->pEG = new CGina(card->pOSS);
name = "Echo Gina";
break;
case LAYLA:
card->pEG = new CLayla(card->pOSS);
name = "Echo Layla";
break;
case DARLA24:
card->pEG = new CDarla24(card->pOSS);
name = "Echo Darla24";
break;
#endif
#ifdef ECHO24_FAMILY
case GINA24:
card->pEG = new CGina24(card->pOSS);
name = "Echo Gina24";
break;
case LAYLA24:
card->pEG = new CLayla24(card->pOSS);
name = "Echo Gina24";
break;
case MONA:
card->pEG = new CMona(card->pOSS);
name = "Echo Mona";
break;
case MIA:
card->pEG = new CMia(card->pOSS);
name = "Echo Mia";
break;
case ECHO3G:
card->pEG = new C3g(card->pOSS);
name = "Echo 3g";
break;
#endif
default:
@ -602,13 +624,15 @@ echo_setup(echo_dev * card)
cmd = (*pci->read_pci_config)(card->info.bus, card->info.device, card->info.function, PCI_command, 2);
PRINT(("PCI command after: %x\n", cmd));
card->pEG->AssignResources(card->log_bmbar, "no name");
card->pEG->AssignResources(card->log_bmbar, name);
ECHOSTATUS status;
status = card->pEG->InitHw();
if(status != ECHOSTATUS_OK)
return B_ERROR;
card->pEG->GetCapabilities(&card->caps);
/* Init streams list */
LIST_INIT(&(card->streams));
@ -620,13 +644,25 @@ echo_setup(echo_dev * card)
PRINT(("echo_setup done\n"));
echo_dump_caps(card);
status = card->pEG->OpenMixer(card->mixer);
if (status != ECHOSTATUS_OK)
return B_ERROR;
return err;
}
static void
echo_shutdown(echo_dev *card)
{
ECHOSTATUS status;
PRINT(("shutdown(%p)\n", card));
status = card->pEG->CloseMixer(card->mixer);
if (status != ECHOSTATUS_OK)
PRINT(("echo_shutdown: error when CloseMixer\n"));
remove_io_interrupt_handler(card->irq, echo_int, card);
delete card->pEG;

View File

@ -86,6 +86,8 @@ typedef struct _echo_dev {
uint16 type;
PCEchoGals pEG;
ECHOGALS_CAPS caps;
NUINT mixer;
PCOsSupport pOSS;
void *ptb_log_base;
@ -97,7 +99,7 @@ typedef struct _echo_dev {
LIST_HEAD(, _echo_stream) streams;
LIST_HEAD(, _echo_mem) mems;
echo_stream *pstream;
echo_stream *pstream, *pstream2;
echo_stream *rstream;
/* multi_audio */
@ -112,7 +114,7 @@ extern "C" {
#endif
status_t echo_stream_set_audioparms(echo_stream *stream, uint8 channels,
uint8 bitsPerSample, uint32 sample_rate);
uint8 bitsPerSample, uint32 sample_ratei, uint8 index);
status_t echo_stream_get_nth_buffer(echo_stream *stream, uint8 chan, uint8 buf,
char** buffer, size_t *stride);
void echo_stream_start(echo_stream *stream, void (*inth) (void *), void *inthparam);

View File

@ -40,10 +40,136 @@
#include "echo.h"
#include "util.h"
typedef enum {
B_MIX_GAIN = 1 << 0,
B_MIX_MUTE = 1 << 1,
B_MIX_MONO = 1 << 2,
B_MIX_STEREO = 1 << 3,
B_MIX_MUX = 1 << 4,
B_MIX_MICBOOST = 1 << 5,
B_MIX_RECORDMUX = 1 << 6
} mixer_type;
static void
echo_channel_get_mix(void *card, MIXER_AUDIO_CHANNEL channel, int32 type, float *values) {
echo_dev *dev = (echo_dev*) card;
MIXER_FUNCTION function;
INT32 size;
function.Channel = channel;
function.iFunction = type == B_MIX_GAIN ? MXF_GET_LEVEL : MXF_GET_MUTE;
dev->pEG->ProcessMixerFunction(&function, size);
if (function.RtnStatus == ECHOSTATUS_OK) {
values[0] = function.Data.iLevel;
PRINT(("echo_channel_get_mix iLevel: %d\n", function.Data.iLevel));
}
}
static void
echo_channel_set_mix(void *card, MIXER_AUDIO_CHANNEL channel, int32 type, float *values) {
echo_dev *dev = (echo_dev*) card;
MIXER_FUNCTION function;
INT32 size;
function.Channel = channel;
function.Data.iLevel = values[0];
function.iFunction = type == B_MIX_GAIN ? MXF_SET_LEVEL : MXF_SET_MUTE;
dev->pEG->ProcessMixerFunction(&function, size);
if (function.RtnStatus == ECHOSTATUS_OK) {
PRINT(("echo_channel_set_mix OK\n"));
}
}
static int32
echo_create_group_control(multi_dev *multi, uint32 *index, int32 parent,
enum strind_id string, const char* name) {
uint32 i = *index;
(*index)++;
multi->controls[i].mix_control.id = MULTI_CONTROL_FIRSTID + i;
multi->controls[i].mix_control.parent = parent;
multi->controls[i].mix_control.flags = B_MULTI_MIX_GROUP;
multi->controls[i].mix_control.master = MULTI_CONTROL_MASTERID;
multi->controls[i].mix_control.string = string;
if(name)
strcpy(multi->controls[i].mix_control.name, name);
return multi->controls[i].mix_control.id;
}
static void
echo_create_channel_control(multi_dev *multi, uint32 *index, int32 parent, int32 string,
MIXER_AUDIO_CHANNEL channel) {
uint32 i = *index, id;
multi_mixer_control control;
control.mix_control.master = MULTI_CONTROL_MASTERID;
control.mix_control.parent = parent;
control.channel = channel;
control.get = &echo_channel_get_mix;
control.set = &echo_channel_set_mix;
control.mix_control.gain.min_gain = -128;
control.mix_control.gain.max_gain = 6;
control.mix_control.gain.granularity = 1;
control.mix_control.id = MULTI_CONTROL_FIRSTID + i;
control.mix_control.flags = B_MULTI_MIX_ENABLE;
control.mix_control.string = S_MUTE;
control.type = B_MIX_MUTE;
multi->controls[i] = control;
i++;
control.mix_control.id = MULTI_CONTROL_FIRSTID + i;
control.mix_control.flags = B_MULTI_MIX_GAIN;
control.mix_control.string = S_null;
control.type = B_MIX_GAIN;
strcpy(control.mix_control.name, "Gain");
multi->controls[i] = control;
id = control.mix_control.id;
i++;
// second channel
control.mix_control.id = MULTI_CONTROL_FIRSTID + i;
control.mix_control.master = id;
multi->controls[i] = control;
i++;
*index = i;
}
static status_t
echo_create_controls_list(multi_dev *multi)
{
multi->control_count = 0;
uint32 i = 0, index = 0, parent, parent2;
echo_dev *card = (echo_dev*)multi->card;
parent = echo_create_group_control(multi, &index, 0, S_OUTPUT, NULL);
MIXER_AUDIO_CHANNEL channel;
channel.dwType = ECHO_BUS_OUT;
for (i=0; i < card->caps.wNumBussesOut / 2; i++) {
channel.wChannel = i;
parent2 = echo_create_group_control(multi, &index, parent, S_null, "Output");
echo_create_channel_control(multi, &index, parent2, 0, channel);
}
parent = echo_create_group_control(multi, &index, 0, S_INPUT, NULL);
channel.dwType = ECHO_BUS_IN;
for (i=0; i < card->caps.wNumBussesIn / 2; i++) {
channel.wChannel = i;
parent2 = echo_create_group_control(multi, &index, parent, S_null, "Input");
echo_create_channel_control(multi, &index, parent2, 0, channel);
}
multi->control_count = index;
PRINT(("multi->control_count %u\n", multi->control_count));
return B_OK;
}
@ -51,12 +177,104 @@ echo_create_controls_list(multi_dev *multi)
static status_t
echo_get_mix(echo_dev *card, multi_mix_value_info * MMVI)
{
int32 i;
uint32 id;
multi_mixer_control *control = NULL;
for(i=0; i<MMVI->item_count; i++) {
id = MMVI->values[i].id - MULTI_CONTROL_FIRSTID;
if(id < 0 || id >= card->multi.control_count) {
PRINT(("echo_get_mix : invalid control id requested : %i\n", id));
continue;
}
control = &card->multi.controls[id];
if(control->mix_control.flags & B_MULTI_MIX_GAIN) {
if(control->get) {
float values[2];
control->get(card, control->channel, control->type, values);
if(control->mix_control.master == MULTI_CONTROL_MASTERID)
MMVI->values[i].gain = values[0];
else
MMVI->values[i].gain = values[1];
}
}
if(control->mix_control.flags & B_MULTI_MIX_ENABLE && control->get) {
float values[1];
control->get(card, control->channel, control->type, values);
MMVI->values[i].enable = (values[0] == 1.0);
}
if(control->mix_control.flags & B_MULTI_MIX_MUX && control->get) {
float values[1];
control->get(card, control->channel, control->type, values);
MMVI->values[i].mux = (int32)values[0];
}
}
return B_OK;
}
static status_t
echo_set_mix(echo_dev *card, multi_mix_value_info * MMVI)
{
int32 i;
uint32 id;
multi_mixer_control *control = NULL;
for(i=0; i<MMVI->item_count; i++) {
id = MMVI->values[i].id - MULTI_CONTROL_FIRSTID;
if(id < 0 || id >= card->multi.control_count) {
PRINT(("echo_set_mix : invalid control id requested : %i\n", id));
continue;
}
control = &card->multi.controls[id];
if(control->mix_control.flags & B_MULTI_MIX_GAIN) {
multi_mixer_control *control2 = NULL;
if(i+1<MMVI->item_count) {
id = MMVI->values[i + 1].id - MULTI_CONTROL_FIRSTID;
if(id < 0 || id >= card->multi.control_count) {
PRINT(("echo_set_mix : invalid control id requested : %i\n", id));
} else {
control2 = &card->multi.controls[id];
if(control2->mix_control.master != control->mix_control.id)
control2 = NULL;
}
}
if(control->set) {
float values[2];
values[0] = 0.0;
values[1] = 0.0;
if(control->mix_control.master == MULTI_CONTROL_MASTERID)
values[0] = MMVI->values[i].gain;
else
values[1] = MMVI->values[i].gain;
if(control2 && control2->mix_control.master != MULTI_CONTROL_MASTERID)
values[1] = MMVI->values[i+1].gain;
control->set(card, control->channel, control->type, values);
}
if(control2)
i++;
}
if(control->mix_control.flags & B_MULTI_MIX_ENABLE && control->set) {
float values[1];
values[0] = MMVI->values[i].enable ? 1.0 : 0.0;
control->set(card, control->channel, control->type, values);
}
if(control->mix_control.flags & B_MULTI_MIX_MUX && control->set) {
float values[1];
values[0] = (float)MMVI->values[i].mux;
control->set(card, control->channel, control->type, values);
}
}
return B_OK;
}
@ -213,7 +431,7 @@ echo_get_description(echo_dev *card, multi_description *data)
data->interface_version = B_CURRENT_INTERFACE_VERSION;
data->interface_minimum = B_CURRENT_INTERFACE_VERSION;
strncpy(data->friendly_name, card->name, 32);
strncpy(data->friendly_name, card->caps.szName, 32);
strcpy(data->vendor_info, AUTHOR);
data->output_channel_count = card->multi.output_channel_count;
@ -308,7 +526,7 @@ echo_get_global_format(echo_dev *card, multi_format_info *data)
static status_t
echo_get_buffers(echo_dev *card, multi_buffer_list *data)
{
int32 i, j, pchannels, rchannels;
int32 i, j, pchannels, rchannels, pchannels2;
LOG(("flags = %#x\n",data->flags));
LOG(("request_playback_buffers = %#x\n",data->request_playback_buffers));
@ -319,10 +537,11 @@ echo_get_buffers(echo_dev *card, multi_buffer_list *data)
LOG(("request_record_buffer_size = %#x\n",data->request_record_buffer_size));
pchannels = card->pstream->channels;
pchannels2 = card->pstream2->channels;
rchannels = card->rstream->channels;
if (data->request_playback_buffers < BUFFER_COUNT ||
data->request_playback_channels < (pchannels) ||
data->request_playback_channels < (pchannels + pchannels2) ||
data->request_record_buffers < BUFFER_COUNT ||
data->request_record_channels < (rchannels)) {
LOG(("not enough channels/buffers\n"));
@ -334,7 +553,7 @@ echo_get_buffers(echo_dev *card, multi_buffer_list *data)
// data->flags = 0;
data->return_playback_buffers = BUFFER_COUNT; /* playback_buffers[b][] */
data->return_playback_channels = pchannels; /* playback_buffers[][c] */
data->return_playback_channels = pchannels + pchannels2; /* playback_buffers[][c] */
data->return_playback_buffer_size = BUFFER_FRAMES; /* frames */
for(i=0; i<BUFFER_COUNT; i++)
@ -343,6 +562,12 @@ echo_get_buffers(echo_dev *card, multi_buffer_list *data)
&data->playback_buffers[i][j].base,
&data->playback_buffers[i][j].stride);
for(i=0; i<BUFFER_COUNT; i++)
for(j=0; j<pchannels2; j++)
echo_stream_get_nth_buffer(card->pstream2, j, i,
&data->playback_buffers[i][pchannels + j].base,
&data->playback_buffers[i][pchannels + j].stride);
data->return_record_buffers = BUFFER_COUNT;
data->return_record_channels = rchannels;
data->return_record_buffer_size = BUFFER_FRAMES; /* frames */
@ -409,7 +634,8 @@ echo_buffer_exchange(echo_dev *card, multi_buffer_info *data)
if (!(card->pstream->state & ECHO_STATE_STARTED))
echo_stream_start(card->pstream, echo_play_inth, card->pstream);
if (!(card->pstream2->state & ECHO_STATE_STARTED))
echo_stream_start(card->pstream2, echo_play_inth, card->pstream2);
if (!(card->rstream->state & ECHO_STATE_STARTED))
echo_stream_start(card->rstream, echo_record_inth, card->rstream);
@ -596,16 +822,18 @@ echo_open(const char *name, uint32 flags, void** cookie)
card->rstream = echo_stream_new(card, ECHO_USE_RECORD, BUFFER_FRAMES, BUFFER_COUNT);
card->pstream = echo_stream_new(card, ECHO_USE_PLAY, BUFFER_FRAMES, BUFFER_COUNT);
card->pstream2 = echo_stream_new(card, ECHO_USE_PLAY, BUFFER_FRAMES, BUFFER_COUNT);
card->buffer_ready_sem = create_sem(0, "pbuffer ready");
LOG(("stream_setaudio\n"));
echo_stream_set_audioparms(card->pstream, 2, 16, 48000);
echo_stream_set_audioparms(card->rstream, 2, 16, 48000);
echo_stream_set_audioparms(card->pstream, 2, 16, 48000, 2);
echo_stream_set_audioparms(card->pstream2, 2, 16, 48000, 0);
echo_stream_set_audioparms(card->rstream, 2, 16, 48000, 0);
card->pstream->first_channel = 0;
card->rstream->first_channel = 2;
card->rstream->first_channel = 4;
echo_create_channels_list(&card->multi);

View File

@ -31,29 +31,32 @@
#ifndef _MULTI_H_
#define _MULTI_H_
#include "OsSupportBeOS.h"
#include "MixerXface.h"
#define BUFFER_FRAMES 512
#define BUFFER_COUNT 2
typedef struct _multi_mixer_control {
struct _multi_dev *multi;
void (*get) (void *card, const void *cookie, int32 type, float *values);
void (*set) (void *card, const void *cookie, int32 type, float *values);
const void *cookie;
void (*get) (void *card, MIXER_AUDIO_CHANNEL, int32 type, float *values);
void (*set) (void *card, MIXER_AUDIO_CHANNEL, int32 type, float *values);
MIXER_AUDIO_CHANNEL channel;
int32 type;
multi_mix_control mix_control;
} multi_mixer_control;
#define EMU_MULTI_CONTROL_FIRSTID 1024
#define EMU_MULTI_CONTROL_MASTERID 0
#define MULTI_CONTROL_FIRSTID 1024
#define MULTI_CONTROL_MASTERID 0
typedef struct _multi_dev {
void *card;
#define EMU_MULTICONTROLSNUM 64
multi_mixer_control controls[EMU_MULTICONTROLSNUM];
#define MULTICONTROLSNUM 128
multi_mixer_control controls[MULTICONTROLSNUM];
uint32 control_count;
#define EMU_MULTICHANNUM 64
multi_channel_info chans[EMU_MULTICHANNUM];
#define MULTICHANNUM 128
multi_channel_info chans[MULTICHANNUM];
uint32 output_channel_count;
uint32 input_channel_count;
uint32 output_bus_channel_count;