/*
* Copyright (C) 2015 Canonical, Ltd.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3, as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranties of
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see .
*
* Author: Xavi Garcia
*/
#include "indicator-sound-test-base.h"
#include "dbus_menus_interface.h"
#include "dbus_properties_interface.h"
#include "dbus_accounts_interface.h"
#include "dbus_accountssound_interface.h"
#include "dbus-types.h"
#include
#include
#include "utils/dbus-pulse-volume.h"
using namespace QtDBusTest;
using namespace QtDBusMock;
using namespace std;
using namespace testing;
namespace mh = unity::gmenuharness;
IndicatorSoundTestBase::IndicatorSoundTestBase() :
dbusMock(dbusTestRunner)
{
}
IndicatorSoundTestBase::~IndicatorSoundTestBase()
{
}
bool IndicatorSoundTestBase::setStreamRestoreVolume(QString const &role, double volume)
{
QProcess setVolume;
setVolume.start(VOLUME_SET_BIN, QStringList()
<< role
<< QString("%1").arg(volume));
if (!setVolume.waitForStarted())
return false;
if (!setVolume.waitForFinished())
return false;
return setVolume.exitCode() == 0;
}
bool IndicatorSoundTestBase::setSinkVolume(double volume)
{
QString volume_percentage = QString("%1\%").arg(volume*100);
QProcess setVolume;
setVolume.start("pactl", QStringList()
<< "-s"
<< "127.0.0.1"
<< "set-sink-volume"
<< "0"
<< volume_percentage);
if (!setVolume.waitForStarted())
return false;
if (!setVolume.waitForFinished())
return false;
return setVolume.exitCode() == 0;
}
bool IndicatorSoundTestBase::clearGSettingsPlayers()
{
QProcess clearPlayers;
clearPlayers.start("gsettings", QStringList()
<< "set"
<< "com.canonical.indicator.sound"
<< "interested-media-players"
<< "[]");
if (!clearPlayers.waitForStarted())
return false;
if (!clearPlayers.waitForFinished())
return false;
return clearPlayers.exitCode() == 0;
}
bool IndicatorSoundTestBase::startTestMprisPlayer(QString const& playerName)
{
testPlayer1.terminate();
testPlayer1.start(MEDIA_PLAYER_MPRIS_BIN, QStringList()
<< playerName);
if (!testPlayer1.waitForStarted())
return false;
return true;
}
bool IndicatorSoundTestBase::setTestMprisPlayerProperty(QString const &testPlayer, QString const &property, bool value)
{
QProcess setProperty;
QString strValue;
strValue = value ? "true" : "false";
setProperty.start(MEDIA_PLAYER_MPRIS_UPDATE_BIN, QStringList()
<< testPlayer
<< property
<< strValue);
if (!setProperty.waitForStarted())
return false;
if (!setProperty.waitForFinished())
return false;
return setProperty.exitCode() == 0;
}
bool IndicatorSoundTestBase::startTestSound(QString const &role)
{
testSoundProcess.terminate();
testSoundProcess.start("paplay", QStringList()
<< "-s"
<< "127.0.0.1"
<< TEST_SOUND
<< QString("--property=media.role=%1").arg(role));
if (!testSoundProcess.waitForStarted())
return false;
return true;
}
void IndicatorSoundTestBase::stopTestSound()
{
testSoundProcess.terminate();
}
void IndicatorSoundTestBase::startPulseDesktop()
{
try
{
pulseaudio.reset(
new QProcessDBusService(DBusTypes::DBUS_PULSE,
QDBusConnection::SessionBus,
"pulseaudio",
QStringList() << "--start"
<< "-vvvv"
<< "--disable-shm=true"
<< "--daemonize=false"
<< "--use-pid-file=false"
<< "--system=false"
<< "--exit-idle-time=-1"
<< "-n"
<< "--load=module-null-sink"
<< "--log-target=file:/tmp/pulse-daemon.log"
<< "--load=module-dbus-protocol"
<< "--load=module-native-protocol-tcp auth-ip-acl=127.0.0.1"
));
pulseaudio->start(dbusTestRunner.sessionConnection());
}
catch (exception const& e)
{
cout << "pulseaudio(): " << e.what() << endl;
throw;
}
}
void IndicatorSoundTestBase::startPulsePhone()
{
try
{
pulseaudio.reset(
new QProcessDBusService(DBusTypes::DBUS_PULSE,
QDBusConnection::SessionBus,
"pulseaudio",
QStringList() << "--start"
<< "-vvvv"
<< "--disable-shm=true"
<< "--daemonize=false"
<< "--use-pid-file=false"
<< "--system=false"
<< "--exit-idle-time=-1"
<< "-n"
<< "--load=module-null-sink"
<< "--log-target=file:/tmp/pulse-daemon.log"
<< QString("--load=module-stream-restore restore_device=false restore_muted=false fallback_table=%1").arg(STREAM_RESTORE_TABLE)
<< "--load=module-dbus-protocol"
<< "--load=module-native-protocol-tcp auth-ip-acl=127.0.0.1"
));
pulseaudio->start(dbusTestRunner.sessionConnection());
}
catch (exception const& e)
{
cout << "pulseaudio(): " << e.what() << endl;
throw;
}
}
void IndicatorSoundTestBase::startAccountsService()
{
try
{
accountsService.reset(
new QProcessDBusService(DBusTypes::ACCOUNTS_SERVICE,
QDBusConnection::SystemBus,
ACCOUNTS_SERVICE_BIN,
QStringList()));
accountsService->start(dbusTestRunner.systemConnection());
initializeAccountsInterface();
}
catch (exception const& e)
{
cout << "accountsService(): " << e.what() << endl;
throw;
}
}
void IndicatorSoundTestBase::startIndicator()
{
try
{
setenv("PULSE_SERVER", "127.0.0.1", true);
indicator.reset(
new QProcessDBusService(DBusTypes::DBUS_NAME,
QDBusConnection::SessionBus,
SOUND_SERVICE_BIN,
QStringList()));
indicator->start(dbusTestRunner.sessionConnection());
}
catch (exception const& e)
{
cout << "startIndicator(): " << e.what() << endl;
throw;
}
}
mh::MenuMatcher::Parameters IndicatorSoundTestBase::desktopParameters()
{
return mh::MenuMatcher::Parameters(
"com.canonical.indicator.sound",
{ { "indicator", "/com/canonical/indicator/sound" } },
"/com/canonical/indicator/sound/desktop");
}
mh::MenuMatcher::Parameters IndicatorSoundTestBase::phoneParameters()
{
return mh::MenuMatcher::Parameters(
"com.canonical.indicator.sound",
{ { "indicator", "/com/canonical/indicator/sound" } },
"/com/canonical/indicator/sound/phone");
}
void IndicatorSoundTestBase::SetUp()
{
setenv("XDG_DATA_DIRS", XDG_DATA_DIRS, true);
setenv("DBUS_SYSTEM_BUS_ADDRESS", dbusTestRunner.systemBus().toStdString().c_str(), true);
}
void IndicatorSoundTestBase::TearDown()
{
unsetenv("XDG_DATA_DIRS");
unsetenv("PULSE_SERVER");
unsetenv("DBUS_SYSTEM_BUS_ADDRESS");
}
void gvariant_deleter(GVariant* varptr)
{
if (varptr != nullptr)
{
g_variant_unref(varptr);
}
}
std::shared_ptr IndicatorSoundTestBase::volume_variant(double volume)
{
GVariantBuilder builder;
g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT);
g_variant_builder_add(&builder,
"{sv}",
"title",
g_variant_new_string("_Sound"));
g_variant_builder_add(&builder,
"{sv}",
"accessible-desc",
g_variant_new_string("_Sound"));
auto icon = g_themed_icon_new("icon");
g_variant_builder_add(&builder,
"{sv}",
"icon",
g_icon_serialize(icon));
g_variant_builder_add(&builder,
"{sv}",
"visible",
g_variant_new_boolean(true));
return shared_ptr(g_variant_builder_end(&builder), &gvariant_deleter);
}
unity::gmenuharness::MenuItemMatcher IndicatorSoundTestBase::volumeSlider(double volume)
{
return mh::MenuItemMatcher().radio()
.label("Volume")
.round_doubles(0.1)
.int32_attribute("target", 0)
.double_attribute("min-value", 0.0)
.double_attribute("max-value", 1.0)
.double_attribute("step", 0.01)
.string_attribute("x-canonical-type", "com.canonical.unity.slider")
.themed_icon("max-icon", {"audio-volume-high-panel", "audio-volume-high", "audio-volume", "audio"})
.themed_icon("min-icon", {"audio-volume-low-zero-panel", "audio-volume-low-zero", "audio-volume-low", "audio-volume", "audio"})
.pass_through_double_attribute("action", volume);
}
unity::gmenuharness::MenuItemMatcher IndicatorSoundTestBase::silentModeSwitch(bool toggled)
{
return mh::MenuItemMatcher::checkbox()
.label("Silent Mode")
.action("indicator.silent-mode")
.toggled(toggled);
}
bool IndicatorSoundTestBase::waitMenuChange()
{
if (signal_spy_menu_changed_)
{
return signal_spy_menu_changed_->wait();
}
return false;
}
bool IndicatorSoundTestBase::initializeMenuChangedSignal()
{
if (!menu_interface_)
{
menu_interface_.reset(new MenusInterface("com.canonical.indicator.sound",
"/com/canonical/indicator/sound",
dbusTestRunner.sessionConnection(), 0));
}
if (menu_interface_)
{
qDebug() << "Waiting for signal";
signal_spy_menu_changed_.reset(new QSignalSpy(menu_interface_.get(), &MenusInterface::Changed));
}
if (!menu_interface_ || !signal_spy_menu_changed_)
{
return false;
}
return true;
}
bool IndicatorSoundTestBase::waitVolumeChangedInIndicator()
{
if (signal_spy_volume_changed_)
{
return signal_spy_volume_changed_->wait();
}
return false;
}
void IndicatorSoundTestBase::initializeAccountsInterface()
{
auto username = qgetenv("USER");
if (username != "")
{
std::unique_ptr accountsInterface(new AccountsInterface("org.freedesktop.Accounts",
"/org/freedesktop/Accounts",
dbusTestRunner.systemConnection(), 0));
QDBusReply userResp = accountsInterface->call(QLatin1String("FindUserByName"),
QLatin1String(username));
if (!userResp.isValid())
{
qWarning() << "SetVolume::initializeAccountsInterface(): D-Bus error: " << userResp.error().message();
}
auto userPath = userResp.value().path();
if (userPath != "")
{
std::unique_ptr soundInterface(new AccountsSoundInterface("org.freedesktop.Accounts",
userPath,
dbusTestRunner.systemConnection(), 0));
accounts_interface_.reset(new DBusPropertiesInterface("org.freedesktop.Accounts",
userPath,
dbusTestRunner.systemConnection(), 0));
if (!accounts_interface_->isValid())
{
qWarning() << "SetVolume::initializeAccountsInterface(): D-Bus error: " << accounts_interface_->lastError().message();
}
signal_spy_volume_changed_.reset(new QSignalSpy(accounts_interface_.get(),&DBusPropertiesInterface::PropertiesChanged));
}
}
}