added support for a settings file,

some fixes in the deferred saving code,
added save/load to mixer connections


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@4294 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
beveloper
2003-08-17 16:03:46 +00:00
parent f825dfe370
commit 1165d5e18a
7 changed files with 137 additions and 70 deletions
@@ -8,6 +8,8 @@
#include <TimeSource.h> #include <TimeSource.h>
#include <ParameterWeb.h> #include <ParameterWeb.h>
#include <MediaRoster.h> #include <MediaRoster.h>
#include <FindDirectory.h>
#include <Path.h>
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@@ -40,7 +42,7 @@ static void multi_audio_format_specialize(media_multi_audio_format *format, cons
#define FORMAT_USER_DATA_MAGIC_1 0xc84173bd #define FORMAT_USER_DATA_MAGIC_1 0xc84173bd
#define FORMAT_USER_DATA_MAGIC_2 0x4af62b7d #define FORMAT_USER_DATA_MAGIC_2 0x4af62b7d
AudioMixer::AudioMixer(BMediaAddOn *addOn) AudioMixer::AudioMixer(BMediaAddOn *addOn, bool isSystemMixer)
: BMediaNode("Audio Mixer"), : BMediaNode("Audio Mixer"),
BBufferConsumer(B_MEDIA_RAW_AUDIO), BBufferConsumer(B_MEDIA_RAW_AUDIO),
BBufferProducer(B_MEDIA_RAW_AUDIO), BBufferProducer(B_MEDIA_RAW_AUDIO),
@@ -67,6 +69,18 @@ AudioMixer::AudioMixer(BMediaAddOn *addOn)
fDefaultFormat.u.raw_audio.valid_bits = 0; fDefaultFormat.u.raw_audio.valid_bits = 0;
fDefaultFormat.u.raw_audio.matrix_mask = 0; fDefaultFormat.u.raw_audio.matrix_mask = 0;
if (isSystemMixer) {
// to get persistent settings, assign a settings file
BPath path;
if (B_OK != find_directory (B_USER_SETTINGS_DIRECTORY, &path))
path.SetTo("/boot/home/config/settings/");
path.Append("System Audio Mixer");
fCore->Settings()->SetSettingsFile(path.Path());
// disable stop on the auto started (system) mixer
DisableNodeStop();
}
ApplySettings(); ApplySettings();
} }
@@ -328,7 +342,10 @@ AudioMixer::Connected(const media_source &producer, const media_destination &whe
sprintf(out_input->name, "Input %ld", out_input->destination.id); sprintf(out_input->name, "Input %ld", out_input->destination.id);
// add a new input to the mixer engine // add a new input to the mixer engine
fCore->AddInput(*out_input); MixerInput *input;
input = fCore->AddInput(*out_input);
fCore->Settings()->LoadConnectionSettings(input);
fCore->Unlock(); fCore->Unlock();
@@ -786,6 +803,9 @@ AudioMixer::Connect(status_t error, const media_source &source, const media_dest
fCore->EnableOutput(true); fCore->EnableOutput(true);
fCore->SetTimingInfo(TimeSource(), fDownstreamLatency); fCore->SetTimingInfo(TimeSource(), fDownstreamLatency);
fCore->SetOutputBufferGroup(fBufferGroup); fCore->SetOutputBufferGroup(fBufferGroup);
fCore->Settings()->LoadConnectionSettings(fCore->Output());
fCore->Unlock(); fCore->Unlock();
UpdateParameterWeb(); UpdateParameterWeb();
@@ -1353,6 +1373,7 @@ AudioMixer::SetParameterValue(int32 id, bigtime_t when,
goto err; goto err;
output->SetOutputChannelSourceGain(PARAM_CHAN(id), PARAM_SRC(id), PERCENT_TO_GAIN(static_cast<const float *>(value)[0])); output->SetOutputChannelSourceGain(PARAM_CHAN(id), PARAM_SRC(id), PERCENT_TO_GAIN(static_cast<const float *>(value)[0]));
} }
fCore->Settings()->SaveConnectionSettings(output);
} else { } else {
MixerInput *input; MixerInput *input;
for (int i = 0; (input = fCore->Input(i)); i++) for (int i = 0; (input = fCore->Input(i)); i++)
@@ -1457,6 +1478,7 @@ AudioMixer::SetParameterValue(int32 id, bigtime_t when,
// but it will change the fokus from tab 3 to tab 1 // but it will change the fokus from tab 3 to tab 1
update = true; update = true;
} }
fCore->Settings()->SaveConnectionSettings(input);
} }
BroadcastNewParameterValue(when, id, const_cast<void *>(value), size); BroadcastNewParameterValue(when, id, const_cast<void *>(value), size);
err: err:
@@ -34,7 +34,7 @@ class AudioMixer :
public: public:
AudioMixer(BMediaAddOn *addOn); AudioMixer(BMediaAddOn *addOn, bool isSystemMixer);
~AudioMixer(); ~AudioMixer();
@@ -83,7 +83,7 @@ BMediaNode *
AudioMixerAddon::InstantiateNodeFor(const flavor_info* info, BMessage* config, AudioMixerAddon::InstantiateNodeFor(const flavor_info* info, BMessage* config,
status_t* out_error) status_t* out_error)
{ {
return new AudioMixer(this); return new AudioMixer(this, false);
} }
status_t status_t
@@ -110,11 +110,7 @@ AudioMixerAddon::AutoStart(int in_index, BMediaNode ** out_node,
return B_ERROR; return B_ERROR;
*out_internal_id = 0; *out_internal_id = 0;
AudioMixer *mixer = new AudioMixer(this); AudioMixer *mixer = new AudioMixer(this, true);
// disable stop on the auto started (system) mixer
mixer->DisableNodeStop();
*out_node = mixer; *out_node = mixer;
return B_OK; return B_OK;
@@ -100,23 +100,23 @@ MixerCore::SetOutputAttenuation(float gain)
fOutputGain = gain; fOutputGain = gain;
} }
bool MixerInput *
MixerCore::AddInput(const media_input &input) MixerCore::AddInput(const media_input &input)
{ {
ASSERT_LOCKED(); ASSERT_LOCKED();
if (HasKawamba()) MixerInput *in = new MixerInput(this, input, fMixBufferFrameRate, fMixBufferFrameCount);
fInputs->AddItem(new MixerInput(this, input, fMixBufferFrameRate * 1.5, fMixBufferFrameCount * 2)); fInputs->AddItem(in);
else return in;
fInputs->AddItem(new MixerInput(this, input, fMixBufferFrameRate, fMixBufferFrameCount));
return true;
} }
bool MixerOutput *
MixerCore::AddOutput(const media_output &output) MixerCore::AddOutput(const media_output &output)
{ {
ASSERT_LOCKED(); ASSERT_LOCKED();
if (fOutput) if (fOutput) {
return false; ERROR("MixerCore::AddOutput: already connected\n");
return fOutput;
}
fOutput = new MixerOutput(this, output); fOutput = new MixerOutput(this, output);
// the output format might have been adjusted inside MixerOutput // the output format might have been adjusted inside MixerOutput
ApplyOutputFormat(); ApplyOutputFormat();
@@ -124,6 +124,8 @@ MixerCore::AddOutput(const media_output &output)
ASSERT(!fRunning); ASSERT(!fRunning);
if (fStarted && fOutputEnabled) if (fStarted && fOutputEnabled)
StartMixThread(); StartMixThread();
return fOutput;
} }
bool bool
@@ -29,8 +29,8 @@ public:
// the audio mixer node using SetOutputAttenuation() // the audio mixer node using SetOutputAttenuation()
void SetOutputAttenuation(float gain); void SetOutputAttenuation(float gain);
bool AddInput(const media_input &input); MixerInput * AddInput(const media_input &input);
bool AddOutput(const media_output &output); MixerOutput * AddOutput(const media_output &output);
bool RemoveInput(int32 inputID); bool RemoveInput(int32 inputID);
bool RemoveOutput(); bool RemoveOutput();
@@ -1,5 +1,6 @@
#include <MediaDefs.h> #include <MediaDefs.h>
#include <Locker.h> #include <Locker.h>
#include <Path.h>
#include <OS.h> #include <OS.h>
#include "MixerCore.h" #include "MixerCore.h"
@@ -8,15 +9,17 @@
#include "MixerSettings.h" #include "MixerSettings.h"
#include "debug.h" #include "debug.h"
#define SAVE_DELAY 8000000 // delay saving of settings for 8s #define SAVE_DELAY 5000000 // delay saving of settings for 5s
#define SAVE_RUNTIME 40000000 // stop save thread after 40s inactivity #define SAVE_RUNTIME 30000000 // stop save thread after 30s inactivity
MixerSettings::MixerSettings() MixerSettings::MixerSettings()
: fLocker(new BLocker), : fLocker(new BLocker),
fSettingsFile(0),
fSettingsDirty(false), fSettingsDirty(false),
fSettingsLastChange(0), fSettingsLastChange(0),
fSaveThread(-1), fSaveThread(-1),
fSaveThreadWaitSem(-1) fSaveThreadWaitSem(-1),
fSaveThreadRunning(false)
{ {
Load(); Load();
} }
@@ -27,6 +30,16 @@ MixerSettings::~MixerSettings()
if (fSettingsDirty) if (fSettingsDirty)
Save(); Save();
delete fLocker; delete fLocker;
delete fSettingsFile;
}
void
MixerSettings::SetSettingsFile(const char *file)
{
fLocker->Lock();
delete fSettingsFile;
fSettingsFile = new BPath(file);
fLocker->Unlock();
} }
bool bool
@@ -201,27 +214,29 @@ MixerSettings::SetRefuseInputFormatChange(bool yesno)
} }
void void
MixerSettings::SaveGain(MixerInput *input) MixerSettings::SaveConnectionSettings(MixerInput *input)
{
StartDeferredSave();
}
void
MixerSettings::LoadConnectionSettings(MixerInput *input)
{ {
} }
void void
MixerSettings::LoadGain(MixerInput *input) MixerSettings::SaveConnectionSettings(MixerOutput *output)
{
StartDeferredSave();
}
void
MixerSettings::LoadConnectionSettings(MixerOutput *output)
{ {
} }
void void
MixerSettings::SaveGain(MixerOutput *output) MixerSettings::SaveConnectionSettingsSetting(const char *name, uint32 channel_mask, const float *gain, int gain_count)
{
}
void
MixerSettings::LoadGain(MixerOutput *output)
{
}
void
MixerSettings::SaveGainSetting(const char *name, uint32 channel_mask, const float *gain, int gain_count)
{ {
fLocker->Lock(); fLocker->Lock();
@@ -232,7 +247,7 @@ MixerSettings::SaveGainSetting(const char *name, uint32 channel_mask, const floa
} }
void void
MixerSettings::LoadGainSetting(const char *name, uint32 channel_mask, float *gain, int gain_count) MixerSettings::LoadConnectionSettingsSetting(const char *name, uint32 channel_mask, float *gain, int gain_count)
{ {
fLocker->Lock(); fLocker->Lock();
@@ -266,9 +281,16 @@ void
MixerSettings::Save() MixerSettings::Save()
{ {
fLocker->Lock(); fLocker->Lock();
// if we don't have a settings file, don't continue
if (!fSettingsFile) {
fLocker->Unlock();
return;
}
TRACE("MixerSettings: SAVE!\n"); TRACE("MixerSettings: SAVE!\n");
// XXX work // XXX work
fSettingsDirty = false; fSettingsDirty = false;
@@ -279,9 +301,7 @@ void
MixerSettings::Load() MixerSettings::Load()
{ {
fLocker->Lock(); fLocker->Lock();
// setup defaults
// XXX work
fSettings.AttenuateOutput = true; fSettings.AttenuateOutput = true;
fSettings.NonLinearGainSlider = true; fSettings.NonLinearGainSlider = true;
fSettings.UseBalanceControl = false; fSettings.UseBalanceControl = false;
@@ -292,6 +312,12 @@ MixerSettings::Load()
fSettings.RefuseOutputFormatChange = false; fSettings.RefuseOutputFormatChange = false;
fSettings.RefuseInputFormatChange = false; fSettings.RefuseInputFormatChange = false;
// if we don't have a settings file, don't continue
if (!fSettingsFile) {
fLocker->Unlock();
return;
}
fLocker->Unlock(); fLocker->Unlock();
} }
@@ -300,28 +326,44 @@ MixerSettings::StartDeferredSave()
{ {
fLocker->Lock(); fLocker->Lock();
// if we don't have a settings file, don't save the settings
if (!fSettingsFile) {
fLocker->Unlock();
return;
}
fSettingsDirty = true; fSettingsDirty = true;
fSettingsLastChange = system_time(); fSettingsLastChange = system_time();
if (fSaveThread < 0) { if (fSaveThreadRunning) {
ASSERT(fSaveThreadWaitSem < 0); fLocker->Unlock();
fSaveThreadWaitSem = create_sem(0, "save thread wait"); return;
if (fSaveThreadWaitSem < B_OK) {
ERROR("MixerSettings: can't create semaphore\n");
Save();
fLocker->Unlock();
return;
}
fSaveThread = spawn_thread(_save_thread_, "deferred settings save", 7, this);
if (fSaveThread < B_OK) {
ERROR("MixerSettings: can't spawn thread\n");
delete_sem(fSaveThreadWaitSem);
fSaveThreadWaitSem = -1;
Save();
fLocker->Unlock();
return;
}
} }
StopDeferredSave();
ASSERT(fSaveThreadWaitSem < 0);
fSaveThreadWaitSem = create_sem(0, "save thread wait");
if (fSaveThreadWaitSem < B_OK) {
ERROR("MixerSettings: can't create semaphore\n");
Save();
fLocker->Unlock();
return;
}
ASSERT(fSaveThread < 0);
fSaveThread = spawn_thread(_save_thread_, "Attack of the Killer Tomatoes", 7, this);
if (fSaveThread < B_OK) {
ERROR("MixerSettings: can't spawn thread\n");
delete_sem(fSaveThreadWaitSem);
fSaveThreadWaitSem = -1;
Save();
fLocker->Unlock();
return;
}
resume_thread(fSaveThread);
fSaveThreadRunning = true;
fLocker->Unlock(); fLocker->Unlock();
} }
@@ -374,6 +416,7 @@ MixerSettings::SaveThread()
} }
if (delta > SAVE_RUNTIME) { if (delta > SAVE_RUNTIME) {
fSaveThreadRunning = false;
fLocker->Unlock(); fLocker->Unlock();
break; break;
} }
@@ -10,6 +10,8 @@ public:
MixerSettings(); MixerSettings();
~MixerSettings(); ~MixerSettings();
void SetSettingsFile(const char *file);
bool AttenuateOutput(); bool AttenuateOutput();
void SetAttenuateOutput(bool yesno); void SetAttenuateOutput(bool yesno);
@@ -37,16 +39,16 @@ public:
bool RefuseInputFormatChange(); bool RefuseInputFormatChange();
void SetRefuseInputFormatChange(bool yesno); void SetRefuseInputFormatChange(bool yesno);
void SaveGain(MixerInput *input); void SaveConnectionSettings(MixerInput *input);
void LoadGain(MixerInput *input); void LoadConnectionSettings(MixerInput *input);
void SaveGain(MixerOutput *output); void SaveConnectionSettings(MixerOutput *output);
void LoadGain(MixerOutput *output); void LoadConnectionSettings(MixerOutput *output);
protected: protected:
void SaveGainSetting(const char *name, uint32 channel_mask, const float *gain, int gain_count); void SaveConnectionSettingsSetting(const char *name, uint32 channel_mask, const float *gain, int gain_count);
void LoadGainSetting(const char *name, uint32 channel_mask, float *gain, int gain_count); void LoadConnectionSettingsSetting(const char *name, uint32 channel_mask, float *gain, int gain_count);
void SaveSetting(const char *name, int value); void SaveSetting(const char *name, int value);
void LoadSetting(const char *name, int *value, int default_value = 0); void LoadSetting(const char *name, int *value, int default_value = 0);
@@ -61,11 +63,13 @@ protected:
void SaveThread(); void SaveThread();
BLocker *fLocker; BLocker *fLocker;
bool fSettingsDirty; BPath *fSettingsFile;
bigtime_t fSettingsLastChange;
thread_id fSaveThread; volatile bool fSettingsDirty;
sem_id fSaveThreadWaitSem; volatile bigtime_t fSettingsLastChange;
volatile thread_id fSaveThread;
volatile sem_id fSaveThreadWaitSem;
volatile bool fSaveThreadRunning;
struct settings struct settings
{ {
@@ -80,7 +84,7 @@ protected:
bool RefuseInputFormatChange; bool RefuseInputFormatChange;
}; };
settings fSettings; volatile settings fSettings;
}; };
#endif //_MIXER_SETTINGS_H #endif //_MIXER_SETTINGS_H