Hi all, I've attached two diffs. First one adds controls to the media preferences for changing the volume of the fake driver. They actually do nothing, but as it is supposed to be a demo driver, I thought it makes sense to finish some relevant parts of it :) The second one is about an issue, which has been discussed previously on this list. In case Haiku finds another real sound card, it was not guaranteed that this one is prioritized over the Virtual Audio one. This fixes it by using the same logic used for the "None Out" and "None In", which I haven't seen anywhere yet. I am not sure if it is needed to include it, but in case the null_audio driver gets into the build, then it probably makes sense to have that patch in, too. Best Regards, Bek -- Psssst! Schon vom neuen GMX MultiMessenger gehört? Der kanns mit allen: http://www.gmx.net/de/go/multimessenger
diff -ur src/add-ons/kernel/drivers/audio/null/driver.c /home/bek/null_audio/driver.c --- src/add-ons/kernel/drivers/audio/null/driver.c 2007-10-07 21:44:46.000000000 +0200 +++ /home/bek/null_audio/driver.c 2007-10-07 21:44:19.000000000 +0200 @@ -22,8 +22,11 @@ status_t init_driver(void) { + int i; dprintf("null_audio: %s\n", __func__); device.running = false; + for (i=0; i < 4; ++i) + device.mix_values[i] = NULL_MAXIMUM_GAIN * 0.8f; return B_OK; } diff -ur src/add-ons/kernel/drivers/audio/null/driver.h /home/bek/null_audio/driver.h --- src/add-ons/kernel/drivers/audio/null/driver.h 2007-10-07 21:44:46.000000000 +0200 +++ /home/bek/null_audio/driver.h 2007-10-07 21:44:19.000000000 +0200 @@ -19,6 +19,9 @@ #define MULTI_AUDIO_MASTER_ID 0 #define STRMINBUF 2 #define STRMAXBUF 2 +#define NULL_MINIMUM_GAIN 0.f +#define NULL_MAXIMUM_GAIN 100.f +#define NULL_GAIN_GRANULARITY 0.5f typedef struct { spinlock lock; @@ -42,6 +45,8 @@ typedef struct { device_stream_t playback_stream; device_stream_t record_stream; + + float mix_values[4]; thread_id interrupt_thread; bool running; diff -ur src/add-ons/kernel/drivers/audio/null/null_multi.c /home/bek/null_audio/null_multi.c --- src/add-ons/kernel/drivers/audio/null/null_multi.c 2007-10-07 21:44:46.000000000 +0200 +++ /home/bek/null_audio/null_multi.c 2007-10-07 21:44:19.000000000 +0200 @@ -131,31 +131,100 @@ return B_OK; } +static status_t +get_mix(device_t* card, multi_mix_value_info* info) +{ + int32 i, index; + + for (i=0; i < info->item_count; ++i) { + index = info->values[i].id - MULTI_AUDIO_BASE_ID; + if (index < 0 || index >= 4) { + dprintf("null_audio: %s invalid control requested : %li\n", __func__, index); + continue; + } + info->values[i].u.gain = card->mix_values[index]; + } + return B_OK; +} + +static status_t +set_mix(device_t* card, multi_mix_value_info* info) +{ + int32 i,index; + + for (i=0; i < info->item_count; ++i) { + index = info->values[i].id - MULTI_AUDIO_BASE_ID; + if (index < 0 || index >= 4) { + dprintf("null_audio: %s invalid control requested : %li\n", __func__, index); + continue; + } + card->mix_values[index] = info->values[i].u.gain; + } + return B_OK; +} static int32 create_group_control(multi_mix_control* multi, int32 idx, int32 parent, int32 string, const char* name) { - multi->id = MULTI_AUDIO_BASE_ID + idx; - multi->parent = parent; - multi->flags = B_MULTI_MIX_GROUP; - multi->master = MULTI_AUDIO_MASTER_ID; - multi->string = string; - if(name) - strcpy(multi->name, name); + multi->id = MULTI_AUDIO_BASE_ID + idx; + multi->parent = parent; + multi->flags = B_MULTI_MIX_GROUP; + multi->master = MULTI_AUDIO_MASTER_ID; + multi->string = string; + if(name) + strcpy(multi->name, name); - return multi->id; + return multi->id; } +static int32 +create_gain_control(multi_mix_control* multi, int32 idx, int32 parent, + int32 master, int32 string, const char* name) +{ + multi->id = idx; + multi->parent = parent; + multi->flags = B_MULTI_MIX_GAIN; + multi->master = master; + multi->string = string; + if (name) + strcpy(multi->name, name); + + multi->u.gain.min_gain = NULL_MINIMUM_GAIN; + multi->u.gain.max_gain = NULL_MAXIMUM_GAIN; + multi->u.gain.granularity = NULL_GAIN_GRANULARITY; + return multi->id; +} static status_t list_mix_controls(device_t* device, multi_mix_control_info * data) { - int32 parent; + int32 master = MULTI_AUDIO_MASTER_ID; + int32 index = 0; + int32 outputGroupID; + int32 inputGroupID; dprintf("null_audio: %s\n" , __func__ ); - parent = create_group_control(data->controls +0, 0, 0, 0, "Record"); - parent = create_group_control(data->controls +1, 1, 0, 0, "Playback"); - data->control_count = 2; + // First create groups, then the actual controls + outputGroupID = create_group_control(data->controls + 0, index++, 0, 0, "Playback"); + outputGroupID = create_group_control(data->controls + 1, index++, outputGroupID, S_MASTER, "Master"); + inputGroupID = create_group_control(data->controls + 2, index++, 0, 0, "Record"); + inputGroupID = create_group_control(data->controls + 3, index++, inputGroupID, S_LINE, "Line In"); + + index = MULTI_AUDIO_BASE_ID; + + // Output controls + // to combine two mono volume controls to one stereo, the first channel + // becomes the master of the others. + master = create_gain_control(data->controls + 4, index++, outputGroupID, master, S_VOLUME, "L"); + create_gain_control(data->controls + 5, index++, outputGroupID, master, S_VOLUME, "R"); + + // Input controls + master = create_gain_control(data->controls + 6, index++, inputGroupID, MULTI_AUDIO_MASTER_ID, S_VOLUME, "L"); + create_gain_control(data->controls + 7, index++, inputGroupID, master, S_VOLUME, "R"); + + // tell the MediaKit, how many controls we have all in all + // that also means groups etc. + data->control_count = 8; return B_OK; } @@ -334,8 +403,8 @@ case B_MULTI_SET_GLOBAL_FORMAT: return set_global_format(cookie, arg); case B_MULTI_GET_CHANNEL_FORMATS: return B_ERROR; case B_MULTI_SET_CHANNEL_FORMATS: return B_ERROR; - case B_MULTI_GET_MIX: return B_ERROR; - case B_MULTI_SET_MIX: return B_ERROR; + case B_MULTI_GET_MIX: return get_mix(cookie, arg); + case B_MULTI_SET_MIX: return set_mix(cookie, arg); case B_MULTI_LIST_MIX_CHANNELS: return list_mix_channels(cookie, arg); case B_MULTI_LIST_MIX_CONTROLS: return list_mix_controls(cookie, arg); case B_MULTI_LIST_MIX_CONNECTIONS: return list_mix_connections(cookie, arg);
--- src/servers/media/DefaultManager.cpp 2007-10-07 21:44:46.000000000 +0200 +++ /home/bek/Desktop/DefaultManager.cpp 2007-10-07 21:43:59.000000000 +0200 @@ -379,6 +379,11 @@ for (int i = 0; i < count; i++) { if (isAudio) { + if (0 == strcmp(info[i].name, "Virtual Audio (null_audio)")) { + // we keep the Virtual Audio driver if none else matches + *id = info[i].node.node; + continue; + } if (isInput) { if (0 == strcmp(info[i].name, "None In")) { // we keep the Null audio driver if none else matchs