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

View File

@ -8,6 +8,8 @@
#include <TimeSource.h>
#include <ParameterWeb.h>
#include <MediaRoster.h>
#include <FindDirectory.h>
#include <Path.h>
#include <string.h>
#include <stdio.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_2 0x4af62b7d
AudioMixer::AudioMixer(BMediaAddOn *addOn)
AudioMixer::AudioMixer(BMediaAddOn *addOn, bool isSystemMixer)
: BMediaNode("Audio Mixer"),
BBufferConsumer(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.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();
}
@ -328,7 +342,10 @@ AudioMixer::Connected(const media_source &producer, const media_destination &whe
sprintf(out_input->name, "Input %ld", out_input->destination.id);
// 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();
@ -786,6 +803,9 @@ AudioMixer::Connect(status_t error, const media_source &source, const media_dest
fCore->EnableOutput(true);
fCore->SetTimingInfo(TimeSource(), fDownstreamLatency);
fCore->SetOutputBufferGroup(fBufferGroup);
fCore->Settings()->LoadConnectionSettings(fCore->Output());
fCore->Unlock();
UpdateParameterWeb();
@ -1353,6 +1373,7 @@ AudioMixer::SetParameterValue(int32 id, bigtime_t when,
goto err;
output->SetOutputChannelSourceGain(PARAM_CHAN(id), PARAM_SRC(id), PERCENT_TO_GAIN(static_cast<const float *>(value)[0]));
}
fCore->Settings()->SaveConnectionSettings(output);
} else {
MixerInput *input;
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
update = true;
}
fCore->Settings()->SaveConnectionSettings(input);
}
BroadcastNewParameterValue(when, id, const_cast<void *>(value), size);
err:

View File

@ -34,7 +34,7 @@ class AudioMixer :
public:
AudioMixer(BMediaAddOn *addOn);
AudioMixer(BMediaAddOn *addOn, bool isSystemMixer);
~AudioMixer();

View File

@ -83,7 +83,7 @@ BMediaNode *
AudioMixerAddon::InstantiateNodeFor(const flavor_info* info, BMessage* config,
status_t* out_error)
{
return new AudioMixer(this);
return new AudioMixer(this, false);
}
status_t
@ -110,11 +110,7 @@ AudioMixerAddon::AutoStart(int in_index, BMediaNode ** out_node,
return B_ERROR;
*out_internal_id = 0;
AudioMixer *mixer = new AudioMixer(this);
// disable stop on the auto started (system) mixer
mixer->DisableNodeStop();
AudioMixer *mixer = new AudioMixer(this, true);
*out_node = mixer;
return B_OK;

View File

@ -100,23 +100,23 @@ MixerCore::SetOutputAttenuation(float gain)
fOutputGain = gain;
}
bool
MixerInput *
MixerCore::AddInput(const media_input &input)
{
ASSERT_LOCKED();
if (HasKawamba())
fInputs->AddItem(new MixerInput(this, input, fMixBufferFrameRate * 1.5, fMixBufferFrameCount * 2));
else
fInputs->AddItem(new MixerInput(this, input, fMixBufferFrameRate, fMixBufferFrameCount));
return true;
MixerInput *in = new MixerInput(this, input, fMixBufferFrameRate, fMixBufferFrameCount);
fInputs->AddItem(in);
return in;
}
bool
MixerOutput *
MixerCore::AddOutput(const media_output &output)
{
ASSERT_LOCKED();
if (fOutput)
return false;
if (fOutput) {
ERROR("MixerCore::AddOutput: already connected\n");
return fOutput;
}
fOutput = new MixerOutput(this, output);
// the output format might have been adjusted inside MixerOutput
ApplyOutputFormat();
@ -124,6 +124,8 @@ MixerCore::AddOutput(const media_output &output)
ASSERT(!fRunning);
if (fStarted && fOutputEnabled)
StartMixThread();
return fOutput;
}
bool

View File

@ -29,8 +29,8 @@ public:
// the audio mixer node using SetOutputAttenuation()
void SetOutputAttenuation(float gain);
bool AddInput(const media_input &input);
bool AddOutput(const media_output &output);
MixerInput * AddInput(const media_input &input);
MixerOutput * AddOutput(const media_output &output);
bool RemoveInput(int32 inputID);
bool RemoveOutput();

View File

