Skip to content

Commit

Permalink
First MythUI screen for the speaker test. MythUI code by Robert McNamara
Browse files Browse the repository at this point in the history
  • Loading branch information
jyavenard committed Dec 13, 2010
1 parent 9ea89aa commit 2b0eaa2
Show file tree
Hide file tree
Showing 7 changed files with 377 additions and 67 deletions.
258 changes: 192 additions & 66 deletions mythtv/programs/mythfrontend/audiosettings.cpp
Expand Up @@ -11,7 +11,6 @@
#include <QCoreApplication>
#include <QEvent>
#include <QDir>
#include <QThread>

// MythTV headers
#include "mythconfig.h"
Expand Down Expand Up @@ -462,98 +461,225 @@ bool AudioConfigSettings::CheckPassthrough()
return m_passthrough8;
}

class AudioTestThread : public QThread
void AudioConfigSettings::AudioTest()
{
QString out = m_OutputDevice->getValue();
QString name;
int channels = m_MaxAudioChannels->getValue().toInt();
QString errMsg;

MythScreenStack *mainStack = GetMythMainWindow()->GetMainStack();

SpeakerTest *st = new SpeakerTest(
mainStack, "Speaker Test", out, name, 2);
if (st->Create())
{
mainStack->AddScreen(st);
}
else
delete st;
}

QEvent::Type ChannelChangedEvent::kEventType =
(QEvent::Type) QEvent::registerEventType();

// ---------------------------------------------------


AudioTestThread::AudioTestThread(QObject *parent,
QString main, QString passthrough,
int channels) :
m_channels(channels), m_device(main), m_passthrough(passthrough),
m_interrupted(false)
{
m_parent = parent;
m_audioOutput = AudioOutput::OpenAudio(m_device,
m_passthrough,
FORMAT_S16, m_channels,
0, 48000,
AUDIOOUTPUT_VIDEO,
true, false);
}

AudioTestThread::~AudioTestThread()
{
cancel();
wait();
if (m_audioOutput)
delete m_audioOutput;
}

QString AudioTestThread::result()
{
QString errMsg;
if (!m_audioOutput)
errMsg = QObject::tr("Unable to create AudioOutput.");
else
errMsg = m_audioOutput->GetError();
return errMsg;
}

void AudioTestThread::cancel()
{
m_interrupted = true;
}

void AudioTestThread::run()
{
public:
void run()
m_interrupted = false;

if (m_audioOutput)
{
char *frames_in = new char[m_channels * 48000 * sizeof(int16_t) + 15];
char *frames = (char *)(((long)frames_in + 15) & ~0xf);
while (!m_interrupted)
{
char *frames_in = new char[m_channels * 48000 * sizeof(int16_t) + 15];
char *frames = (char *)(((long)frames_in + 15) & ~0xf);
for (int i = 0; i < m_channels; i++)
for (int i = 0; i < m_channels && !m_interrupted; i++)
{
AudioOutputUtil::GeneratePinkSamples(frames, m_channels,
i, 48000);
if (m_parent)
{
QString channel;

switch(i)
{
case 0:
channel = "frontleft";
break;
case 1:
channel = "frontright";
break;
case 2:
channel = "center";
break;
case 3:
channel = "lfe";
break;
case 4:
if (m_channels == 6)
channel = "leftsurround";
else
channel = "rearleft";
break;
case 5:
if (m_channels == 6)
channel = "rightsurround";
else
channel = "rearleft";
break;
case 6:
channel = "leftsurround";
break;
case 7:
channel = "rightsurround";
break;
}
QCoreApplication::postEvent(
m_parent, new ChannelChangedEvent(channel));
}
if (!m_audioOutput->AddFrames(frames, 48000, -1))
{
VERBOSE(VB_AUDIO, "AddAudioData() "
"Audio buffer overflow, audio data lost!");
}
//if (m_dialog)
for (int j = 0; j < 16 && !m_interrupted; j++)
{
// Send event here
//QApplication::postEvent(m_dialog, NULL);
usleep(62500); //1/16th of a second
}
sleep(1);
usleep(500000);
usleep(500000); //.5s
}

delete[] frames_in;
}
QString result()
{
QString errMsg;

if (!m_audioOutput)
errMsg = QObject::tr("Unable to create AudioOutput.");
else
errMsg = m_audioOutput->GetError();
return errMsg;
}
AudioTestThread(QString main, QString pass, int channels)
: m_channels(channels)
{
m_audioOutput = AudioOutput::OpenAudio(main,
pass,
FORMAT_S16, channels,
0, 48000,
AUDIOOUTPUT_VIDEO,
true, false);
}
~AudioTestThread()
{
if (m_audioOutput)
delete m_audioOutput;
}

private:
AudioOutput *m_audioOutput;
int m_channels;
};

void AudioConfigSettings::AudioTest()
delete[] frames_in;
}
}

SpeakerTest::SpeakerTest(MythScreenStack *parent, QString name,
QString main, QString passthrough, int channels)
: MythScreenType(parent, name),
m_speakerLocation(NULL), m_testButton(NULL), m_testSpeakers(NULL)
{
QString out = m_OutputDevice->getValue();
QString name;
int channels = m_MaxAudioChannels->getValue().toInt();
QString errMsg;
m_testSpeakers = new AudioTestThread(this, main, passthrough, channels);
}

