From c9002531707d3f9a185a100dc6393d7b6e75aca3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Wed, 30 Mar 2005 18:58:43 +0000 Subject: [PATCH] work in progress changed name initial mixer interface git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@12164 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../kernel/drivers/audio/echo/echo.cpp | 54 +++- src/add-ons/kernel/drivers/audio/echo/echo.h | 6 +- .../kernel/drivers/audio/echo/multi.cpp | 248 +++++++++++++++++- src/add-ons/kernel/drivers/audio/echo/multi.h | 21 +- 4 files changed, 299 insertions(+), 30 deletions(-) diff --git a/src/add-ons/kernel/drivers/audio/echo/echo.cpp b/src/add-ons/kernel/drivers/audio/echo/echo.cpp index 6cf229f40c..6254ef1981 100644 --- a/src/add-ons/kernel/drivers/audio/echo/echo.cpp +++ b/src/add-ons/kernel/drivers/audio/echo/echo.cpp @@ -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; diff --git a/src/add-ons/kernel/drivers/audio/echo/echo.h b/src/add-ons/kernel/drivers/audio/echo/echo.h index ed0de8614a..52fc0ffd73 100644 --- a/src/add-ons/kernel/drivers/audio/echo/echo.h +++ b/src/add-ons/kernel/drivers/audio/echo/echo.h @@ -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); diff --git a/src/add-ons/kernel/drivers/audio/echo/multi.cpp b/src/add-ons/kernel/drivers/audio/echo/multi.cpp index 591ed3daee..a98844190a 100644 --- a/src/add-ons/kernel/drivers/audio/echo/multi.cpp +++ b/src/add-ons/kernel/drivers/audio/echo/multi.cpp @@ -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; iitem_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; iitem_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+1item_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; ipstream, j, i, &data->playback_buffers[i][j].base, &data->playback_buffers[i][j].stride); + + for(i=0; ipstream2, 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; @@ -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,19 +822,21 @@ 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); - + return B_OK; } diff --git a/src/add-ons/kernel/drivers/audio/echo/multi.h b/src/add-ons/kernel/drivers/audio/echo/multi.h index b0d908a29c..6d6499b7c9 100644 --- a/src/add-ons/kernel/drivers/audio/echo/multi.h +++ b/src/add-ons/kernel/drivers/audio/echo/multi.h @@ -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;