@ -1,5 +1,6 @@
#include <MediaDefs.h>
#include <Locker.h>
#include <Path.h>
#include <OS.h>
#include "MixerCore.h"
@ -8,15 +9,17 @@
#include "MixerSettings.h"
#include "debug.h"
#define SAVE_DELAY 8000000 // delay saving of settings for 8s
#define SAVE_RUNTIME 40000000 // stop save thread after 40s inactivity
#define SAVE_DELAY 5000000 // delay saving of settings for 5s
#define SAVE_RUNTIME 30000000 // stop save thread after 30s inactivity
MixerSettings::MixerSettings()
: fLocker(new BLocker),
fSettingsFile(0),
fSettingsDirty(false),
fSettingsLastChange(0),
fSaveThread(-1),
fSaveThreadWaitSem(-1)
fSaveThreadWaitSem(-1),
fSaveThreadRunning(false)
{
Load();
}
@ -27,6 +30,16 @@ MixerSettings::~MixerSettings()
if (fSettingsDirty)
Save();
delete fLocker;
delete fSettingsFile;
}
void
MixerSettings::SetSettingsFile(const char *file)
{
fLocker->Lock();
delete fSettingsFile;
fSettingsFile = new BPath(file);
fLocker->Unlock();
}
bool
@ -201,27 +214,29 @@ MixerSettings::SetRefuseInputFormatChange(bool yesno)
}
void
MixerSettings::SaveGain(MixerInput *input)
MixerSettings::SaveConnectionSettings(MixerInput *input)
{
StartDeferredSave();
}
void
MixerSettings::LoadConnectionSettings(MixerInput *input)
{
}
void
MixerSettings::LoadGain(MixerInput *input)
MixerSettings::SaveConnectionSettings(MixerOutput *output)
{
StartDeferredSave();
}
void
MixerSettings::LoadConnectionSettings(MixerOutput *output)
{
}
void
MixerSettings::SaveGain(MixerOutput *output)
{
}
void
MixerSettings::LoadGain(MixerOutput *output)
{
}
void
MixerSettings::SaveGainSetting(const char *name, uint32 channel_mask, const float *gain, int gain_count)
MixerSettings::SaveConnectionSettingsSetting(const char *name, uint32 channel_mask, const float *gain, int gain_count)
{
fLocker->Lock();
@ -232,7 +247,7 @@ MixerSettings::SaveGainSetting(const char *name, uint32 channel_mask, const floa
}
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();
@ -266,8 +281,15 @@ void
MixerSettings::Save()
{
fLocker->Lock();
// if we don't have a settings file, don't continue
if (!fSettingsFile) {
fLocker->Unlock();
return;
}
TRACE("MixerSettings: SAVE!\n");
// XXX work
@ -279,9 +301,7 @@ void
MixerSettings::Load()
{
fLocker->Lock();
// XXX work
// setup defaults
fSettings.AttenuateOutput = true;
fSettings.NonLinearGainSlider = true;
fSettings.UseBalanceControl = false;
@ -292,6 +312,12 @@ MixerSettings::Load()
fSettings.RefuseOutputFormatChange = false;
fSettings.RefuseInputFormatChange = false;
// if we don't have a settings file, don't continue
if (!fSettingsFile) {
fLocker->Unlock();
return;
}
fLocker->Unlock();
}
@ -299,29 +325,45 @@ void
MixerSettings::StartDeferredSave()
{
fLocker->Lock();
// if we don't have a settings file, don't save the settings
if (!fSettingsFile) {
fLocker->Unlock();
return;
}
fSettingsDirty = true;
fSettingsLastChange = system_time();
if (fSaveThread < 0) {
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;
}
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;
}
if (fSaveThreadRunning) {
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();
}
@ -374,6 +416,7 @@ MixerSettings::SaveThread()
}
if (delta > SAVE_RUNTIME) {
fSaveThreadRunning = false;
fLocker->Unlock();
break;
}

View File

@ -9,6 +9,8 @@ class MixerSettings
public:
MixerSettings();
~MixerSettings();
void SetSettingsFile(const char *file);
bool AttenuateOutput();
void SetAttenuateOutput(bool yesno);
@ -37,16 +39,16 @@ public:
bool RefuseInputFormatChange();
void SetRefuseInputFormatChange(bool yesno);
void SaveGain(MixerInput *input);
void LoadGain(MixerInput *input);
void SaveConnectionSettings(MixerInput *input);
void LoadConnectionSettings(MixerInput *input);
void SaveGain(MixerOutput *output);
void LoadGain(MixerOutput *output);
void SaveConnectionSettings(MixerOutput *output);
void LoadConnectionSettings(MixerOutput *output);
protected:
void SaveGainSetting(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 SaveConnectionSettingsSetting(const char *name, uint32 channel_mask, const 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 LoadSetting(const char *name, int *value, int default_value = 0);
@ -61,11 +63,13 @@ protected:
void SaveThread();
BLocker *fLocker;
bool fSettingsDirty;
bigtime_t fSettingsLastChange;
thread_id fSaveThread;
sem_id fSaveThreadWaitSem;
BPath *fSettingsFile;
volatile bool fSettingsDirty;
volatile bigtime_t fSettingsLastChange;
volatile thread_id fSaveThread;
volatile sem_id fSaveThreadWaitSem;
volatile bool fSaveThreadRunning;
struct settings
{
@ -80,7 +84,7 @@ protected:
bool RefuseInputFormatChange;
};
settings fSettings;
volatile settings fSettings;
};
#endif //_MIXER_SETTINGS_H