100cffa1cSbeveloper // MixerAddOn.cpp 200cffa1cSbeveloper // 300cffa1cSbeveloper // David Shipman, 2002 4*c9c07d81Sbeveloper // Marcus Overhagen, 2003 500cffa1cSbeveloper // 6*c9c07d81Sbeveloper // Allows AudioMixer to be used as an addon. 7*c9c07d81Sbeveloper // The add-on will request to be auto-started, 8*c9c07d81Sbeveloper // if this happens, it will try to connect 9*c9c07d81Sbeveloper // itself to the default audio output. 10*c9c07d81Sbeveloper 11*c9c07d81Sbeveloper #include <MediaRoster.h> 12*c9c07d81Sbeveloper #include <MediaNode.h> 13*c9c07d81Sbeveloper #include <cstring> 14*c9c07d81Sbeveloper #include <cstdio> 1500cffa1cSbeveloper 1600cffa1cSbeveloper #include "AudioMixer.h" 1700cffa1cSbeveloper #include "MixerAddOn.h" 1800cffa1cSbeveloper 1900cffa1cSbeveloper // instantiation function 2000cffa1cSbeveloper extern "C" _EXPORT BMediaAddOn* make_media_addon(image_id image) { 2100cffa1cSbeveloper return new AudioMixerAddon(image); 2200cffa1cSbeveloper } 2300cffa1cSbeveloper 24ea83877fSbeveloper // ------------------------------------------------------- // 2500cffa1cSbeveloper // ctor/dtor 2600cffa1cSbeveloper // -------------------------------------------------------- // 2700cffa1cSbeveloper 28*c9c07d81Sbeveloper AudioMixerAddon::AudioMixerAddon(image_id image) 29*c9c07d81Sbeveloper : BMediaAddOn(image), 30*c9c07d81Sbeveloper fFormat(new media_format), 31*c9c07d81Sbeveloper fInfo(new flavor_info) 32*c9c07d81Sbeveloper { 33*c9c07d81Sbeveloper // Init media_format 34*c9c07d81Sbeveloper memset(fFormat, 0, sizeof(*fFormat)); 35*c9c07d81Sbeveloper fFormat->type = B_MEDIA_RAW_AUDIO; 36*c9c07d81Sbeveloper fFormat->u.raw_audio = media_raw_audio_format::wildcard; 3700cffa1cSbeveloper 38*c9c07d81Sbeveloper // Init flavor_info 39*c9c07d81Sbeveloper fInfo->internal_id = 0; 40ea83877fSbeveloper fInfo->name = "AudioMixer"; 4129372222Sbeveloper fInfo->info = "AudioMixer media addon"; 42ea83877fSbeveloper fInfo->kinds = B_BUFFER_PRODUCER | B_BUFFER_CONSUMER | B_SYSTEM_MIXER | B_CONTROLLABLE; 4329625f76Sbeveloper fInfo->flavor_flags = 0; // 0 = global or local instantiation allowed, no restrictions 4429625f76Sbeveloper fInfo->possible_count = 0; // 0 = infinite 45ea83877fSbeveloper fInfo->in_format_count = 1; 46ea83877fSbeveloper fInfo->in_formats = fFormat; 47ea83877fSbeveloper fInfo->out_format_count = 1; 48ea83877fSbeveloper fInfo->out_formats = fFormat; 49*c9c07d81Sbeveloper } 50*c9c07d81Sbeveloper 51*c9c07d81Sbeveloper AudioMixerAddon::~AudioMixerAddon() 52*c9c07d81Sbeveloper { 53*c9c07d81Sbeveloper delete fFormat; 54*c9c07d81Sbeveloper delete fInfo; 55*c9c07d81Sbeveloper } 56*c9c07d81Sbeveloper 57*c9c07d81Sbeveloper // -------------------------------------------------------- // 58*c9c07d81Sbeveloper // BMediaAddOn impl 59*c9c07d81Sbeveloper // -------------------------------------------------------- // 60*c9c07d81Sbeveloper 61*c9c07d81Sbeveloper status_t 62*c9c07d81Sbeveloper AudioMixerAddon::InitCheck(const char** out_failure_text) 63*c9c07d81Sbeveloper { 64*c9c07d81Sbeveloper return B_OK; 65*c9c07d81Sbeveloper } 66*c9c07d81Sbeveloper 67*c9c07d81Sbeveloper int32 68*c9c07d81Sbeveloper AudioMixerAddon::CountFlavors() 69*c9c07d81Sbeveloper { 70*c9c07d81Sbeveloper return 1; 71*c9c07d81Sbeveloper } 72*c9c07d81Sbeveloper 73*c9c07d81Sbeveloper status_t 74*c9c07d81Sbeveloper AudioMixerAddon::GetFlavorAt(int32 n, const flavor_info** out_info) 75*c9c07d81Sbeveloper { 76*c9c07d81Sbeveloper // only the 0th flavor exists 77*c9c07d81Sbeveloper if (n != 0) 78*c9c07d81Sbeveloper return B_ERROR; 7900cffa1cSbeveloper 80ea83877fSbeveloper *out_info = fInfo; 8100cffa1cSbeveloper return B_OK; 8200cffa1cSbeveloper } 8300cffa1cSbeveloper 84*c9c07d81Sbeveloper BMediaNode * 85*c9c07d81Sbeveloper AudioMixerAddon::InstantiateNodeFor(const flavor_info* info, BMessage* config, 86*c9c07d81Sbeveloper status_t* out_error) 87*c9c07d81Sbeveloper { 8800cffa1cSbeveloper return new AudioMixer(this); 8900cffa1cSbeveloper } 9000cffa1cSbeveloper 91*c9c07d81Sbeveloper status_t 92*c9c07d81Sbeveloper AudioMixerAddon::GetConfigurationFor(BMediaNode* your_node, BMessage* into_message) 93*c9c07d81Sbeveloper { 9400cffa1cSbeveloper // no config yet 95ea83877fSbeveloper return B_ERROR; 9600cffa1cSbeveloper } 9700cffa1cSbeveloper 98*c9c07d81Sbeveloper bool 99*c9c07d81Sbeveloper AudioMixerAddon::WantsAutoStart() 100*c9c07d81Sbeveloper { 101*c9c07d81Sbeveloper // yes, please kick me 102*c9c07d81Sbeveloper return true; 103*c9c07d81Sbeveloper } 104*c9c07d81Sbeveloper 105*c9c07d81Sbeveloper status_t 106*c9c07d81Sbeveloper AudioMixerAddon::AutoStart(int in_index, BMediaNode ** out_node, 107*c9c07d81Sbeveloper int32 * out_internal_id, bool * out_has_more) 108*c9c07d81Sbeveloper { 109*c9c07d81Sbeveloper *out_has_more = false; 110*c9c07d81Sbeveloper 111*c9c07d81Sbeveloper if (in_index != 0) 112*c9c07d81Sbeveloper return B_ERROR; 113*c9c07d81Sbeveloper 114*c9c07d81Sbeveloper *out_internal_id = 0; 115*c9c07d81Sbeveloper *out_node = new AudioMixer(this); 116*c9c07d81Sbeveloper 117*c9c07d81Sbeveloper // The mixer has been created. 118*c9c07d81Sbeveloper // We now try to connect it with the default audio output. 119*c9c07d81Sbeveloper 120*c9c07d81Sbeveloper if (ConnectToOutput(*out_node) != B_OK) { 121*c9c07d81Sbeveloper printf("AudioMixerAddon::AutoStart: failed to ConnectToOutput()\n"); 122*c9c07d81Sbeveloper // cleanup 123*c9c07d81Sbeveloper // return B_ERROR; 124*c9c07d81Sbeveloper } 125*c9c07d81Sbeveloper 126*c9c07d81Sbeveloper return B_OK; 127*c9c07d81Sbeveloper } 128*c9c07d81Sbeveloper 129*c9c07d81Sbeveloper status_t 130*c9c07d81Sbeveloper AudioMixerAddon::ConnectToOutput(BMediaNode *node) 131*c9c07d81Sbeveloper { 132*c9c07d81Sbeveloper BMediaRoster *roster; 133*c9c07d81Sbeveloper media_node mixer; 134*c9c07d81Sbeveloper media_node soundcard; 135*c9c07d81Sbeveloper media_input input; 136*c9c07d81Sbeveloper media_output output; 137*c9c07d81Sbeveloper int32 count; 138*c9c07d81Sbeveloper status_t rv; 139*c9c07d81Sbeveloper 140*c9c07d81Sbeveloper roster = BMediaRoster::Roster(); 141*c9c07d81Sbeveloper mixer = node->Node(); 142*c9c07d81Sbeveloper 143*c9c07d81Sbeveloper // XXX this connects to *any* physical output, but not the default logical input 144*c9c07d81Sbeveloper 145*c9c07d81Sbeveloper rv = roster->GetAudioOutput(&soundcard); 146*c9c07d81Sbeveloper if (rv < B_OK) { 147*c9c07d81Sbeveloper printf("AudioMixerAddon::AutoStart: failed to find soundcard (physical audio output)\n"); 148*c9c07d81Sbeveloper return B_ERROR; 149*c9c07d81Sbeveloper } 150*c9c07d81Sbeveloper 151*c9c07d81Sbeveloper // we now have the mixer and soundcard nodes, 152*c9c07d81Sbeveloper // find a free input/output and connect them 153*c9c07d81Sbeveloper 154*c9c07d81Sbeveloper rv = roster->GetFreeOutputsFor(mixer, &output, 1, &count, B_MEDIA_RAW_AUDIO); 155*c9c07d81Sbeveloper if (rv < B_OK || count != 1) { 156*c9c07d81Sbeveloper printf("AudioMixerAddon::AutoStart: can't find free mixer output\n"); 157*c9c07d81Sbeveloper return B_ERROR; 158*c9c07d81Sbeveloper } 159*c9c07d81Sbeveloper 160*c9c07d81Sbeveloper rv = roster->GetFreeInputsFor(soundcard, &input, 1, &count, B_MEDIA_RAW_AUDIO); 161*c9c07d81Sbeveloper if (rv < B_OK || count != 1) { 162*c9c07d81Sbeveloper printf("AudioMixerAddon::AutoStart: can't find free soundcard input\n"); 163*c9c07d81Sbeveloper return B_ERROR; 164*c9c07d81Sbeveloper } 165*c9c07d81Sbeveloper 166*c9c07d81Sbeveloper media_format format; 167*c9c07d81Sbeveloper memset(&format, 0, sizeof(format)); 168*c9c07d81Sbeveloper format.type = B_MEDIA_RAW_AUDIO; 169*c9c07d81Sbeveloper 170*c9c07d81Sbeveloper rv = roster->Connect(output.source, input.destination, &format, &output, &input); 171*c9c07d81Sbeveloper if (rv < B_OK) { 172*c9c07d81Sbeveloper printf("AudioMixerAddon::AutoStart: connect failed\n"); 173*c9c07d81Sbeveloper return B_ERROR; 174*c9c07d81Sbeveloper } 175*c9c07d81Sbeveloper 176*c9c07d81Sbeveloper return B_OK; 177*c9c07d81Sbeveloper } 178