if (gCoreContext->GetNumSetting("PassThruDeviceOverride", false))
bool SpeakerTest::Create()
{
bool foundtheme = false;

// Load the theme for this screen
foundtheme = LoadWindowFromXML("config-ui.xml", "audiosettings", this);

if (!foundtheme)
return false;

if (!m_testSpeakers->result().isEmpty())
{
name = gCoreContext->GetSetting("PassThruOutputDevice");
VERBOSE(VB_IMPORTANT, "Not working.");
return false;
}
AudioTestThread *att = new AudioTestThread(out, name, channels);

QString result = att->result();
if (!result.isEmpty())
m_testButton = dynamic_cast<MythUIButton *> (GetChild("test"));
m_speakerLocation = dynamic_cast<MythUIStateType *> (GetChild("speakerlocation"));

if (!m_testButton || !m_speakerLocation)
{
MythPopupBox::showOkPopup(
GetMythMainWindow(), QObject::tr("Error"), errMsg);
delete att;
att = NULL;
VERBOSE(VB_IMPORTANT, "Theme is missing critical theme elements.");
return false;
}
else

connect(m_testButton, SIGNAL(Clicked()), this, SLOT(toggleTest()));

BuildFocusList();

return true;
}

SpeakerTest::~SpeakerTest()
{
if (m_testSpeakers)
{
// set MythUI recipient here
//att->setUIWindow(NULL);
att->start();
m_testSpeakers->cancel();
m_testSpeakers->wait();
delete m_testSpeakers;
m_testSpeakers = NULL;
}
if (att && att->wait())
}

void SpeakerTest::toggleTest(void)
{
if (m_testSpeakers->isRunning())
m_testSpeakers->cancel();
else if (m_testSpeakers)
m_testSpeakers->start();
}

bool SpeakerTest::keyPressEvent(QKeyEvent *event)
{
if (GetFocusWidget()->keyPressEvent(event))
return true;

bool handled = false;

if (!handled && MythScreenType::keyPressEvent(event))
handled = true;

return handled;
}

void SpeakerTest::customEvent(QEvent *event)
{
if (event->type() == ChannelChangedEvent::kEventType)
{
delete att;
ChannelChangedEvent *cce = (ChannelChangedEvent*)(event);

QString channel = cce->channel;

if (!channel.isEmpty())
m_speakerLocation->DisplayState(channel);
}
}

static HostCheckBox *MythControlsVolume()
HostCheckBox *AudioMixerSettings::MythControlsVolume()
{
HostCheckBox *gc = new HostCheckBox("MythControlsVolume");
gc->setLabel(QObject::tr("Use internal volume controls"));
Expand Down
71 changes: 70 additions & 1 deletion mythtv/programs/mythfrontend/audiosettings.h
Expand Up @@ -2,12 +2,20 @@
#define MYTHAUDIOSETTINGS_H

#include <QStringList>

#include <QObject>
#include <QMutex>
#include <QThread>

#include "settings.h"
#include "mythcontext.h"

#include <QMutex>
// libmythui
#include <mythuibutton.h>
#include <mythuistatetype.h>
#include <mythscreentype.h>
#include <mythdialogbox.h>

#include "audiooutput.h"

class AudioDeviceComboBox;
Expand Down Expand Up @@ -78,6 +86,7 @@ class AudioMixerSettings : public TriggeredConfigurationGroup
public:
AudioMixerSettings();
private:
HostCheckBox *MythControlsVolume();
HostComboBox *MixerDevice();
HostComboBox *MixerControl();
HostSlider *MixerVolume();
Expand Down Expand Up @@ -113,4 +122,64 @@ class AudioAdvancedSettingsGroup : public ConfigurationWizard
AudioAdvancedSettingsGroup(bool mpcm);
};

class ChannelChangedEvent : public QEvent
{
public:
ChannelChangedEvent(QString channame) :
QEvent(kEventType),
channel(channame) {}
~ChannelChangedEvent() {}

QString channel;

static Type kEventType;
};

class AudioTestThread : public QThread
{
public:

AudioTestThread(QObject *parent, QString main, QString passthrough,
int channels);
~AudioTestThread();

void cancel();
QString result();

protected:
void run();

private:
QObject *m_parent;
AudioOutput *m_audioOutput;
int m_channels;
QString m_device;
QString m_passthrough;
bool m_interrupted;
};

class SpeakerTest : public MythScreenType
{
Q_OBJECT

public:

SpeakerTest(MythScreenStack *parent, QString name,
QString main, QString passthrough, int channels);
~SpeakerTest();

bool Create(void);
bool keyPressEvent(QKeyEvent *);
void customEvent(QEvent *event);

private:
MythUIStateType *m_speakerLocation;
MythUIButton *m_testButton;

AudioTestThread *m_testSpeakers;

private slots:
void toggleTest(void);
};

#endif

0 comments on commit 2b0eaa2

Please sign in to comment.