aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt21
-rw-r--r--src/gmenuharness/CMakeLists.txt17
-rw-r--r--src/gmenuharness/MatchResult.cpp187
-rw-r--r--src/gmenuharness/MatchUtils.cpp77
-rw-r--r--src/gmenuharness/MenuItemMatcher.cpp1008
-rw-r--r--src/gmenuharness/MenuMatcher.cpp208
-rw-r--r--src/service.vala407
-rw-r--r--src/sound-menu.vala38
-rw-r--r--src/volume-control-pulse.vala83
-rw-r--r--src/volume-control.vala14
10 files changed, 75 insertions, 1985 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 6c621ae..194dfc9 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -8,12 +8,12 @@ set(SYMBOLS_PATH "${CMAKE_CURRENT_BINARY_DIR}/indicator-sound-service.def")
set(VAPI_PATH "${CMAKE_CURRENT_BINARY_DIR}/indicator-sound-service.vapi")
vapi_gen(accounts-service
- LIBRARY
- accounts-service
- PACKAGES
- gio-2.0
- INPUT
- /usr/share/gir-1.0/AccountsService-1.0.gir
+ LIBRARY
+ accounts-service
+ PACKAGES
+ gio-2.0
+ INPUT
+ /usr/share/gir-1.0/AccountsService-1.0.gir
)
vala_init(indicator-sound-service
@@ -70,7 +70,7 @@ vala_add(indicator-sound-service
media-player-user.vala
DEPENDS
media-player
- accounts-service-sound-settings
+ accounts-service-sound-settings
greeter-broadcast
)
vala_add(indicator-sound-service
@@ -103,7 +103,6 @@ vala_add(indicator-sound-service
sound-menu.vala
DEPENDS
media-player
- volume-control
)
vala_add(indicator-sound-service
accounts-service-user.vala
@@ -165,8 +164,8 @@ add_definitions(
)
add_library(
- indicator-sound-service-lib STATIC
- ${INDICATOR_SOUND_SOURCES}
+ indicator-sound-service-lib STATIC
+ ${INDICATOR_SOUND_SOURCES}
)
target_link_libraries(
@@ -207,5 +206,3 @@ install(
RUNTIME DESTINATION ${CMAKE_INSTALL_LIBEXECDIR}/indicator-sound/
)
-# Disable integration tests
-# add_subdirectory(gmenuharness)
diff --git a/src/gmenuharness/CMakeLists.txt b/src/gmenuharness/CMakeLists.txt
deleted file mode 100644
index c9e613a..0000000
--- a/src/gmenuharness/CMakeLists.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-pkg_check_modules(UNITY_API libunity-api>=0.1.3 REQUIRED)
-include_directories(${UNITY_API_INCLUDE_DIRS})
-
-include_directories("${CMAKE_SOURCE_DIR}/include")
-
-add_library(
- gmenuharness-shared SHARED
- MatchResult.cpp
- MatchUtils.cpp
- MenuItemMatcher.cpp
- MenuMatcher.cpp
-)
-
-target_link_libraries(
- gmenuharness-shared
- ${GLIB_LDFLAGS}
-)
diff --git a/src/gmenuharness/MatchResult.cpp b/src/gmenuharness/MatchResult.cpp
deleted file mode 100644
index 40629aa..0000000
--- a/src/gmenuharness/MatchResult.cpp
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * Copyright © 2014 Canonical Ltd.
- *
- * This program is free software: you can redistribute it and/or modify it
- * under the terms of the GNU Lesser 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 warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- * Authored by: Pete Woods <pete.woods@canonical.com>
- */
-
-#include <unity/gmenuharness/MatchResult.h>
-
-#include <chrono>
-#include <map>
-#include <sstream>
-#include <iostream>
-
-using namespace std;
-
-namespace unity
-{
-
-namespace gmenuharness
-{
-
-namespace
-{
-
-
-static void printLocation(ostream& ss, const vector<unsigned int>& location, bool first)
-{
- for (int i : location)
- {
- ss << " ";
- if (first)
- {
- ss << i;
- }
- else
- {
- ss << " ";
- }
- }
- ss << " ";
-}
-
-struct compare_vector
-{
- bool operator()(const vector<unsigned int>& a,
- const vector<unsigned int>& b) const
- {
- auto p1 = a.begin();
- auto p2 = b.begin();
-
- while (p1 != a.end())
- {
- if (p2 == b.end())
- {
- return false;
- }
- if (*p2 > *p1)
- {
- return true;
- }
- if (*p1 > *p2)
- {
- return false;
- }
-
- ++p1;
- ++p2;
- }
-
- if (p2 != b.end())
- {
- return true;
- }
-
- return false;
- }
-};
-}
-
-struct MatchResult::Priv
-{
- bool m_success = true;
-
- map<vector<unsigned int>, vector<string>, compare_vector> m_failures;
-
- chrono::time_point<chrono::system_clock> m_timeout = chrono::system_clock::now() + chrono::seconds(10);
-};
-
-MatchResult::MatchResult() :
- p(new Priv)
-{
-}
-
-MatchResult::MatchResult(MatchResult&& other)
-{
- *this = move(other);
-}
-
-MatchResult::MatchResult(const MatchResult& other) :
- p(new Priv)
-{
- *this = other;
-}
-
-MatchResult& MatchResult::operator=(const MatchResult& other)
-{
- p->m_success = other.p->m_success;
- p->m_failures= other.p->m_failures;
- return *this;
-}
-
-MatchResult& MatchResult::operator=(MatchResult&& other)
-{
- p = move(other.p);
- return *this;
-}
-
-MatchResult MatchResult::createChild() const
-{
- MatchResult child;
- child.p->m_timeout = p->m_timeout;
- return child;
-}
-
-void MatchResult::failure(const vector<unsigned int>& location, const string& message)
-{
- p->m_success = false;
- auto it = p->m_failures.find(location);
- if (it == p->m_failures.end())
- {
- it = p->m_failures.insert(make_pair(location, vector<string>())).first;
- }
- it->second.emplace_back(message);
-}
-
-void MatchResult::merge(const MatchResult& other)
-{
- p->m_success &= other.p->m_success;
- for (const auto& e : other.p->m_failures)
- {
- p->m_failures.insert(make_pair(e.first, e.second));
- }
-}
-
-bool MatchResult::success() const
-{
- return p->m_success;
-}
-
-bool MatchResult::hasTimedOut() const
-{
- auto now = chrono::system_clock::now();
- return (now >= p->m_timeout);
-}
-
-string MatchResult::concat_failures() const
-{
- stringstream ss;
- ss << "Failed expectations:" << endl;
- for (const auto& failure : p->m_failures)
- {
- bool first = true;
- for (const string& s: failure.second)
- {
- printLocation(ss, failure.first, first);
- first = false;
- ss << s << endl;
- }
- }
- return ss.str();
-}
-
-} // namespace gmenuharness
-
-} // namespace unity
diff --git a/src/gmenuharness/MatchUtils.cpp b/src/gmenuharness/MatchUtils.cpp
deleted file mode 100644
index 7b87a25..0000000
--- a/src/gmenuharness/MatchUtils.cpp
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright © 2014 Canonical Ltd.
- *
- * This program is free software: you can redistribute it and/or modify it
- * under the terms of the GNU Lesser 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 warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- * Authored by: Pete Woods <pete.woods@canonical.com>
- */
-
-#include <unity/gmenuharness/MatchUtils.h>
-
-#include <unity/util/ResourcePtr.h>
-
-using namespace std;
-namespace util = unity::util;
-
-namespace unity
-{
-
-namespace gmenuharness
-{
-
-void waitForCore (GObject * obj, const string& signalName, unsigned int timeout) {
- shared_ptr<GMainLoop> loop(g_main_loop_new(nullptr, false), &g_main_loop_unref);
-
- /* Our two exit criteria */
- util::ResourcePtr<gulong, function<void(gulong)>> signal(
- g_signal_connect_swapped(obj, signalName.c_str(),
- G_CALLBACK(g_main_loop_quit), loop.get()),
- [obj](gulong s)
- {
- g_signal_handler_disconnect(obj, s);
- });
-
- util::ResourcePtr<guint, function<void(guint)>> timer(g_timeout_add(timeout,
- [](gpointer user_data) -> gboolean
- {
- g_main_loop_quit((GMainLoop *)user_data);
- return G_SOURCE_CONTINUE;
- },
- loop.get()),
- &g_source_remove);
-
- /* Wait for sync */
- g_main_loop_run(loop.get());
-}
-
-void menuWaitForItems(const shared_ptr<GMenuModel>& menu, unsigned int timeout)
-{
- waitForCore(G_OBJECT(menu.get()), "items-changed", timeout);
-}
-
-void g_object_deleter(gpointer object)
-{
- g_clear_object(&object);
-}
-
-void gvariant_deleter(GVariant* varptr)
-{
- if (varptr != nullptr)
- {
- g_variant_unref(varptr);
- }
-}
-
-} // namespace gmenuharness
-
-} // namespace unity
diff --git a/src/gmenuharness/MenuItemMatcher.cpp b/src/gmenuharness/MenuItemMatcher.cpp
deleted file mode 100644
index f39acef..0000000
--- a/src/gmenuharness/MenuItemMatcher.cpp
+++ /dev/null
@@ -1,1008 +0,0 @@
-/*
- * Copyright © 2014 Canonical Ltd.
- *
- * This program is free software: you can redistribute it and/or modify it
- * under the terms of the GNU Lesser 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 warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- * Authored by: Pete Woods <pete.woods@canonical.com>
- */
-
-#include <unity/gmenuharness/MatchResult.h>
-#include <unity/gmenuharness/MatchUtils.h>
-#include <unity/gmenuharness/MenuItemMatcher.h>
-
-#include <iostream>
-#include <vector>
-#include <map>
-
-using namespace std;
-
-namespace unity
-{
-
-namespace gmenuharness
-{
-
-namespace
-{
-
-enum class LinkType
-{
- any,
- section,
- submenu
-};
-
-static string bool_to_string(bool value)
-{
- return value? "true" : "false";
-}
-
-static shared_ptr<GVariant> get_action_group_attribute(const shared_ptr<GActionGroup>& actionGroup, const gchar* attribute)
-{
- shared_ptr<GVariant> value(
- g_action_group_get_action_state(actionGroup.get(), attribute),
- &gvariant_deleter);
- return value;
-}
-
-static shared_ptr<GVariant> get_attribute(const shared_ptr<GMenuItem> menuItem, const gchar* attribute)
-{
- shared_ptr<GVariant> value(
- g_menu_item_get_attribute_value(menuItem.get(), attribute, nullptr),
- &gvariant_deleter);
- return value;
-}
-
-static string get_string_attribute(const shared_ptr<GMenuItem> menuItem, const gchar* attribute)
-{
- string result;
- char* temp = nullptr;
- if (g_menu_item_get_attribute(menuItem.get(), attribute, "s", &temp))
- {
- result = temp;
- g_free(temp);
- }
- return result;
-}
-
-static pair<string, string> split_action(const string& action)
-{
- auto index = action.find('.');
-
- if (index == string::npos)
- {
- return make_pair(string(), action);
- }
-
- return make_pair(action.substr(0, index), action.substr(index + 1, action.size()));
-}
-
-static string type_to_string(MenuItemMatcher::Type type)
-{
- switch(type)
- {
- case MenuItemMatcher::Type::plain:
- return "plain";
- case MenuItemMatcher::Type::checkbox:
- return "checkbox";
- case MenuItemMatcher::Type::radio:
- return "radio";
- }
-
- return string();
-}
-}
-
-struct MenuItemMatcher::Priv
-{
- void all(MatchResult& matchResult, const vector<unsigned int>& location,
- const shared_ptr<GMenuModel>& menu,
- map<string, shared_ptr<GActionGroup>>& actions)
- {
- int count = g_menu_model_get_n_items(menu.get());
-
- if (m_items.size() != (unsigned int) count)
- {
- matchResult.failure(
- location,
- "Expected " + to_string(m_items.size())
- + " children, but found " + to_string(count));
- return;
- }
-
- for (size_t i = 0; i < m_items.size(); ++i)
- {
- const auto& matcher = m_items.at(i);
- matcher.match(matchResult, location, menu, actions, i);
- }
- }
-
- void startsWith(MatchResult& matchResult, const vector<unsigned int>& location,
- const shared_ptr<GMenuModel>& menu,
- map<string, shared_ptr<GActionGroup>>& actions)
- {
- int count = g_menu_model_get_n_items(menu.get());
- if (m_items.size() > (unsigned int) count)
- {
- matchResult.failure(
- location,
- "Expected at least " + to_string(m_items.size())
- + " children, but found " + to_string(count));
- return;
- }
-
- for (size_t i = 0; i < m_items.size(); ++i)
- {
- const auto& matcher = m_items.at(i);
- matcher.match(matchResult, location, menu, actions, i);
- }
- }
-
- void endsWith(MatchResult& matchResult, const vector<unsigned int>& location,
- const shared_ptr<GMenuModel>& menu,
- map<string, shared_ptr<GActionGroup>>& actions)
- {
- int count = g_menu_model_get_n_items(menu.get());
- if (m_items.size() > (unsigned int) count)
- {
- matchResult.failure(
- location,
- "Expected at least " + to_string(m_items.size())
- + " children, but found " + to_string(count));
- return;
- }
-
- // match the last N items
- size_t j;
- for (size_t i = count - m_items.size(), j = 0; i < count && j < m_items.size(); ++i, ++j)
- {
- const auto& matcher = m_items.at(j);
- matcher.match(matchResult, location, menu, actions, i);
- }
- }
-
- Type m_type = Type::plain;
-
- Mode m_mode = Mode::all;
-
- LinkType m_linkType = LinkType::any;
-
- shared_ptr<size_t> m_expectedSize;
-
- shared_ptr<string> m_label;
-
- shared_ptr<string> m_icon;
-
- map<shared_ptr<string>, vector<std::string>> m_themed_icons;
-
- shared_ptr<string> m_action;
-
- vector<std::string> m_state_icons;
-
- vector<pair<string, shared_ptr<GVariant>>> m_attributes;
-
- vector<string> m_not_exist_attributes;
-
- vector<pair<string, shared_ptr<GVariant>>> m_pass_through_attributes;
-
- shared_ptr<bool> m_isToggled;
-
- vector<MenuItemMatcher> m_items;
-
- vector<pair<string, shared_ptr<GVariant>>> m_activations;
-
- vector<pair<string, shared_ptr<GVariant>>> m_setActionStates;
-
- double m_maxDifference = 0.0;
-};
-
-MenuItemMatcher MenuItemMatcher::checkbox()
-{
- MenuItemMatcher matcher;
- matcher.type(Type::checkbox);
- return matcher;
-}
-
-MenuItemMatcher MenuItemMatcher::radio()
-{
- MenuItemMatcher matcher;
- matcher.type(Type::radio);
- return matcher;
-}
-
-MenuItemMatcher::MenuItemMatcher() :
- p(new Priv)
-{
-}
-
-MenuItemMatcher::~MenuItemMatcher()
-{
-}
-
-MenuItemMatcher::MenuItemMatcher(const MenuItemMatcher& other) :
- p(new Priv)
-{
- *this = other;
-}
-
-MenuItemMatcher::MenuItemMatcher(MenuItemMatcher&& other)
-{
- *this = move(other);
-}
-
-MenuItemMatcher& MenuItemMatcher::operator=(const MenuItemMatcher& other)
-{
- p->m_type = other.p->m_type;
- p->m_mode = other.p->m_mode;
- p->m_expectedSize = other.p->m_expectedSize;
- p->m_label = other.p->m_label;
- p->m_icon = other.p->m_icon;
- p->m_themed_icons = other.p->m_themed_icons;
- p->m_action = other.p->m_action;
- p->m_state_icons = other.p->m_state_icons;
- p->m_attributes = other.p->m_attributes;
- p->m_not_exist_attributes = other.p->m_not_exist_attributes;
- p->m_pass_through_attributes = other.p->m_pass_through_attributes;
- p->m_isToggled = other.p->m_isToggled;
- p->m_linkType = other.p->m_linkType;
- p->m_items = other.p->m_items;
- p->m_activations = other.p->m_activations;
- p->m_setActionStates = other.p->m_setActionStates;
- p->m_maxDifference = other.p->m_maxDifference;
- return *this;
-}
-
-MenuItemMatcher& MenuItemMatcher::operator=(MenuItemMatcher&& other)
-{
- p = move(other.p);
- return *this;
-}
-
-MenuItemMatcher& MenuItemMatcher::type(Type type)
-{
- p->m_type = type;
- return *this;
-}
-
-MenuItemMatcher& MenuItemMatcher::label(const string& label)
-{
- p->m_label = make_shared<string>(label);
- return *this;
-}
-
-MenuItemMatcher& MenuItemMatcher::action(const string& action)
-{
- p->m_action = make_shared<string>(action);
- return *this;
-}
-
-MenuItemMatcher& MenuItemMatcher::state_icons(const std::vector<std::string>& state_icons)
-{
- p->m_state_icons = state_icons;
- return *this;
-}
-
-MenuItemMatcher& MenuItemMatcher::icon(const string& icon)
-{
- p->m_icon = make_shared<string>(icon);
- return *this;
-}
-
-MenuItemMatcher& MenuItemMatcher::themed_icon(const std::string& iconName, const std::vector<std::string>& icons)
-{
- p->m_themed_icons[make_shared<string>(iconName)] = icons;
- return *this;
-}
-
-MenuItemMatcher& MenuItemMatcher::widget(const string& widget)
-{
- return string_attribute("x-canonical-type", widget);
-}
-
-MenuItemMatcher& MenuItemMatcher::pass_through_attribute(const string& actionName, const shared_ptr<GVariant>& value)
-{
- p->m_pass_through_attributes.emplace_back(actionName, value);
- return *this;
-}
-
-MenuItemMatcher& MenuItemMatcher::pass_through_boolean_attribute(const string& actionName, bool value)
-{
- return pass_through_attribute(
- actionName,
- shared_ptr<GVariant>(g_variant_new_boolean(value),
- &gvariant_deleter));
-}
-
-MenuItemMatcher& MenuItemMatcher::pass_through_string_attribute(const string& actionName, const string& value)
-{
- return pass_through_attribute(
- actionName,
- shared_ptr<GVariant>(g_variant_new_string(value.c_str()),
- &gvariant_deleter));
-}
-
-MenuItemMatcher& MenuItemMatcher::pass_through_double_attribute(const std::string& actionName, double value)
-{
- return pass_through_attribute(
- actionName,
- shared_ptr<GVariant>(g_variant_new_double(value),
- &gvariant_deleter));
-}
-
-MenuItemMatcher& MenuItemMatcher::round_doubles(double maxDifference)
-{
- p->m_maxDifference = maxDifference;
- return *this;
-}
-
-MenuItemMatcher& MenuItemMatcher::attribute(const string& name, const shared_ptr<GVariant>& value)
-{
- p->m_attributes.emplace_back(name, value);
- return *this;
-}
-
-MenuItemMatcher& MenuItemMatcher::boolean_attribute(const string& name, bool value)
-{
- return attribute(
- name,
- shared_ptr<GVariant>(g_variant_new_boolean(value),
- &gvariant_deleter));
-}
-
-MenuItemMatcher& MenuItemMatcher::string_attribute(const string& name, const string& value)
-{
- return attribute(
- name,
- shared_ptr<GVariant>(g_variant_new_string(value.c_str()),
- &gvariant_deleter));
-}
-
-MenuItemMatcher& MenuItemMatcher::int32_attribute(const std::string& name, int value)
-{
- return attribute(
- name,
- shared_ptr<GVariant>(g_variant_new_int32 (value),
- &gvariant_deleter));
-}
-
-MenuItemMatcher& MenuItemMatcher::int64_attribute(const std::string& name, int value)
-{
- return attribute(
- name,
- shared_ptr<GVariant>(g_variant_new_int64 (value),
- &gvariant_deleter));
-}
-
-MenuItemMatcher& MenuItemMatcher::double_attribute(const std::string& name, double value)
-{
- return attribute(
- name,
- shared_ptr<GVariant>(g_variant_new_double (value),
- &gvariant_deleter));
-}
-
-MenuItemMatcher& MenuItemMatcher::attribute_not_set(const std::string& name)
-{
- p->m_not_exist_attributes.emplace_back (name);
- return *this;
-}
-
-MenuItemMatcher& MenuItemMatcher::toggled(bool isToggled)
-{
- p->m_isToggled = make_shared<bool>(isToggled);
- return *this;
-}
-
-MenuItemMatcher& MenuItemMatcher::mode(Mode mode)
-{
- p->m_mode = mode;
- return *this;
-}
-
-MenuItemMatcher& MenuItemMatcher::submenu()
-{
- p->m_linkType = LinkType::submenu;
- return *this;
-}
-
-MenuItemMatcher& MenuItemMatcher::section()
-{
- p->m_linkType = LinkType::section;
- return *this;
-}
-
-MenuItemMatcher& MenuItemMatcher::is_empty()
-{
- return has_exactly(0);
-}
-
-MenuItemMatcher& MenuItemMatcher::has_exactly(size_t children)
-{
- p->m_expectedSize = make_shared<size_t>(children);
- return *this;
-}
-
-MenuItemMatcher& MenuItemMatcher::item(const MenuItemMatcher& item)
-{
- p->m_items.emplace_back(item);
- return *this;
-}
-
-MenuItemMatcher& MenuItemMatcher::item(MenuItemMatcher&& item)
-{
- p->m_items.emplace_back(item);
- return *this;
-}
-
-MenuItemMatcher& MenuItemMatcher::pass_through_activate(std::string const& action, const shared_ptr<GVariant>& parameter)
-{
- p->m_activations.emplace_back(action, parameter);
- return *this;
-}
-
-MenuItemMatcher& MenuItemMatcher::activate(const shared_ptr<GVariant>& parameter)
-{
- p->m_activations.emplace_back(string(), parameter);
- return *this;
-}
-
-MenuItemMatcher& MenuItemMatcher::set_pass_through_action_state(const std::string& action, const std::shared_ptr<GVariant>& state)
-{
- p->m_setActionStates.emplace_back(action, state);
- return *this;
-}
-
-MenuItemMatcher& MenuItemMatcher::set_action_state(const std::shared_ptr<GVariant>& state)
-{
- p->m_setActionStates.emplace_back("", state);
- return *this;
-}
-
-void MenuItemMatcher::match(
- MatchResult& matchResult,
- const vector<unsigned int>& parentLocation,
- const shared_ptr<GMenuModel>& menu,
- map<string, shared_ptr<GActionGroup>>& actions,
- int index) const
-{
- shared_ptr<GMenuItem> menuItem(g_menu_item_new_from_model(menu.get(), index), &g_object_deleter);
-
- vector<unsigned int> location(parentLocation);
- location.emplace_back(index);
-
- string action = get_string_attribute(menuItem, G_MENU_ATTRIBUTE_ACTION);
-
- bool isCheckbox = false;
- bool isRadio = false;
- bool isToggled = false;
-
- pair<string, string> idPair;
- shared_ptr<GActionGroup> actionGroup;
- shared_ptr<GVariant> state;
-
- if (!action.empty())
- {
- idPair = split_action(action);
- actionGroup = actions[idPair.first];
- state = shared_ptr<GVariant>(g_action_group_get_action_state(actionGroup.get(),
- idPair.second.c_str()),
- &gvariant_deleter);
- auto attributeTarget = get_attribute(menuItem, G_MENU_ATTRIBUTE_TARGET);
-
- if (attributeTarget && state)
- {
- isToggled = g_variant_equal(state.get(), attributeTarget.get());
- isRadio = true;
- }
- else if (state
- && g_variant_is_of_type(state.get(), G_VARIANT_TYPE_BOOLEAN))
- {
- isToggled = g_variant_get_boolean(state.get());
- isCheckbox = true;
- }
- }
-
- Type actualType = Type::plain;
- if (isCheckbox)
- {
- actualType = Type::checkbox;
- }
- else if (isRadio)
- {
- actualType = Type::radio;
- }
-
- if (actualType != p->m_type)
- {
- matchResult.failure(
- location,
- "Expected " + type_to_string(p->m_type) + ", found "
- + type_to_string(actualType));
- }
-
- // check themed icons
- map<shared_ptr<string>, vector<string>>::iterator iter;
- for (iter = p->m_themed_icons.begin(); iter != p->m_themed_icons.end(); ++iter)
- {
- auto icon_val = g_menu_item_get_attribute_value(menuItem.get(), (*iter).first->c_str(), nullptr);
- if (!icon_val)
- {
- matchResult.failure(
- location,
- "Expected themed icon " + (*(*iter).first) + " was not found");
- }
-
- auto gicon = g_icon_deserialize(icon_val);
- if (!gicon || !G_IS_THEMED_ICON(gicon))
- {
- matchResult.failure(
- location,
- "Expected attribute " + (*(*iter).first) + " is not a themed icon");
- }
- auto iconNames = g_themed_icon_get_names(G_THEMED_ICON(gicon));
- int nb_icons = 0;
- while(iconNames[nb_icons])
- {
- ++nb_icons;
- }
-
- if (nb_icons != (*iter).second.size())
- {
- matchResult.failure(
- location,
- "Expected " + to_string((*iter).second.size()) +
- " icons for themed icon [" + (*(*iter).first) +
- "], but " + to_string(nb_icons) + " were found.");
- }
- else
- {
- // now compare all the icons
- for (int i = 0; i < nb_icons; ++i)
- {
- if (string(iconNames[i]) != (*iter).second[i])
- {
- matchResult.failure(
- location,
- "Icon at position " + to_string(i) +
- " for themed icon [" + (*(*iter).first) +
- "], mismatchs. Expected: " + iconNames[i] + " but found " + (*iter).second[i]);
- }
- }
- }
- g_object_unref(gicon);
- }
-
- string label = get_string_attribute(menuItem, G_MENU_ATTRIBUTE_LABEL);
- if (p->m_label && (*p->m_label) != label)
- {
- matchResult.failure(
- location,
- "Expected label '" + *p->m_label + "', but found '" + label
- + "'");
- }
-
- string icon = get_string_attribute(menuItem, G_MENU_ATTRIBUTE_ICON);
- if (p->m_icon && (*p->m_icon) != icon)
- {
- matchResult.failure(
- location,
- "Expected icon '" + *p->m_icon + "', but found '" + icon + "'");
- }
-
- if (p->m_action && (*p->m_action) != action)
- {
- matchResult.failure(
- location,
- "Expected action '" + *p->m_action + "', but found '" + action
- + "'");
- }
-
- if (!p->m_state_icons.empty() && !state)
- {
- matchResult.failure(
- location,
- "Expected state icons but no state was found");
- }
- else if (!p->m_state_icons.empty() && state &&
- !g_variant_is_of_type(state.get(), G_VARIANT_TYPE_VARDICT))
- {
- matchResult.failure(
- location,
- "Expected state icons vardict, found "
- + type_to_string(actualType));
- }
- else if (!p->m_state_icons.empty() && state &&
- g_variant_is_of_type(state.get(), G_VARIANT_TYPE_VARDICT))
- {
- std::vector<std::string> actual_state_icons;
- GVariantIter it;
- gchar* key;
- GVariant* value;
-
- g_variant_iter_init(&it, state.get());
- while (g_variant_iter_loop(&it, "{sv}", &key, &value))
- {
- if (std::string(key) == "icon") {
- auto gicon = g_icon_deserialize(value);
- if (gicon && G_IS_THEMED_ICON(gicon))
- {
- auto iconNames = g_themed_icon_get_names(G_THEMED_ICON(gicon));
- // Just take the first icon in the list (there is only ever one)
- actual_state_icons.push_back(iconNames[0]);
- g_object_unref(gicon);
- }
- }
- else if (std::string(key) == "icons" && g_variant_is_of_type(value, G_VARIANT_TYPE("av")))
- {
- // If we find "icons" in the map, clear any icons we may have found in "icon",
- // then break from the loop as we have found all icons now.
- actual_state_icons.clear();
- GVariantIter icon_it;
- GVariant* icon_value;
-
- g_variant_iter_init(&icon_it, value);
- while (g_variant_iter_loop(&icon_it, "v", &icon_value))
- {
- auto gicon = g_icon_deserialize(icon_value);
- if (gicon && G_IS_THEMED_ICON(gicon))
- {
- auto iconNames = g_themed_icon_get_names(G_THEMED_ICON(gicon));
- // Just take the first icon in the list (there is only ever one)
- actual_state_icons.push_back(iconNames[0]);
- g_object_unref(gicon);
- }
- }
- // We're breaking out of g_variant_iter_loop here so clean up
- g_variant_unref(value);
- g_free(key);
- break;
- }
- }
-
- if (p->m_state_icons != actual_state_icons)
- {
- std::string expected_icons;
- for (unsigned int i = 0; i < p->m_state_icons.size(); ++i)
- {
- expected_icons += i == 0 ? p->m_state_icons[i] : ", " + p->m_state_icons[i];
- }
- std::string actual_icons;
- for (unsigned int i = 0; i < actual_state_icons.size(); ++i)
- {
- actual_icons += i == 0 ? actual_state_icons[i] : ", " + actual_state_icons[i];
- }
- matchResult.failure(
- location,
- "Expected state_icons == {" + expected_icons
- + "} but found {" + actual_icons + "}");
- }
- }
-
- for (const auto& e: p->m_pass_through_attributes)
- {
- string actionName = get_string_attribute(menuItem, e.first.c_str());
- if (actionName.empty())
- {
- matchResult.failure(
- location,
- "Could not find action name '" + e.first + "'");
- }
- else
- {
- auto passThroughIdPair = split_action(actionName);
- auto actionGroup = actions[passThroughIdPair.first];
- if (actionGroup)
- {
- auto value = get_action_group_attribute(
- actionGroup, passThroughIdPair.second.c_str());
- if (!value)
- {
- matchResult.failure(
- location,
- "Expected pass-through attribute '" + e.first
- + "' was not present");
- }
- else if (!g_variant_is_of_type(e.second.get(), g_variant_get_type(value.get())))
- {
- std::string expectedType = g_variant_get_type_string(e.second.get());
- std::string actualType = g_variant_get_type_string(value.get());
- matchResult.failure(
- location,
- "Expected pass-through attribute type '" + expectedType
- + "' but found '" + actualType + "'");
- }
- else if (g_variant_compare(e.second.get(), value.get()))
- {
- bool reportMismatch = true;
- if (g_strcmp0(g_variant_get_type_string(value.get()),"d") == 0 && p->m_maxDifference)
- {
- auto actualDouble = g_variant_get_double(value.get());
- auto expectedDouble = g_variant_get_double(e.second.get());
- auto difference = actualDouble-expectedDouble;
- if (difference < 0) difference = difference * -1.0;
- if (difference <= p->m_maxDifference)
- {
- reportMismatch = false;
- }
- }
- if (reportMismatch)
- {
- gchar* expectedString = g_variant_print(e.second.get(), true);
- gchar* actualString = g_variant_print(value.get(), true);
- matchResult.failure(
- location,
- "Expected pass-through attribute '" + e.first
- + "' == " + expectedString + " but found "
- + actualString);
-
- g_free(expectedString);
- g_free(actualString);
- }
- }
- }
- else
- {
- matchResult.failure(location, "Could not find action group for ID '" + passThroughIdPair.first + "'");
- }
- }
- }
-
- for (const auto& e: p->m_attributes)
- {
- auto value = get_attribute(menuItem, e.first.c_str());
- if (!value)
- {
- matchResult.failure(location,
- "Expected attribute '" + e.first
- + "' could not be found");
- }
- else if (!g_variant_is_of_type(e.second.get(), g_variant_get_type(value.get())))
- {
- std::string expectedType = g_variant_get_type_string(e.second.get());
- std::string actualType = g_variant_get_type_string(value.get());
- matchResult.failure(
- location,
- "Expected attribute type '" + expectedType
- + "' but found '" + actualType + "'");
- }
- else if (g_variant_compare(e.second.get(), value.get()))
- {
- gchar* expectedString = g_variant_print(e.second.get(), true);
- gchar* actualString = g_variant_print(value.get(), true);
- matchResult.failure(
- location,
- "Expected attribute '" + e.first + "' == " + expectedString
- + ", but found " + actualString);
- g_free(expectedString);
- g_free(actualString);
- }
- }
-
- for (const auto& e: p->m_not_exist_attributes)
- {
- auto value = get_attribute(menuItem, e.c_str());
- if (value)
- {
- matchResult.failure(location,
- "Not expected attribute '" + e
- + "' was found");
- }
- }
-
- if (p->m_isToggled && (*p->m_isToggled) != isToggled)
- {
- matchResult.failure(
- location,
- "Expected toggled = " + bool_to_string(*p->m_isToggled)
- + ", but found " + bool_to_string(isToggled));
- }
-
- if (!matchResult.success())
- {
- return;
- }
-
- if (!p->m_items.empty() || p->m_expectedSize)
- {
- shared_ptr<GMenuModel> link;
-
- switch (p->m_linkType)
- {
- case LinkType::any:
- {
- link.reset(g_menu_model_get_item_link(menu.get(), (int) index, G_MENU_LINK_SUBMENU), &g_object_deleter);
- if (!link)
- {
- link.reset(g_menu_model_get_item_link(menu.get(), (int) index, G_MENU_LINK_SECTION), &g_object_deleter);
- }
- break;
- }
- case LinkType::submenu:
- {
- link.reset(g_menu_model_get_item_link(menu.get(), (int) index, G_MENU_LINK_SUBMENU), &g_object_deleter);
- break;
- }
- case LinkType::section:
- {
- link.reset(g_menu_model_get_item_link(menu.get(), (int) index, G_MENU_LINK_SECTION), &g_object_deleter);
- break;
- }
- }
-
-
- if (!link)
- {
- if (p->m_expectedSize)
- {
- matchResult.failure(
- location,
- "Expected " + to_string(*p->m_expectedSize)
- + " children, but found none");
- }
- else
- {
- matchResult.failure(
- location,
- "Expected " + to_string(p->m_items.size())
- + " children, but found none");
- }
- return;
- }
- else
- {
- while (true)
- {
- MatchResult childMatchResult(matchResult.createChild());
-
- if (p->m_expectedSize
- && *p->m_expectedSize
- != (unsigned int) g_menu_model_get_n_items(
- link.get()))
- {
- childMatchResult.failure(
- location,
- "Expected " + to_string(*p->m_expectedSize)
- + " child items, but found "
- + to_string(
- g_menu_model_get_n_items(
- link.get())));
- }
- else if (!p->m_items.empty())
- {
- switch (p->m_mode)
- {
- case Mode::all:
- p->all(childMatchResult, location, link, actions);
- break;
- case Mode::starts_with:
- p->startsWith(childMatchResult, location, link, actions);
- break;
- case Mode::ends_with:
- p->endsWith(childMatchResult, location, link, actions);
- break;
- }
- }
-
- if (childMatchResult.success())
- {
- matchResult.merge(childMatchResult);
- break;
- }
- else
- {
- if (matchResult.hasTimedOut())
- {
- matchResult.merge(childMatchResult);
- break;
- }
- menuWaitForItems(link);
- }
- }
- }
- }
-
-
- for (const auto& a: p->m_setActionStates)
- {
- auto stateAction = action;
- auto stateIdPair = idPair;
- auto stateActionGroup = actionGroup;
- if (!a.first.empty())
- {
- stateAction = get_string_attribute(menuItem, a.first.c_str());;
- stateIdPair = split_action(stateAction);
- stateActionGroup = actions[stateIdPair.first];
- }
-
- if (stateAction.empty())
- {
- matchResult.failure(
- location,
- "Tried to set action state, but no action was found");
- }
- else if(!stateActionGroup)
- {
- matchResult.failure(
- location,
- "Tried to set action state for action group '" + stateIdPair.first
- + "', but action group wasn't found");
- }
- else if (!g_action_group_has_action(stateActionGroup.get(), stateIdPair.second.c_str()))
- {
- matchResult.failure(
- location,
- "Tried to set action state for action '" + stateAction
- + "', but action was not found");
- }
- else
- {
- g_action_group_change_action_state(stateActionGroup.get(), stateIdPair.second.c_str(),
- g_variant_ref(a.second.get()));
- }
-
- // FIXME this is a dodgy way to ensure the action state change gets dispatched
- menuWaitForItems(menu, 100);
- }
-
- for (const auto& a: p->m_activations)
- {
- string tmpAction = action;
- auto tmpIdPair = idPair;
- auto tmpActionGroup = actionGroup;
- if (!a.first.empty())
- {
- tmpAction = get_string_attribute(menuItem, a.first.c_str());
- tmpIdPair = split_action(tmpAction);
- tmpActionGroup = actions[tmpIdPair.first];
- }
-
- if (tmpAction.empty())
- {
- matchResult.failure(
- location,
- "Tried to activate action, but no action was found");
- }
- else if(!tmpActionGroup)
- {
- matchResult.failure(
- location,
- "Tried to activate action group '" + tmpIdPair.first
- + "', but action group wasn't found");
- }
- else if (!g_action_group_has_action(tmpActionGroup.get(), tmpIdPair.second.c_str()))
- {
- matchResult.failure(
- location,
- "Tried to activate action '" + tmpAction + "', but action was not found");
- }
- else
- {
- if (a.second)
- {
- g_action_group_activate_action(tmpActionGroup.get(), tmpIdPair.second.c_str(),
- g_variant_ref(a.second.get()));
- }
- else
- {
- g_action_group_activate_action(tmpActionGroup.get(), tmpIdPair.second.c_str(), nullptr);
- }
-
- // FIXME this is a dodgy way to ensure the activation gets dispatched
- menuWaitForItems(menu, 100);
- }
- }
-}
-
-} // namepsace gmenuharness
-
-} // namespace unity
diff --git a/src/gmenuharness/MenuMatcher.cpp b/src/gmenuharness/MenuMatcher.cpp
deleted file mode 100644
index 5bb4fbd..0000000
--- a/src/gmenuharness/MenuMatcher.cpp
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * Copyright © 2014 Canonical Ltd.
- *
- * This program is free software: you can redistribute it and/or modify it
- * under the terms of the GNU Lesser 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 warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- * Authored by: Pete Woods <pete.woods@canonical.com>
- */
-
-#include <unity/gmenuharness/MenuMatcher.h>
-#include <unity/gmenuharness/MatchUtils.h>
-
-#include <iostream>
-
-#include <gio/gio.h>
-
-using namespace std;
-
-namespace unity
-{
-
-namespace gmenuharness
-{
-
-namespace
-{
-
-static void gdbus_connection_deleter(GDBusConnection* connection)
-{
-// if (!g_dbus_connection_is_closed(connection))
-// {
-// g_dbus_connection_close_sync(connection, nullptr, nullptr);
-// }
- g_clear_object(&connection);
-}
-}
-
-struct MenuMatcher::Parameters::Priv
-{
- string m_busName;
-
- vector<pair<string, string>> m_actions;
-
- string m_menuObjectPath;
-};
-
-MenuMatcher::Parameters::Parameters(const string& busName,
- const vector<pair<string, string>>& actions,
- const string& menuObjectPath) :
- p(new Priv)
-{
- p->m_busName = busName;
- p->m_actions = actions;
- p->m_menuObjectPath = menuObjectPath;
-}
-
-MenuMatcher::Parameters::~Parameters()
-{
-}
-
-MenuMatcher::Parameters::Parameters(const Parameters& other) :
- p(new Priv)
-{
- *this = other;
-}
-
-MenuMatcher::Parameters::Parameters(Parameters&& other)
-{
- *this = move(other);
-}
-
-MenuMatcher::Parameters& MenuMatcher::Parameters::operator=(const Parameters& other)
-{
- p->m_busName = other.p->m_busName;
- p->m_actions = other.p->m_actions;
- p->m_menuObjectPath = other.p->m_menuObjectPath;
- return *this;
-}
-
-MenuMatcher::Parameters& MenuMatcher::Parameters::operator=(Parameters&& other)
-{
- p = move(other.p);
- return *this;
-}
-
-struct MenuMatcher::Priv
-{
- Priv(const Parameters& parameters) :
- m_parameters(parameters)
- {
- }
-
- Parameters m_parameters;
-
- vector<MenuItemMatcher> m_items;
-
- shared_ptr<GDBusConnection> m_system;
-
- shared_ptr<GDBusConnection> m_session;
-
- shared_ptr<GMenuModel> m_menu;
-
- map<string, shared_ptr<GActionGroup>> m_actions;
-};
-
-MenuMatcher::MenuMatcher(const Parameters& parameters) :
- p(new Priv(parameters))
-{
- p->m_system.reset(g_bus_get_sync(G_BUS_TYPE_SYSTEM, nullptr, nullptr),
- &gdbus_connection_deleter);
- g_dbus_connection_set_exit_on_close(p->m_system.get(), false);
-
- p->m_session.reset(g_bus_get_sync(G_BUS_TYPE_SESSION, nullptr, nullptr),
- &gdbus_connection_deleter);
- g_dbus_connection_set_exit_on_close(p->m_session.get(), false);
-
- p->m_menu.reset(
- G_MENU_MODEL(
- g_dbus_menu_model_get(
- p->m_session.get(),
- p->m_parameters.p->m_busName.c_str(),
- p->m_parameters.p->m_menuObjectPath.c_str())),
- &g_object_deleter);
-
- for (const auto& action : p->m_parameters.p->m_actions)
- {
- shared_ptr<GActionGroup> actionGroup(
- G_ACTION_GROUP(
- g_dbus_action_group_get(
- p->m_session.get(),
- p->m_parameters.p->m_busName.c_str(),
- action.second.c_str())),
- &g_object_deleter);
- p->m_actions[action.first] = actionGroup;
- }
-}
-
-MenuMatcher::~MenuMatcher()
-{
-}
-
-MenuMatcher& MenuMatcher::item(const MenuItemMatcher& item)
-{
- p->m_items.emplace_back(item);
- return *this;
-}
-
-void MenuMatcher::match(MatchResult& matchResult) const
-{
- vector<unsigned int> location;
-
- while (true)
- {
- MatchResult childMatchResult(matchResult.createChild());
-
- int menuSize = g_menu_model_get_n_items(p->m_menu.get());
- if (p->m_items.size() > (unsigned int) menuSize)
- {
- childMatchResult.failure(
- location,
- "Row count mismatch, expected " + to_string(p->m_items.size())
- + " but found " + to_string(menuSize));
- }
- else
- {
- for (size_t i = 0; i < p->m_items.size(); ++i)
- {
- const auto& matcher = p->m_items.at(i);
- matcher.match(childMatchResult, location, p->m_menu, p->m_actions, i);
- }
- }
-
- if (childMatchResult.success())
- {
- matchResult.merge(childMatchResult);
- break;
- }
- else
- {
- if (matchResult.hasTimedOut())
- {
- matchResult.merge(childMatchResult);
- break;
- }
- menuWaitForItems(p->m_menu);
- }
- }
-}
-
-MatchResult MenuMatcher::match() const
-{
- MatchResult matchResult;
- match(matchResult);
- return matchResult;
-}
-
-} // namespace gmenuharness
-
-} // namespace unity
diff --git a/src/service.vala b/src/service.vala
index 12e2ac2..a08edf3 100644
--- a/src/service.vala
+++ b/src/service.vala
@@ -43,7 +43,7 @@ public class IndicatorSound.Service: Object {
warn_notification.closed.connect((n) => { n.clear_actions(); });
BusWatcher.watch_namespace (GLib.BusType.SESSION,
"org.freedesktop.Notifications",
- () => { debug("Notifications name appeared"); },
+ () => { debug("Notifications name appeared"); notify_server_caps_checked = false; },
() => { debug("Notifications name vanshed"); notify_server_caps_checked = false; });
this.settings = new Settings ("com.canonical.indicator.sound");
@@ -52,8 +52,6 @@ public class IndicatorSound.Service: Object {
this.notify["visible"].connect ( () => this.update_root_icon () );
this.volume_control = volume;
- this.volume_control.active_output_changed.connect (this.update_root_icon);
- this.volume_control.active_output_changed.connect (this.update_notification);
this.accounts_service = accounts;
/* If we're on the greeter, don't export */
@@ -92,10 +90,6 @@ public class IndicatorSound.Service: Object {
this.volume_control.bind_property ("high-volume", menu, "show-high-volume-warning", BindingFlags.SYNC_CREATE);
});
- this.menus.@foreach ( (profile, menu) => {
- this.volume_control.active_output_changed.connect (menu.update_volume_slider);
- });
-
this.sync_preferred_players ();
this.settings.changed["interested-media-players"].connect ( () => {
this.sync_preferred_players ();
@@ -251,7 +245,17 @@ public class IndicatorSound.Service: Object {
void update_root_icon () {
double volume = this.volume_control.volume.volume;
- string icon = get_volume_root_icon (volume, this.volume_control.mute, volume_control.active_output);
+ string icon;
+ if (this.volume_control.mute || volume <= 0.0)
+ icon = this.mute_blocks_sound ? "audio-volume-muted-blocking-panel" : "audio-volume-muted-panel";
+ else if (this.accounts_service != null && this.accounts_service.silentMode)
+ icon = "audio-volume-muted-panel";
+ else if (volume <= 0.3)
+ icon = "audio-volume-low-panel";
+ else if (volume <= 0.7)
+ icon = "audio-volume-medium-panel";
+ else
+ icon = "audio-volume-high-panel";
string accessible_name;
if (this.volume_control.mute) {
@@ -277,333 +281,15 @@ public class IndicatorSound.Service: Object {
private bool notify_server_supports_actions = false;
private bool notify_server_supports_sync = false;
private bool block_info_notifications = false;
- private bool waiting_user_approve_warn = false;
-
- private string get_volume_icon (double volume, VolumeControl.ActiveOutput active_output)
- {
- string icon = "";
- switch (active_output)
- {
- case VolumeControl.ActiveOutput.SPEAKERS:
- if (volume <= 0.0)
- icon = "audio-volume-muted";
- else if (volume <= 0.3)
- icon = "audio-volume-low";
- else if (volume <= 0.7)
- icon = "audio-volume-medium";
- else
- icon = "audio-volume-high";
- break;
- case VolumeControl.ActiveOutput.HEADPHONES:
- if (volume <= 0.0)
- icon = "audio-volume-muted";
- else if (volume <= 0.3)
- icon = "audio-volume-low";
- else if (volume <= 0.7)
- icon = "audio-volume-medium";
- else
- icon = "audio-volume-high";
- break;
- case VolumeControl.ActiveOutput.BLUETOOTH_HEADPHONES:
- if (volume <= 0.0)
- icon = "audio-volume-muted";
- else if (volume <= 0.3)
- icon = "audio-volume-low";
- else if (volume <= 0.7)
- icon = "audio-volume-medium";
- else
- icon = "audio-volume-high";
- break;
- case VolumeControl.ActiveOutput.BLUETOOTH_SPEAKER:
- if (volume <= 0.0)
- icon = "audio-volume-muted";
- else if (volume <= 0.3)
- icon = "audio-volume-low";
- else if (volume <= 0.7)
- icon = "audio-volume-medium";
- else
- icon = "audio-volume-high";
- break;
- case VolumeControl.ActiveOutput.USB_SPEAKER:
- if (volume <= 0.0)
- icon = "audio-volume-muted";
- else if (volume <= 0.3)
- icon = "audio-volume-low";
- else if (volume <= 0.7)
- icon = "audio-volume-medium";
- else
- icon = "audio-volume-high";
- break;
- case VolumeControl.ActiveOutput.USB_HEADPHONES:
- if (volume <= 0.0)
- icon = "audio-volume-muted";
- else if (volume <= 0.3)
- icon = "audio-volume-low";
- else if (volume <= 0.7)
- icon = "audio-volume-medium";
- else
- icon = "audio-volume-high";
- break;
- case VolumeControl.ActiveOutput.HDMI_SPEAKER:
- if (volume <= 0.0)
- icon = "audio-volume-muted";
- else if (volume <= 0.3)
- icon = "audio-volume-low";
- else if (volume <= 0.7)
- icon = "audio-volume-medium";
- else
- icon = "audio-volume-high";
- break;
- case VolumeControl.ActiveOutput.HDMI_HEADPHONES:
- if (volume <= 0.0)
- icon = "audio-volume-muted";
- else if (volume <= 0.3)
- icon = "audio-volume-low";
- else if (volume <= 0.7)
- icon = "audio-volume-medium";
- else
- icon = "audio-volume-high";
- break;
- }
- return icon;
- }
-
- private string get_volume_root_icon_by_volume (double volume, VolumeControl.ActiveOutput active_output)
- {
- string icon = "";
- switch (active_output)
- {
- case VolumeControl.ActiveOutput.SPEAKERS:
- if (volume <= 0.0)
- icon = "audio-volume-muted-panel";
- else if (volume <= 0.3)
- icon = "audio-volume-low-panel";
- else if (volume <= 0.7)
- icon = "audio-volume-medium-panel";
- else
- icon = "audio-volume-high-panel";
- break;
- case VolumeControl.ActiveOutput.HEADPHONES:
- if (volume <= 0.0)
- icon = "audio-volume-muted-panel";
- else if (volume <= 0.3)
- icon = "audio-volume-low-panel";
- else if (volume <= 0.7)
- icon = "audio-volume-medium-panel";
- else
- icon = "audio-volume-high-panel";
- break;
- case VolumeControl.ActiveOutput.BLUETOOTH_HEADPHONES:
- if (volume <= 0.0)
- icon = "audio-volume-muted-panel";
- else if (volume <= 0.3)
- icon = "audio-volume-low-panel";
- else if (volume <= 0.7)
- icon = "audio-volume-medium-panel";
- else
- icon = "audio-volume-high-panel";
- break;
- case VolumeControl.ActiveOutput.BLUETOOTH_SPEAKER:
- if (volume <= 0.0)
- icon = "audio-volume-muted-panel";
- else if (volume <= 0.3)
- icon = "audio-volume-low-panel";
- else if (volume <= 0.7)
- icon = "audio-volume-medium-panel";
- else
- icon = "audio-volume-high-panel";
- break;
- case VolumeControl.ActiveOutput.USB_SPEAKER:
- if (volume <= 0.0)
- icon = "audio-volume-muted-panel";
- else if (volume <= 0.3)
- icon = "audio-volume-low-panel";
- else if (volume <= 0.7)
- icon = "audio-volume-medium-panel";
- else
- icon = "audio-volume-high-panel";
- break;
- case VolumeControl.ActiveOutput.USB_HEADPHONES:
- if (volume <= 0.0)
- icon = "audio-volume-muted-panel";
- else if (volume <= 0.3)
- icon = "audio-volume-low-panel";
- else if (volume <= 0.7)
- icon = "audio-volume-medium-panel";
- else
- icon = "audio-volume-high-panel";
- break;
- case VolumeControl.ActiveOutput.HDMI_SPEAKER:
- if (volume <= 0.0)
- icon = "audio-volume-muted-panel";
- else if (volume <= 0.3)
- icon = "audio-volume-low-panel";
- else if (volume <= 0.7)
- icon = "audio-volume-medium-panel";
- else
- icon = "audio-volume-high-panel";
- break;
- case VolumeControl.ActiveOutput.HDMI_HEADPHONES:
- if (volume <= 0.0)
- icon = "audio-volume-muted-panel";
- else if (volume <= 0.3)
- icon = "audio-volume-low-panel";
- else if (volume <= 0.7)
- icon = "audio-volume-medium-panel";
- else
- icon = "audio-volume-high-panel";
- break;
- }
- return icon;
- }
-
- private string get_volume_notification_icon (double volume, bool loud, VolumeControl.ActiveOutput active_output) {
- string icon = "";
- if (loud) {
- switch (active_output)
- {
- case VolumeControl.ActiveOutput.SPEAKERS:
- icon = "audio-volume-high";
- break;
- case VolumeControl.ActiveOutput.HEADPHONES:
- icon = "audio-volume-high";
- break;
- case VolumeControl.ActiveOutput.BLUETOOTH_HEADPHONES:
- icon = "audio-volume-high";
- break;
- case VolumeControl.ActiveOutput.BLUETOOTH_SPEAKER:
- icon = "audio-volume-high";
- break;
- case VolumeControl.ActiveOutput.USB_SPEAKER:
- icon = "audio-volume-high";
- break;
- case VolumeControl.ActiveOutput.USB_HEADPHONES:
- icon = "audio-volume-high";
- break;
- case VolumeControl.ActiveOutput.HDMI_SPEAKER:
- icon = "audio-volume-high";
- break;
- case VolumeControl.ActiveOutput.HDMI_HEADPHONES:
- icon = "audio-volume-high";
- break;
- }
- } else {
- icon = get_volume_icon (volume, active_output);
- }
- return icon;
- }
-
- private string get_volume_root_icon (double volume, bool mute, VolumeControl.ActiveOutput active_output) {
- string icon = "";
- switch (active_output)
- {
- case VolumeControl.ActiveOutput.SPEAKERS:
- if (mute || volume <= 0.0)
- icon = this.mute_blocks_sound ? "audio-volume-muted-blocking-panel" : "audio-volume-muted-panel";
- else if (this.accounts_service != null && this.accounts_service.silentMode)
- icon = "audio-volume-muted-panel";
- else
- icon = get_volume_root_icon_by_volume (volume, active_output);
- break;
- case VolumeControl.ActiveOutput.HEADPHONES:
- if (mute || volume <= 0.0)
- icon = this.mute_blocks_sound ? "audio-volume-muted-blocking-panel" : "audio-volume-muted-panel";
- else if (this.accounts_service != null && this.accounts_service.silentMode)
- icon = "audio-volume-muted-panel";
- else
- icon = get_volume_root_icon_by_volume (volume, active_output);
- break;
- case VolumeControl.ActiveOutput.BLUETOOTH_HEADPHONES:
- if (mute || volume <= 0.0)
- icon = this.mute_blocks_sound ? "audio-volume-muted-blocking-panel" : "audio-volume-muted-panel";
- else if (this.accounts_service != null && this.accounts_service.silentMode)
- icon = "audio-volume-muted-panel";
- else
- icon = get_volume_root_icon_by_volume (volume, active_output);
- break;
- case VolumeControl.ActiveOutput.BLUETOOTH_SPEAKER:
- if (mute || volume <= 0.0)
- icon = this.mute_blocks_sound ? "audio-volume-muted-blocking-panel" : "audio-volume-muted-panel";
- else if (this.accounts_service != null && this.accounts_service.silentMode)
- icon = "audio-volume-muted-panel";
- else
- icon = get_volume_root_icon_by_volume (volume, active_output);
- break;
- case VolumeControl.ActiveOutput.USB_SPEAKER:
- if (mute || volume <= 0.0)
- icon = this.mute_blocks_sound ? "audio-volume-muted-blocking-panel" : "audio-volume-muted-panel";
- else if (this.accounts_service != null && this.accounts_service.silentMode)
- icon = "audio-volume-muted-panel";
- else
- icon = get_volume_root_icon_by_volume (volume, active_output);
- break;
- case VolumeControl.ActiveOutput.USB_HEADPHONES:
- if (mute || volume <= 0.0)
- icon = this.mute_blocks_sound ? "audio-volume-muted-blocking-panel" : "audio-volume-muted-panel";
- else if (this.accounts_service != null && this.accounts_service.silentMode)
- icon = "audio-volume-muted-panel";
- else
- icon = get_volume_root_icon_by_volume (volume, active_output);
- break;
- case VolumeControl.ActiveOutput.HDMI_SPEAKER:
- if (mute || volume <= 0.0)
- icon = this.mute_blocks_sound ? "audio-volume-muted-blocking-panel" : "audio-volume-muted-panel";
- else if (this.accounts_service != null && this.accounts_service.silentMode)
- icon = "audio-volume-muted-panel";
- else
- icon = get_volume_root_icon_by_volume (volume, active_output);
- break;
- case VolumeControl.ActiveOutput.HDMI_HEADPHONES:
- if (mute || volume <= 0.0)
- icon = this.mute_blocks_sound ? "audio-volume-muted-blocking-panel" : "audio-volume-muted-panel";
- else if (this.accounts_service != null && this.accounts_service.silentMode)
- icon = "audio-volume-muted-panel";
- else
- icon = get_volume_root_icon_by_volume (volume, active_output);
- break;
- }
- return icon;
- }
-
- private string get_notification_label () {
- string volume_label = "";
- switch (volume_control.active_output)
- {
- case VolumeControl.ActiveOutput.SPEAKERS:
- volume_label = _("Speakers");
- break;
- case VolumeControl.ActiveOutput.HEADPHONES:
- volume_label = _("Headphones");
- break;
- case VolumeControl.ActiveOutput.BLUETOOTH_HEADPHONES:
- volume_label = _("Bluetooth headphones");
- break;
- case VolumeControl.ActiveOutput.BLUETOOTH_SPEAKER:
- volume_label = _("Bluetooth speaker");
- break;
- case VolumeControl.ActiveOutput.USB_SPEAKER:
- volume_label = _("Usb speaker");
- break;
- case VolumeControl.ActiveOutput.USB_HEADPHONES:
- volume_label = _("Usb headphones");
- break;
- case VolumeControl.ActiveOutput.HDMI_SPEAKER:
- volume_label = _("HDMI speaker");
- break;
- case VolumeControl.ActiveOutput.HDMI_HEADPHONES:
- volume_label = _("HDMI headphones");
- break;
- }
-
- return volume_label;
- }
private void update_notification () {
- List<string> caps = Notify.get_server_caps ();
- notify_server_supports_actions = caps.find_custom ("actions", strcmp) != null;
- notify_server_supports_sync = caps.find_custom ("x-canonical-private-synchronous", strcmp) != null;
- notify_server_caps_checked = true;
+ if (!notify_server_caps_checked) {
+ List<string> caps = Notify.get_server_caps ();
+ notify_server_supports_actions = caps.find_custom ("actions", strcmp) != null;
+ notify_server_supports_sync = caps.find_custom ("x-canonical-private-synchronous", strcmp) != null;
+ notify_server_caps_checked = true;
+ }
var loud = volume_control.high_volume;
var warn = loud
@@ -626,36 +312,47 @@ public class IndicatorSound.Service: Object {
_pre_warn_volume = null;
volume_control.volume = tmp;
}
- waiting_user_approve_warn = false;
});
warn_notification.add_action ("cancel", _("Cancel"), (n, a) => {
_pre_warn_volume = null;
- waiting_user_approve_warn = false;
});
- waiting_user_approve_warn = true;
show_notification(warn_notification);
} else {
- if (!waiting_user_approve_warn) {
- close_notification(warn_notification);
-
- if (notify_server_supports_sync && !block_info_notifications) {
-
- /* Determine Label */
- string volume_label = get_notification_label ();
-
- /* Choose an icon */
- string icon = get_volume_notification_icon (volume_control.volume.volume, loud, volume_control.active_output);
-
- /* Reset the notification */
- var n = this.info_notification;
- n.update (_("Volume"), volume_label, icon);
- n.clear_hints();
- n.set_hint ("x-canonical-non-shaped-icon", "true");
- n.set_hint ("x-canonical-private-synchronous", "true");
- n.set_hint ("x-canonical-value-bar-tint", loud ? "true" : "false");
- n.set_hint ("value", (int32)Math.round(get_volume_percent() * 100.0));
- show_notification(n);
+ close_notification(warn_notification);
+
+ if (notify_server_supports_sync && !block_info_notifications) {
+
+ /* Determine Label */
+ unowned string volume_label = loud
+ ? _("High volume can damage your hearing.")
+ : "";
+
+ /* Choose an icon */
+ unowned string icon;
+ if (loud) {
+ icon = "audio-volume-high";
+ } else {
+ var volume = volume_control.volume.volume;
+
+ if (volume <= 0.0)
+ icon = "audio-volume-muted";
+ else if (volume <= 0.3)
+ icon = "audio-volume-low";
+ else if (volume <= 0.7)
+ icon = "audio-volume-medium";
+ else
+ icon = "audio-volume-high";
}
+
+ /* Reset the notification */
+ var n = this.info_notification;
+ n.update (_("Volume"), volume_label, icon);
+ n.clear_hints();
+ n.set_hint ("x-canonical-non-shaped-icon", "true");
+ n.set_hint ("x-canonical-private-synchronous", "true");
+ n.set_hint ("x-canonical-value-bar-tint", loud ? "true" : "false");
+ n.set_hint ("value", (int32)Math.round(get_volume_percent() * 100.0));
+ show_notification(n);
}
}
}
diff --git a/src/sound-menu.vala b/src/sound-menu.vala
index 3d682e4..7a6044b 100644
--- a/src/sound-menu.vala
+++ b/src/sound-menu.vala
@@ -71,7 +71,6 @@ public class SoundMenu: Object
this.notify_handlers = new HashTable<MediaPlayer, ulong> (direct_hash, direct_equal);
this.greeter_players = (flags & DisplayFlags.GREETER_PLAYERS) != 0;
-
}
~SoundMenu () {
@@ -194,43 +193,6 @@ public class SoundMenu: Object
this.notify_handlers.remove (player);
}
- public void update_volume_slider (VolumeControl.ActiveOutput active_output) {
- int index = find_action (this.volume_section, "indicator.volume");
- if (index != -1) {
- string label = "Volume";
- switch (active_output) {
- case VolumeControl.ActiveOutput.SPEAKERS:
- label = _("Volume");
- break;
- case VolumeControl.ActiveOutput.HEADPHONES:
- label = _("Volume (Headphones)");
- break;
- case VolumeControl.ActiveOutput.BLUETOOTH_SPEAKER:
- label = _("Volume (Bluetooth)");
- break;
- case VolumeControl.ActiveOutput.USB_SPEAKER:
- label = _("Volume (Usb)");
- break;
- case VolumeControl.ActiveOutput.HDMI_SPEAKER:
- label = _("Volume (HDMI)");
- break;
- case VolumeControl.ActiveOutput.BLUETOOTH_HEADPHONES:
- label = _("Volume (Bluetooth headphones)");
- break;
- case VolumeControl.ActiveOutput.USB_HEADPHONES:
- label = _("Volume (Usb headphones)");
- break;
- case VolumeControl.ActiveOutput.HDMI_HEADPHONES:
- label = _("Volume (HDMI headphones)");
- break;
- }
- this.volume_section.remove (index);
- this.volume_section.insert_item (index, this.create_slider_menu_item (_(label), "indicator.volume(0)", 0.0, 1.0, 0.01,
- "audio-volume-low-zero-panel",
- "audio-volume-high-panel"));
- }
- }
-
public Menu root;
public Menu menu;
Menu volume_section;
diff --git a/src/volume-control-pulse.vala b/src/volume-control-pulse.vala
index 8122f26..87af258 100644
--- a/src/volume-control-pulse.vala
+++ b/src/volume-control-pulse.vala
@@ -87,7 +87,6 @@ public class VolumeControlPulse : VolumeControl
private bool _send_next_local_volume = false;
private double _account_service_volume = 0.0;
private bool _active_port_headphone = false;
- private VolumeControl.ActiveOutput _active_output = VolumeControl.ActiveOutput.SPEAKERS;
/** true when connected to the pulse server */
public override bool ready { get; private set; }
@@ -136,49 +135,6 @@ public class VolumeControlPulse : VolumeControl
stop_high_volume_approved_timer();
}
- private VolumeControl.ActiveOutput calculate_active_output (SinkInfo? sink) {
-
- VolumeControl.ActiveOutput ret_output = VolumeControl.ActiveOutput.SPEAKERS;
- /* Check if the current active port is headset/headphone */
- /* There is not easy way to check if the port is a headset/headphone besides
- * checking for the port name. On touch (with the pulseaudio droid element)
- * the headset/headphone port is called 'output-headset' and 'output-headphone'.
- * On the desktop this is usually called 'analog-output-headphones' */
- // look if it's a headset/headphones
- if (sink.name == "indicator_sound_test_headphones" ||
- (sink.active_port != null &&
- (sink.active_port.name.contains("headset") ||
- sink.active_port.name.contains("headphone")))) {
- _active_port_headphone = true;
- // check if it's a bluetooth device
- var device_bus = sink.proplist.gets ("device.bus");
- if (device_bus != null && device_bus == "bluetooth") {
- ret_output = VolumeControl.ActiveOutput.BLUETOOTH_HEADPHONES;
- } else if (device_bus != null && device_bus == "usb") {
- ret_output = VolumeControl.ActiveOutput.USB_HEADPHONES;
- } else if (device_bus != null && device_bus == "hdmi") {
- ret_output = VolumeControl.ActiveOutput.HDMI_HEADPHONES;
- } else {
- ret_output = VolumeControl.ActiveOutput.HEADPHONES;
- }
- } else {
- // speaker
- _active_port_headphone = false;
- var device_bus = sink.proplist.gets ("device.bus");
- if (device_bus != null && device_bus == "bluetooth") {
- ret_output = VolumeControl.ActiveOutput.BLUETOOTH_SPEAKER;
- } else if (device_bus != null && device_bus == "usb") {
- ret_output = VolumeControl.ActiveOutput.USB_SPEAKER;
- } else if (device_bus != null && device_bus == "hdmi") {
- ret_output = VolumeControl.ActiveOutput.HDMI_SPEAKER;
- } else {
- ret_output = VolumeControl.ActiveOutput.SPEAKERS;
- }
- }
-
- return ret_output;
- }
-
/* PulseAudio logic*/
private void context_events_cb (Context c, Context.SubscriptionEventType t, uint32 index)
{
@@ -245,20 +201,18 @@ public class VolumeControlPulse : VolumeControl
this.notify_property ("is-playing");
}
- // store the current status of the active output
- VolumeControl.ActiveOutput active_output_before = active_output;
-
- // calculate the output
- _active_output = calculate_active_output (i);
-
- // check if the output has changed, if so... emit a signal
- VolumeControl.ActiveOutput active_output_now = active_output;
- if (active_output_now != active_output_before) {
- this.active_output_changed (active_output_now);
- if (active_output_now == VolumeControl.ActiveOutput.SPEAKERS) {
- _high_volume_approved = false;
- }
- update_high_volume();
+ /* Check if the current active port is headset/headphone */
+ /* There is not easy way to check if the port is a headset/headphone besides
+ * checking for the port name. On touch (with the pulseaudio droid element)
+ * the headset/headphone port is called 'output-headset' and 'output-headphone'.
+ * On the desktop this is usually called 'analog-output-headphones' */
+ if (i.active_port != null &&
+ (i.active_port.name == "output-wired_headset" ||
+ i.active_port.name == "output-wired_headphone" ||
+ i.active_port.name == "analog-output-headphones")) {
+ _active_port_headphone = true;
+ } else {
+ _active_port_headphone = false;
}
if (_pulse_use_stream_restore == false &&
@@ -524,8 +478,7 @@ public class VolumeControlPulse : VolumeControl
this.context = new PulseAudio.Context (loop.get_api(), null, props);
this.context.set_state_callback (context_state_callback);
- var server_string = Environment.get_variable("PULSE_SERVER");
- if (context.connect(server_string, Context.Flags.NOFAIL, null) < 0)
+ if (context.connect(null, Context.Flags.NOFAIL, null) < 0)
warning( "pa_context_connect() failed: %s\n", PulseAudio.strerror(context.errno()));
}
@@ -582,14 +535,6 @@ public class VolumeControlPulse : VolumeControl
}
}
- public override VolumeControl.ActiveOutput active_output
- {
- get
- {
- return _active_output;
- }
- }
-
/* Volume operations */
private static PulseAudio.Volume double_to_volume (double vol)
{
@@ -765,7 +710,7 @@ public class VolumeControlPulse : VolumeControl
private bool calculate_high_volume_from_volume(double volume) {
return _active_port_headphone
&& _warning_volume_enabled
- && volume > _warning_volume_norms
+ && volume >= _warning_volume_norms
&& (stream == "multimedia");
}
diff --git a/src/volume-control.vala b/src/volume-control.vala
index 8e615ea..6efac35 100644
--- a/src/volume-control.vala
+++ b/src/volume-control.vala
@@ -28,17 +28,6 @@ public abstract class VolumeControl : Object
VOLUME_STREAM_CHANGE
}
- public enum ActiveOutput {
- SPEAKERS,
- HEADPHONES,
- BLUETOOTH_HEADPHONES,
- BLUETOOTH_SPEAKER,
- USB_SPEAKER,
- USB_HEADPHONES,
- HDMI_SPEAKER,
- HDMI_HEADPHONES
- }
-
public class Volume : Object {
public double volume;
public VolumeReasons reason;
@@ -50,7 +39,6 @@ public abstract class VolumeControl : Object
public virtual bool high_volume { get { return false; } protected set { } }
public virtual bool mute { get { return false; } }
public virtual bool is_playing { get { return false; } }
- public virtual VolumeControl.ActiveOutput active_output { get { return VolumeControl.ActiveOutput.SPEAKERS; } }
private Volume _volume;
public virtual Volume volume { get { return _volume; } set { } }
public virtual double mic_volume { get { return 0.0; } set { } }
@@ -68,6 +56,4 @@ public abstract class VolumeControl : Object
v.reason = reason;
this.volume = v;
}
-
- public signal void active_output_changed (VolumeControl.ActiveOutput active_output);
}