[haiku-development] Further null_audio stuff

  • From: "HOST Team" <HOST.HAIKU@xxxxxx>
  • To: haiku-development@xxxxxxxxxxxxx
  • Date: Sun, 07 Oct 2007 21:57:29 +0200

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

Other related posts:

  • » [haiku-development] Further null_audio stuff