diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 5 | ||||
-rw-r--r-- | src/dbus-shared-names.h | 37 | ||||
-rw-r--r-- | src/fetch-file.vala | 86 | ||||
-rw-r--r-- | src/metadata-menu-item.vala | 220 | ||||
-rw-r--r-- | src/mpris2-controller.vala | 286 | ||||
-rw-r--r-- | src/mpris2-watcher.vala | 2 | ||||
-rw-r--r-- | src/music-player-bridge.vala | 305 | ||||
-rw-r--r-- | src/mute-menu-item.c | 154 | ||||
-rw-r--r-- | src/mute-menu-item.h | 59 | ||||
-rw-r--r-- | src/player-controller.vala | 247 | ||||
-rw-r--r-- | src/player-item.vala | 104 | ||||
-rw-r--r-- | src/playlists-menu-item.vala | 154 | ||||
-rw-r--r-- | src/pulseaudio-mgr.c | 717 | ||||
-rw-r--r-- | src/pulseaudio-mgr.h | 33 | ||||
-rw-r--r-- | src/scrub-menu-item.vala | 56 | ||||
-rw-r--r-- | src/settings-manager.vala | 136 | ||||
-rw-r--r-- | src/slider-menu-item.c | 258 | ||||
-rw-r--r-- | src/slider-menu-item.h | 64 | ||||
-rw-r--r-- | src/sound-state.c | 43 | ||||
-rw-r--r-- | src/sound-state.h | 31 | ||||
-rw-r--r-- | src/specific-items-manager.vala | 109 | ||||
-rw-r--r-- | src/transport-menu-item.vala | 97 | ||||
-rw-r--r-- | src/voip-input-menu-item.c | 278 |
23 files changed, 0 insertions, 3481 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 083c5c2..84ee0f1 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,7 +1,6 @@ libexec_PROGRAMS = indicator-sound-service indicator_sound_service_SOURCES = \ - common-defs.h \ service.vala \ main.vala \ volume-control.vala \ @@ -16,13 +15,9 @@ indicator_sound_service_VALAFLAGS = \ --vapidir=$(top_srcdir)/vapi/ \ --vapidir=./ \ --thread \ - --pkg gee-1.0 \ - --pkg Dbusmenu-0.4 \ - --pkg common-defs \ --pkg config \ --pkg gio-2.0 \ --pkg gio-unix-2.0 \ - --pkg gdk-pixbuf-2.0 \ --pkg libxml-2.0 \ --pkg libpulse \ --pkg libpulse-mainloop-glib \ diff --git a/src/dbus-shared-names.h b/src/dbus-shared-names.h deleted file mode 100644 index 2517eb9..0000000 --- a/src/dbus-shared-names.h +++ /dev/null @@ -1,37 +0,0 @@ -/* -A small wrapper utility to load indicators and put them as menu items -into the gnome-panel using it's applet interface. - -Copyright 2010 Canonical Ltd. - -Authors: - Conor Curran <conor.curran@canonical.com> - Ted Gould <ted@canonical.com> - -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 <http://www.gnu.org/licenses/>. -*/ - - -#ifndef __DBUS_SHARED_NAMES_H__ -#define __DBUS_SHARED_NAMES_H__ - -#define INDICATOR_SOUND_DBUS_NAME "com.canonical.indicator.sound" -#define INDICATOR_SOUND_MENU_DBUS_OBJECT_PATH "/com/canonical/indicator/sound/menu" -#define INDICATOR_SOUND_SERVICE_DBUS_OBJECT_PATH "/com/canonical/indicator/sound/service" -#define INDICATOR_SOUND_DBUS_INTERFACE "com.canonical.indicator.sound" -#define INDICATOR_SOUND_DBUS_VERSION 0 - -#define INDICATOR_SOUND_SIGNAL_STATE_UPDATE "SoundStateUpdate" - - -#endif /* __DBUS_SHARED_NAMES_H__ */ diff --git a/src/fetch-file.vala b/src/fetch-file.vala deleted file mode 100644 index e94afef..0000000 --- a/src/fetch-file.vala +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (C) 2010 Canonical, Ltd. - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License - * version 3.0 as published by the Free Software Foundation. - * - * This library 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 version 3.0 for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. If not, see - * <http://www.gnu.org/licenses/>. - * - * Authors - * Gordon Allott <gord.allott@canonical.com> - * Conor Curran <conor.curran@canonical.com> - */ - -public class FetchFile : Object -{ - /* public variables */ - public string uri {get; construct;} - public string intended_property {get; construct;} - - /* private variables */ - private DataInputStream stream; - private File? file; - private ByteArray data; - - /* public signals */ - public signal void failed (); - public signal void completed (ByteArray data, string property); - - public FetchFile (string uri, string prop) - { - Object (uri: uri, intended_property: prop); - } - - construct - { - this.file = File.new_for_uri(this.uri); - this.data = new ByteArray (); - } - - public async void fetch_data () - { - try { - this.stream = new DataInputStream(this.file.read(null)); - this.stream.set_byte_order (DataStreamByteOrder.LITTLE_ENDIAN); - } catch (GLib.Error e) { - this.failed (); - } - this.read_something_async (); - } - - private async void read_something_async () - { - ssize_t size = 1024; - uint8[] buffer = new uint8[size]; - - ssize_t bufsize = 1; - do { - try { - bufsize = yield this.stream.read_async (buffer, GLib.Priority.DEFAULT, null); - if (bufsize < 1) { break;} - - if (bufsize != size) - { - uint8[] cpybuf = new uint8[bufsize]; - Memory.copy (cpybuf, buffer, bufsize); - this.data.append (cpybuf); - } - else - { - this.data.append (buffer); - } - } catch (Error e) { - this.failed (); - } - } while (bufsize > 0); - this.completed (this.data, this.intended_property); - } -} diff --git a/src/metadata-menu-item.vala b/src/metadata-menu-item.vala deleted file mode 100644 index b2dd752..0000000 --- a/src/metadata-menu-item.vala +++ /dev/null @@ -1,220 +0,0 @@ -/* -Copyright 2010 Canonical Ltd. - -Authors: - Conor Curran <conor.curran@canonical.com> - -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 <http://www.gnu.org/licenses/>. -*/ - -using Gee; -using Dbusmenu; -using DbusmenuMetadata; -using Gdk; - -public class MetadataMenuitem : PlayerItem -{ - public const string ALBUM_ART_DIR_SUFFIX = "indicator/sound/album-art-cache"; - - public static string album_art_cache_dir; - private static FetchFile fetcher; - private string previous_temp_album_art_path; - - public MetadataMenuitem (PlayerController parent) - { - Object(item_type: MENUITEM_TYPE, owner: parent); - } - - construct{ - MetadataMenuitem.clean_album_art_temp_dir(); - this.previous_temp_album_art_path = null; - this.album_art_cache_dir = MetadataMenuitem.create_album_art_temp_dir(); - //debug ("JUST ABOUT TO ATTEMPT PLAYER NAME SETTING %s", this.owner.app_info.get_name()); - this.property_set (MENUITEM_PLAYER_NAME, this.owner.app_info.get_name()); - this.property_set (MENUITEM_PLAYER_ICON, this.owner.icon_name); - this.property_set_bool (MENUITEM_PLAYER_RUNNING, false); - this.property_set_bool (MENUITEM_HIDE_TRACK_DETAILS, true); - reset (relevant_attributes_for_ui()); - } - - private static void clean_album_art_temp_dir() - { - string path = GLib.Path.build_filename(Environment.get_user_cache_dir(), ALBUM_ART_DIR_SUFFIX); - - GLib.File? album_art_dir = GLib.File.new_for_path(path); - - if(delete_album_art_contents(album_art_dir) == false) - { - warning("could not remove the temp album art files %s", path); - } - } - - private static string? create_album_art_temp_dir() - { - string path = GLib.Path.build_filename(Environment.get_user_cache_dir(), ALBUM_ART_DIR_SUFFIX); - if(DirUtils.create_with_parents(path, 0700) == -1){ - warning("could not create temp dir %s for remote album art, it must have been created already", path); - } - return path; - } - - private static bool delete_album_art_contents (GLib.File dir) - { - bool result = true; - try { - var e = dir.enumerate_children (FILE_ATTRIBUTE_STANDARD_NAME, - FileQueryInfoFlags.NOFOLLOW_SYMLINKS, - null); - while (true) - { - var file = e.next_file (null); - - if (file == null) - break; - - debug("file name = %s", file.get_name()); - - var child = dir.get_child (file.get_name ()); - - try { - child.delete (null); - } catch (Error error_) { - warning (@"Unable to delete file '$(child.get_basename ()): $(error_.message)"); - result = false; - } - } - } catch (Error error) { - warning (@"Unable to read files from directory '$(dir.get_basename ())': %s", - error.message); - result = false; - } - return result; - } - - public void fetch_art(string uri, string prop) - { - File art_file = File.new_for_uri(uri); - if (art_file.is_native() == true){ - if (art_file.query_exists() == false){ - // Can't load the image, set prop to empty and return. - this.property_set_int ( prop, EMPTY ); - return; - } - string path; - try{ - path = Filename.from_uri ( uri.strip() ); - debug ("Populating the artwork field with %s", uri.strip()); - this.property_set ( prop, path ); - } - catch(ConvertError e){ - warning("Problem converting URI %s to file path", - uri); - } - // eitherway return, the artwork was local - return; - } - debug("fetch_art -remotely %s", this.album_art_cache_dir); - // If we didn't manage to create the temp dir - // don't bother with remote - if(this.album_art_cache_dir == null){ - return; - } - // green light to go remote - this.fetcher = new FetchFile (uri, prop); - this.fetcher.failed.connect (() => { this.on_fetcher_failed ();}); - this.fetcher.completed.connect (this.on_fetcher_completed); - this.fetcher.fetch_data (); - } - - private void on_fetcher_failed () - { - warning("on_fetcher_failed -> could not fetch artwork"); - } - - private void on_fetcher_completed(ByteArray update, string property) - { - try{ - PixbufLoader loader = new PixbufLoader (); - loader.write (update.data); - loader.close (); - Pixbuf icon = loader.get_pixbuf (); - string path = this.album_art_cache_dir.concat("/downloaded-coverart-XXXXXX"); - int r = FileUtils.mkstemp(path); - if(r != -1){ - icon.save (path, loader.get_format().get_name()); - this.property_set(property, path); - if(this.previous_temp_album_art_path != null){ - FileUtils.remove(this.previous_temp_album_art_path); - } - this.previous_temp_album_art_path = path; - } - } - catch(GLib.Error e){ - warning("Problem creating file from bytearray fetched from the interweb - error: %s", - e.message); - } - } - - public override void handle_event (string name, - Variant input_value, - uint timestamp) - { - if(this.owner.current_state == PlayerController.state.OFFLINE) - { - this.owner.instantiate(); - } - else if(this.owner.current_state == PlayerController.state.CONNECTED){ - this.owner.mpris_bridge.expose(); - } - } - - public void alter_label (string? new_title) - { - if (new_title == null) return; - this.property_set (MENUITEM_PLAYER_NAME, new_title); - } - - public void toggle_active_triangle (bool update) - { - debug ("toggle active triangle"); - this.property_set_bool (MENUITEM_PLAYER_RUNNING, update); - } - - public void should_collapse(bool collapse) - { - this.property_set_bool (MENUITEM_HIDE_TRACK_DETAILS, collapse); - } - - public static HashSet<string> attributes_format() - { - HashSet<string> attrs = new HashSet<string>(); - attrs.add(MENUITEM_TITLE); - attrs.add(MENUITEM_ARTIST); - attrs.add(MENUITEM_ALBUM); - attrs.add(MENUITEM_ARTURL); - attrs.add(MENUITEM_PLAYER_NAME); - attrs.add(MENUITEM_PLAYER_ICON); - attrs.add(MENUITEM_PLAYER_RUNNING); - return attrs; - } - - public static HashSet<string> relevant_attributes_for_ui() - { - HashSet<string> attrs = new HashSet<string>(); - attrs.add(MENUITEM_TITLE); - attrs.add(MENUITEM_ARTIST); - attrs.add(MENUITEM_ALBUM); - attrs.add(MENUITEM_ARTURL); - return attrs; - } -} diff --git a/src/mpris2-controller.vala b/src/mpris2-controller.vala deleted file mode 100644 index 2cc8d12..0000000 --- a/src/mpris2-controller.vala +++ /dev/null @@ -1,286 +0,0 @@ -/* -Copyright 2010 Canonical Ltd. - -Authors: - Conor Curran <conor.curran@canonical.com> - -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 <http://www.gnu.org/licenses/>. -*/ -using Dbusmenu; -using Transport; - -public class Mpris2Controller : GLib.Object -{ - public const int MAX_PLAYLIST_COUNT = 100; - - public MprisRoot mpris2_root {get; construct;} - public MprisPlayer player {get; construct;} - public MprisPlaylists playlists {get; construct;} - public FreeDesktopProperties properties_interface {get; construct;} - public PlayerController owner {get; construct;} - - public Mpris2Controller(PlayerController ctrl) - { - GLib.Object(owner: ctrl); - } - - construct{ - try { - this.mpris2_root = Bus.get_proxy_sync ( BusType.SESSION, - this.owner.dbus_name, - "/org/mpris/MediaPlayer2" ); - this.player = Bus.get_proxy_sync ( BusType.SESSION, - this.owner.dbus_name, - "/org/mpris/MediaPlayer2" ); - this.properties_interface = Bus.get_proxy_sync ( BusType.SESSION, - "org.freedesktop.Properties.PropertiesChanged", - "/org/mpris/MediaPlayer2" ); - this.properties_interface.PropertiesChanged.connect ( property_changed_cb ); - if ( this.owner.use_playlists == true ){ - this.playlists = Bus.get_proxy_sync ( BusType.SESSION, - this.owner.dbus_name, - "/org/mpris/MediaPlayer2" ); - this.playlists.PlaylistChanged.connect (on_playlistdetails_changed); - } - } - catch (IOError e) { - critical("Problems connecting to the session bus - %s", e.message); - } - } - /* - * property_changed_cb - * Called when a property changed signal is emitted from any of mpris - * objects on the bus. - * Note that the signal will be received by each instance for each player - * and at that moment there is no way to know what player that signal - * came from therefore it is necessary to query each relevant property - * to update the respective dbusmenuitem property inorder to keep the UI in sync - * Please also note due to some race condition in the depths of gdbus - * a timeout is needed between receiving the prop update and query the respective property. - * This can be seen at various points below. - */ - public void property_changed_cb ( string interface_source, - HashTable<string, Variant?> changed_properties, - string[] invalid ) - { - if ( changed_properties == null || - interface_source.has_prefix ( MPRIS_PREFIX ) == false ){ - warning("Property-changed hash is null or this is an interface that doesn't concern us"); - return; - } - Variant? play_v = changed_properties.lookup("PlaybackStatus"); - if(play_v != null){ - string state = this.player.PlaybackStatus; - Timeout.add ( 200, ensure_correct_playback_status ); - Transport.State p = (Transport.State)this.determine_play_state(state); - (this.owner.custom_items[PlayerController.widget_order.TRANSPORT] as TransportMenuitem).change_play_state(p); - } - Variant? meta_v = changed_properties.lookup("Metadata"); - if(meta_v != null) - { - Timeout.add ( 200, ensure_correct_metadata ); - } - Variant? playlist_v = changed_properties.lookup("ActivePlaylist"); - if ( playlist_v != null && this.owner.use_playlists == true ){ - Timeout.add (500, this.fetch_active_playlist); - } - Variant? playlist_count_v = changed_properties.lookup("PlaylistCount"); - if ( playlist_count_v != null && this.owner.use_playlists == true ){ - this.fetch_playlists.begin(); - this.fetch_active_playlist(); - } - Variant? playlist_orderings_v = changed_properties.lookup("Orderings"); - if ( playlist_orderings_v != null && this.owner.use_playlists == true ){ - this.fetch_playlists.begin(); - this.fetch_active_playlist(); - } - Variant? identity_v = changed_properties.lookup("Identity"); - if (identity_v != null){ - MetadataMenuitem md = this.owner.custom_items[PlayerController.widget_order.METADATA] as MetadataMenuitem; - md.alter_label (this.mpris2_root.Identity); - } - } - - private bool ensure_correct_metadata () - { - GLib.HashTable<string, Variant?> changed_updates = clean_metadata(); - PlayerItem metadata = this.owner.custom_items[PlayerController.widget_order.METADATA]; - metadata.reset (MetadataMenuitem.relevant_attributes_for_ui()); - metadata.update ( changed_updates, - MetadataMenuitem.relevant_attributes_for_ui()); - MetadataMenuitem md = this.owner.custom_items[PlayerController.widget_order.METADATA] as MetadataMenuitem; - bool collapsing = !metadata.populated(MetadataMenuitem.relevant_attributes_for_ui()); - md.should_collapse(collapsing); - - return false; - } - - private bool ensure_correct_playback_status() - { - Transport.State p = (Transport.State)this.determine_play_state(this.player.PlaybackStatus); - (this.owner.custom_items[PlayerController.widget_order.TRANSPORT] as TransportMenuitem).change_play_state(p); - return false; - } - - private GLib.HashTable<string, Variant?>? clean_metadata() - { - GLib.HashTable<string, Variant?> changed_updates = this.player.Metadata; - - Variant? artist_v = this.player.Metadata.lookup("xesam:artist"); - if(artist_v != null){ - string display_artists; - // Accomodate Spotify (should return 'as' and not 's') - if(artist_v.get_type_string() == "s"){ - display_artists = artist_v.get_string(); - } - else{ - string[] artists = artist_v.dup_strv(); - display_artists = string.joinv(", ", artists); - } - changed_updates.replace("xesam:artist", display_artists); - } - return changed_updates; - } - - private Transport.State determine_play_state(string? status){ - if(status != null && status == "Playing"){ - return Transport.State.PLAYING; - } - return Transport.State.PAUSED; - } - - public void initial_update() - { - Transport.State update; - - if(this.player.PlaybackStatus == null){ - update = Transport.State.PAUSED; - } - else{ - update = determine_play_state (this.player.PlaybackStatus); - } - if (this.mpris2_root.Identity != null){ - MetadataMenuitem md = this.owner.custom_items[PlayerController.widget_order.METADATA] as MetadataMenuitem; - md.alter_label (this.mpris2_root.Identity); - } - (this.owner.custom_items[PlayerController.widget_order.TRANSPORT] as TransportMenuitem).change_play_state (update); - GLib.HashTable<string, Value?>? cleaned_metadata = this.clean_metadata(); - this.owner.custom_items[PlayerController.widget_order.METADATA].update (cleaned_metadata, - MetadataMenuitem.attributes_format()); - - if ( this.owner.use_playlists == true ){ - this.fetch_playlists.begin(); - this.fetch_active_playlist(); - } - } - - public void transport_update(Transport.Action command) - { - if(command == Transport.Action.PLAY_PAUSE){ - this.player.PlayPause.begin(); - } - else if(command == Transport.Action.PREVIOUS){ - this.player.Previous.begin(); - } - else if(command == Transport.Action.NEXT){ - this.player.Next.begin(); - } - else if(command == Transport.Action.REWIND){ - this.player.Seek.begin(-500000); - } - else if(command == Transport.Action.FORWIND){ - this.player.Seek.begin(400000); - } - } - - public bool connected() - { - return (this.player != null && this.mpris2_root != null); - } - - public void expose() - { - if(this.connected() == true){ - this.mpris2_root.Raise.begin(); - } - } - - private void on_playlistdetails_changed (PlaylistDetails details) - { - PlaylistsMenuitem playlists_item = this.owner.custom_items[PlayerController.widget_order.PLAYLISTS] as PlaylistsMenuitem; - playlists_item.update_individual_playlist (details); - } - - public async void fetch_playlists() - { - PlaylistDetails[] current_playlists = null; - - try{ - current_playlists = yield this.playlists.GetPlaylists (0, - MAX_PLAYLIST_COUNT, - "Alphabetical", - false); - } - catch (IOError e){ - return; - } - - if( current_playlists != null ){ - PlaylistsMenuitem playlists_item = this.owner.custom_items[PlayerController.widget_order.PLAYLISTS] as PlaylistsMenuitem; - playlists_item.update(current_playlists); - } - else{ - warning(" Playlists are on but %s is returning no current_playlists ?", - this.owner.app_info.get_name()); - this.owner.use_playlists = false; - } - } - - private bool validate_playlists_details() - { - if (this.playlists.ActivePlaylist == null){ - return false; - } - if (this.playlists.ActivePlaylist.valid == false){ - return false; - } - if (this.playlists.ActivePlaylist.details == null){ - return false; - } - if (this.playlists.ActivePlaylist.details.path == null || - this.playlists.ActivePlaylist.details.name == null){ - return false; - } - return true; - } - - private bool fetch_active_playlist() - { - if (this.validate_playlists_details() == false){ - return false; - } - PlaylistsMenuitem playlists_item = this.owner.custom_items[PlayerController.widget_order.PLAYLISTS] as PlaylistsMenuitem; - playlists_item.active_playlist_update ( this.playlists.ActivePlaylist.details ); - return false; - } - - public void activate_playlist (ObjectPath path) - { - try{ - this.playlists.ActivatePlaylist.begin(path); - } - catch(IOError e){ - warning ("Could not activate playlist %s because %s", (string)path, e.message); - } - } -} diff --git a/src/mpris2-watcher.vala b/src/mpris2-watcher.vala index 4ab75c8..740089d 100644 --- a/src/mpris2-watcher.vala +++ b/src/mpris2-watcher.vala @@ -104,8 +104,6 @@ public class Mpris2Watcher : GLib.Object { string name, previous_owner, current_owner; - message ("xyxp"); - parameters.get ("(sss)", out name, out previous_owner, out current_owner); MprisRoot? mpris2_root = this.create_mpris_root (name); diff --git a/src/music-player-bridge.vala b/src/music-player-bridge.vala deleted file mode 100644 index 59ced36..0000000 --- a/src/music-player-bridge.vala +++ /dev/null @@ -1,305 +0,0 @@ -/* -Copyright 2010 Canonical Ltd. - -Authors: - Conor Curran <conor.curran@canonical.com> - -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 <http://www.gnu.org/licenses/>. -*/ - -using Dbusmenu; -using Gee; -using GLib; - -public class MusicPlayerBridge : GLib.Object -{ - const int DEVICE_ITEMS_COUNT = 3; - - private SettingsManager settings_manager; - private Dbusmenu.Menuitem root_menu; - private HashMap<string, PlayerController> registered_clients; - private HashMap<string, string> file_monitors; - private HashMap<string, string> mpris_to_desktop; - private Mpris2Watcher watcher; - - public MusicPlayerBridge() - { - } - - construct{ - this.registered_clients = new HashMap<string, PlayerController> (); - this.file_monitors = new HashMap<string, string> (); - this.mpris_to_desktop = new HashMap<string, string> (); - this.settings_manager = new SettingsManager(); - this.settings_manager.blacklist_updates.connect ( this.on_blacklist_update ); - this.settings_manager.preferred_updates.connect ( this.on_preferred_update ); - } - - private void on_blacklist_update ( string[] blacklist ) - { - debug("some blacklist update"); - - foreach(var desktop_id in blacklist){ - string key = desktop_id; - if (this.registered_clients.has_key (key)){ - debug ("Apparently %s is now blacklisted - remove thy self", key); - this.registered_clients[key].remove_from_menu(); - this.registered_clients.unset (key); - } - } - // double check present players to ensure dynamic removal/addition - this.watcher.check_for_active_clients.begin(); - } - - private void on_preferred_update ( Gee.ArrayList<string> preferred ) - { - debug ("Preferred players update. Clearing current preferred players..."); - - foreach (var player_controller in this.registered_clients.values) { - player_controller.set_as_preferred (false); - } - - foreach (var desktop_id in preferred) { - string key = desktop_id; - if (this.registered_clients.has_key (key)) { - debug ("Setting %s as preferred player", key); - this.registered_clients[key].set_as_preferred (true); - } - } - } - - private void try_to_add_inactive_familiar_clients() - { - var preferred_players = this.settings_manager.fetch_preferred (); - foreach ( string desktop in this.settings_manager.fetch_interested()){ - debug ( "interested client found : %s", desktop ); - AppInfo? app_info = create_app_info ( desktop.concat( ".desktop" ) ); - if ( app_info == null ){ - warning ( "Could not create app_info for path %s \n Getting out of here ", - desktop ); - continue; - } - bool is_preferred = desktop in preferred_players; - PlayerController ctrl = new PlayerController ( this.root_menu, - app_info, - null, - this.fetch_icon_name(desktop), - calculate_menu_position(), - null, - PlayerController.state.OFFLINE, - is_preferred ); - var mpris_key = desktop; - this.registered_clients.set(mpris_key, ctrl); - this.establish_file_monitoring (app_info, mpris_key); - } - } - - private void establish_file_monitoring (AppInfo info, string mpris_key){ - DesktopAppInfo desktop_info = info as DesktopAppInfo; - var file_path = desktop_info.get_filename (); - File f = File.new_for_path (file_path); - try { - FileMonitor monitor = f.monitor (FileMonitorFlags.SEND_MOVED, null); - unowned FileMonitor weak_monitor = monitor; - monitor.changed.connect ((desktop_file, other_file, event_type) => { - this.relevant_desktop_file_changed (desktop_file, other_file, event_type, weak_monitor); - }); - monitor.ref(); // will be unref()ed by relevant_desktop_file_changed() - GLib.debug ("monitoring file '%s'", file_path); - this.file_monitors.set (file_path, mpris_key); - } - catch (Error e){ - warning ("Unable to create a file monitor for %s", info.get_name()); - return; - } - } - - private void relevant_desktop_file_changed (File desktop_file, - File? other_file, - FileMonitorEvent event_type, - FileMonitor monitor) - { - if (event_type != FileMonitorEvent.DELETED) - return; - - string? path = desktop_file.get_path (); - if (path == null){ - warning ("relevant_desktop_file_changed is returning a file with no path !"); - return; - } - if (!this.file_monitors.has_key (path)){ - warning ("relevant_desktop_file_changed is returning a file which we know nothing about - %s", - path); - return; - } - - var mpris_key = this.file_monitors[path]; - GLib.debug ("file \"%s\" was removed; stopping monitoring \"%s\"", path, mpris_key); - this.registered_clients[mpris_key].remove_from_menu(); - this.settings_manager.remove_interested (mpris_key); - this.registered_clients.unset (mpris_key); - monitor.cancel (); - monitor.unref(); - } - - private int calculate_menu_position() - { - if(this.registered_clients.size == 0){ - return DEVICE_ITEMS_COUNT; - } - else{ - return (DEVICE_ITEMS_COUNT + (this.registered_clients.size * PlayerController.WIDGET_QUANTITY)); - } - } - - public void client_has_become_available ( string desktop, - string dbus_name, - bool use_playlists ) - { - if (desktop == null || desktop == ""){ - warning("Client %s attempting to register without desktop entry being set on the mpris root", - dbus_name); - return; - } - if (desktop in this.settings_manager.fetch_blacklist()) { - debug ("Client %s attempting to register but I'm afraid it is blacklisted", - desktop); - return; - } - - debug ( "client_has_become_available %s", desktop ); - AppInfo? app_info = create_app_info ( desktop.concat( ".desktop" ) ); - if ( app_info == null ){ - warning ( "Could not create app_info for path %s \n Getting out of here ", - desktop ); - return; - } - - var mpris_key = desktop; - bool is_preferred = desktop in this.settings_manager.fetch_preferred (); - - mpris_to_desktop.set (dbus_name, desktop); - if ( this.registered_clients.has_key (mpris_key) == false ){ - debug("New client has registered that we have not seen before: %s", dbus_name ); - PlayerController ctrl = new PlayerController ( this.root_menu, - app_info, - dbus_name, - this.fetch_icon_name(desktop), - this.calculate_menu_position(), - use_playlists, - PlayerController.state.READY, - is_preferred); - this.registered_clients.set ( mpris_key, ctrl ); - debug ( "Have not seen this %s before, new controller created.", desktop ); - this.settings_manager.add_interested ( desktop ); - this.establish_file_monitoring (app_info, mpris_key); - debug ( "application added to the interested list" ); - } - else{ - this.registered_clients[mpris_key].use_playlists = use_playlists; - this.registered_clients[mpris_key].update_state ( PlayerController.state.READY ); - this.registered_clients[mpris_key].activate ( dbus_name ); - debug("Application has already registered - awaken the hibernation: %s with playlists %s \n", dbus_name, use_playlists.to_string() ); - } - } - - public void client_has_vanished ( string mpris_root_interface ) - { - debug("\n MusicPlayerBridge -> client with dbus interface %s has vanished", - mpris_root_interface ); - if (root_menu != null){ - debug("\n attempt to remove %s", mpris_root_interface); - if (mpris_to_desktop.has_key(mpris_root_interface)){ - var mpris_key = mpris_to_desktop[mpris_root_interface]; - mpris_to_desktop.unset(mpris_root_interface); - if ( mpris_key != null && this.registered_clients.has_key(mpris_key)){ - registered_clients[mpris_key].hibernate(); - debug("\n Successively offlined client %s", mpris_key); - } - } - } - } - - public void set_root_menu_item ( Dbusmenu.Menuitem menu ) - { - this.root_menu = menu; - this.try_to_add_inactive_familiar_clients(); - this.watcher = new Mpris2Watcher (); - this.watcher.client_appeared.connect (this.client_has_become_available); - this.watcher.client_disappeared.connect (this.client_has_vanished); - } - - public void enable_player_specific_items_for_client (string object_path, - string desktop_id) - { - var mpris_key = desktop_id; - if (this.registered_clients.has_key (mpris_key) == false){ - warning ("we don't have a client with desktop id %s registered", desktop_id); - return; - } - this.registered_clients[mpris_key].enable_player_specific_items(object_path); - } - - public void enable_track_specific_items_for_client (string object_path, - string desktop_id) - { - var mpris_key = desktop_id; - if (this.registered_clients.has_key (mpris_key) == false){ - warning ("we don't have a client with desktop id %s registered", desktop_id); - return; - } - this.registered_clients[mpris_key].enable_track_specific_items(object_path); - } - - private static AppInfo? create_app_info ( string desktop ) - { - DesktopAppInfo info = new DesktopAppInfo ( desktop ); - if ( desktop == null || info == null ){ - warning ( "Could not create a desktopappinfo instance from app: %s", desktop ); - return null; - } - GLib.AppInfo app_info = info as GLib.AppInfo; - return app_info; - } - - private static string? fetch_icon_name(string desktop) - { - // We know the appinfo is good because it was loaded in the previous reg step. - DesktopAppInfo info = new DesktopAppInfo ( desktop.concat( ".desktop" ) ) ; - KeyFile desktop_keyfile = new KeyFile (); - try{ - desktop_keyfile.load_from_file (info.get_filename(), KeyFileFlags.NONE); - } - catch(GLib.FileError error){ - warning("Error loading keyfile - FileError"); - return null; - } - catch(GLib.KeyFileError error){ - warning("Error loading keyfile - KeyFileError"); - return null; - } - - try{ - return desktop_keyfile.get_string (KeyFileDesktop.GROUP, - KeyFileDesktop.KEY_ICON); - } - catch(GLib.KeyFileError error){ - warning("Error trying to fetch the icon name from the keyfile"); - return null; - } - } -} - - - - diff --git a/src/mute-menu-item.c b/src/mute-menu-item.c deleted file mode 100644 index 0e6a46f..0000000 --- a/src/mute-menu-item.c +++ /dev/null @@ -1,154 +0,0 @@ -/* -Copyright 2011 Canonical Ltd. - -Authors: - Conor Curran <conor.curran@canonical.com> - -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 <http://www.gnu.org/licenses/>. -*/ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <glib/gi18n.h> - -#include "common-defs.h" -#include "mute-menu-item.h" -#include "pulseaudio-mgr.h" - -typedef struct _MuteMenuItemPrivate MuteMenuItemPrivate; - -struct _MuteMenuItemPrivate { - DbusmenuMenuitem* button; -}; - -#define MUTE_MENU_ITEM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), MUTE_MENU_ITEM_TYPE, MuteMenuItemPrivate)) - -/* Prototypes */ -static void mute_menu_item_class_init (MuteMenuItemClass *klass); -static void mute_menu_item_init (MuteMenuItem *self); -static void mute_menu_item_dispose (GObject *object); -static void mute_menu_item_finalize (GObject *object); -static void mute_menu_item_set_global_mute_from_ui (gpointer user_data); - -G_DEFINE_TYPE (MuteMenuItem, mute_menu_item, G_TYPE_OBJECT); - -static void -mute_menu_item_class_init (MuteMenuItemClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - g_type_class_add_private (klass, sizeof (MuteMenuItemPrivate)); - - object_class->dispose = mute_menu_item_dispose; - object_class->finalize = mute_menu_item_finalize; - - return; -} - -static void -mute_menu_item_init (MuteMenuItem *self) -{ - g_debug("Building new Mute Menu Item"); - MuteMenuItemPrivate* priv = MUTE_MENU_ITEM_GET_PRIVATE(self); - priv->button = NULL; - priv->button = dbusmenu_menuitem_new(); - - dbusmenu_menuitem_property_set(priv->button, - DBUSMENU_MENUITEM_PROP_TYPE, - DBUSMENU_MUTE_MENUITEM_TYPE); - - dbusmenu_menuitem_property_set_bool (priv->button, - DBUSMENU_MENUITEM_PROP_VISIBLE, - TRUE); - - g_signal_connect (G_OBJECT (priv->button), - DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, - G_CALLBACK (mute_menu_item_set_global_mute_from_ui), - self); - return; -} - -static void -mute_menu_item_dispose (GObject *object) -{ - G_OBJECT_CLASS (mute_menu_item_parent_class)->dispose (object); - return; -} - -static void -mute_menu_item_finalize (GObject *object) -{ - G_OBJECT_CLASS (mute_menu_item_parent_class)->finalize (object); -} - -static void -mute_menu_item_set_global_mute_from_ui (gpointer user_data) -{ - g_return_if_fail (DBUSMENU_IS_MENUITEM (user_data)); - DbusmenuMenuitem* button = DBUSMENU_MENUITEM (user_data); - gboolean current_value = dbusmenu_menuitem_property_get_bool (button, - DBUSMENU_MUTE_MENUITEM_VALUE); - gboolean new_value = !current_value; - pm_update_mute (new_value); -} - -void -mute_menu_item_update (MuteMenuItem* item, gboolean value_update) -{ - MuteMenuItemPrivate* priv = MUTE_MENU_ITEM_GET_PRIVATE (item); - - dbusmenu_menuitem_property_set_bool (priv->button, - DBUSMENU_MUTE_MENUITEM_VALUE, - value_update); - dbusmenu_menuitem_property_set (priv->button, - DBUSMENU_MENUITEM_PROP_LABEL, - value_update == FALSE ? _("Mute") : _("Unmute")); -} - -void -mute_menu_item_enable (MuteMenuItem* item, gboolean active) -{ - MuteMenuItemPrivate* priv = MUTE_MENU_ITEM_GET_PRIVATE (item); - dbusmenu_menuitem_property_set_bool (priv->button, - DBUSMENU_MENUITEM_PROP_VISIBLE, - TRUE); - - dbusmenu_menuitem_property_set_bool (priv->button, - DBUSMENU_MENUITEM_PROP_ENABLED, - active); -} - -DbusmenuMenuitem* -mute_menu_item_get_button (MuteMenuItem* item) -{ - MuteMenuItemPrivate* priv = MUTE_MENU_ITEM_GET_PRIVATE (item); - return priv->button; -} - -gboolean -mute_menu_item_is_muted (MuteMenuItem* item) -{ - MuteMenuItemPrivate* priv = MUTE_MENU_ITEM_GET_PRIVATE (item); - return dbusmenu_menuitem_property_get_bool (priv->button, - DBUSMENU_MUTE_MENUITEM_VALUE); -} - -MuteMenuItem* -mute_menu_item_new (gboolean initial_update, gboolean enabled) -{ - MuteMenuItem *self = g_object_new (MUTE_MENU_ITEM_TYPE, NULL); - mute_menu_item_update (self, initial_update); - mute_menu_item_enable (self, enabled); - return self; -} diff --git a/src/mute-menu-item.h b/src/mute-menu-item.h deleted file mode 100644 index 81a4b33..0000000 --- a/src/mute-menu-item.h +++ /dev/null @@ -1,59 +0,0 @@ -/* -Copyright 2010 Canonical Ltd. - -Authors: - Conor Curran <conor.curran@canonical.com> - -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 <http://www.gnu.org/licenses/>. -*/ - -#ifndef __MUTE_MENU_ITEM_H__ -#define __MUTE_MENU_ITEM_H__ - -#include <glib.h> -#include <glib-object.h> -#include <libdbusmenu-glib/menuitem.h> - -G_BEGIN_DECLS - -#define MUTE_MENU_ITEM_TYPE (mute_menu_item_get_type ()) -#define MUTE_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MUTE_MENU_ITEM_TYPE, MuteMenuItem)) -#define MUTE_MENU_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MUTE_MENU_ITEM_TYPE, MuteMenuItemClass)) -#define IS_MUTE_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MUTE_MENU_ITEM_TYPE)) -#define IS_MUTE_MENU_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MUTE_MENU_ITEM_TYPE)) -#define MUTE_MENU_ITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MUTE_MENU_ITEM_TYPE, MuteMenuItemClass)) - -typedef struct _MuteMenuItem MuteMenuItem; -typedef struct _MuteMenuItemClass MuteMenuItemClass; - -struct _MuteMenuItemClass { - GObjectClass parent_class; -}; - -struct _MuteMenuItem { - GObject parent; -}; - -GType mute_menu_item_get_type (void); - -MuteMenuItem* mute_menu_item_new (); - -void mute_menu_item_update (MuteMenuItem* item, gboolean update); -void mute_menu_item_enable (MuteMenuItem* item, gboolean active); -gboolean mute_menu_item_is_muted (MuteMenuItem* item); - -DbusmenuMenuitem* mute_menu_item_get_button (MuteMenuItem* item); - -G_END_DECLS - -#endif
\ No newline at end of file diff --git a/src/player-controller.vala b/src/player-controller.vala deleted file mode 100644 index fd66a8a..0000000 --- a/src/player-controller.vala +++ /dev/null @@ -1,247 +0,0 @@ -/* -Copyright 2010 Canonical Ltd. - -Authors: - Conor Curran <conor.curran@canonical.com> - -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 <http://www.gnu.org/licenses/>. -*/ - -using Dbusmenu; -using Gee; - -public class PlayerController : GLib.Object -{ - public const int WIDGET_QUANTITY = 4; - - public enum widget_order{ - SEPARATOR, - METADATA, - TRANSPORT, - PLAYLISTS - } - - public enum state{ - OFFLINE, - INSTANTIATING, - READY, - CONNECTED, - DISCONNECTED - } - - public int current_state = state.OFFLINE; - - public Dbusmenu.Menuitem root_menu; - public string dbus_name { get; set;} - public ArrayList<PlayerItem> custom_items; - public Mpris2Controller mpris_bridge; - public AppInfo? app_info { get; set;} - public int menu_offset { get; set;} - public string icon_name { get; set; } - public bool? use_playlists; - public bool is_preferred { get; private set; } - private SpecificItemsManager track_specific_mgr; - private SpecificItemsManager player_specific_mgr; - - public PlayerController(Dbusmenu.Menuitem root, - GLib.AppInfo app, - string? dbus_name, - string icon_name, - int offset, - bool? use_playlists, - state initial_state, - bool is_preferred) - { - this.use_playlists = use_playlists; - this.root_menu = root; - this.app_info = app; - this.dbus_name = dbus_name; - this.icon_name = icon_name; - this.custom_items = new ArrayList<PlayerItem>(); - this.current_state = initial_state; - this.menu_offset = offset; - this.is_preferred = is_preferred; - - this.construct_widgets(); - this.establish_mpris_connection(); - this.update_layout(); - debug ("New player controller for %s with icon name %s", this.app_info.get_name(), this.icon_name); - } - - public void update_state(state new_state) - { - debug("update_state - player controller %s : new state %i", this.app_info.get_name(), - new_state); - this.current_state = new_state; - this.update_layout(); - } - - public void activate( string dbus_name ) - { - this.dbus_name = dbus_name; - this.establish_mpris_connection(); - } - - /* - instantiate() - The user should be able to start the app from the transport bar when in an offline state - There is a need to wait before the application is on DBus before attempting to access its mpris address - Hence only when the it has registered with us via libindicate do we attempt to kick off mpris communication - */ - public void instantiate() - { - debug("instantiate in player controller for %s", this.app_info.get_name() ); - try{ - this.app_info.launch(null, null); - this.update_state(state.INSTANTIATING); - } - catch(GLib.Error error){ - warning("Failed to launch app %s with error message: %s", this.app_info.get_name(), - error.message ); - } - } - - public void enable_track_specific_items (string object_path) - { - if (this.track_specific_mgr == null){ - track_specific_mgr = new SpecificItemsManager (this, - object_path, - SpecificItemsManager.category.TRACK); - } - } - - public void enable_player_specific_items (string object_path) - { - if (this.player_specific_mgr == null){ - player_specific_mgr = new SpecificItemsManager (this, - object_path, - SpecificItemsManager.category.PLAYER); - } - } - - public int track_specific_count () - { - if (this.track_specific_mgr == null) { - return 0; - } - return this.track_specific_mgr.proxy_items.size; - } - - private void establish_mpris_connection() - { - if(this.current_state != state.READY || this.dbus_name == null ){ - debug("establish_mpris_connection - Not ready to connect"); - return; - } - debug ( " establish mpris connection - use playlists value = %s ", - this.use_playlists.to_string() ); - this.mpris_bridge = new Mpris2Controller (this); - this.determine_state (); - } - - public void remove_from_menu() - { - foreach(PlayerItem item in this.custom_items){ - this.root_menu.child_delete(item); - } - if (this.use_playlists == true){ - PlaylistsMenuitem playlists_menuitem = this.custom_items[widget_order.PLAYLISTS] as PlaylistsMenuitem; - this.root_menu.child_delete (playlists_menuitem.root_item); - } - } - - public void set_as_preferred (bool val) { - this.is_preferred = val; - this.update_layout(); - } - - public void hibernate() - { - update_state(PlayerController.state.OFFLINE); - TransportMenuitem transport = this.custom_items[widget_order.TRANSPORT] as TransportMenuitem; - transport.change_play_state (Transport.State.PAUSED); - this.custom_items[widget_order.METADATA].reset(MetadataMenuitem.relevant_attributes_for_ui()); - MetadataMenuitem md = this.custom_items[widget_order.METADATA] as MetadataMenuitem; - md.toggle_active_triangle (false); - this.mpris_bridge = null; - } - - public void update_layout() - { - PlaylistsMenuitem playlists_menuitem = this.custom_items[widget_order.PLAYLISTS] as PlaylistsMenuitem; - MetadataMenuitem metadata_menuitem = this.custom_items[widget_order.METADATA] as MetadataMenuitem; - if(this.current_state != state.CONNECTED){ - metadata_menuitem.should_collapse (true); - playlists_menuitem.root_item.property_set_bool (MENUITEM_PROP_VISIBLE, - false); - this.custom_items[widget_order.TRANSPORT].property_set_bool (MENUITEM_PROP_VISIBLE, is_preferred); - return; - } - - bool should_collapse = !this.custom_items[widget_order.METADATA].populated (MetadataMenuitem.relevant_attributes_for_ui()); - metadata_menuitem.should_collapse (should_collapse); - - if (is_preferred){ - TransportMenuitem transport = this.custom_items[widget_order.TRANSPORT] as TransportMenuitem; - transport.handle_cached_action(); - } - else{ - this.custom_items[widget_order.TRANSPORT].property_set_bool (MENUITEM_PROP_VISIBLE, - true); - } - playlists_menuitem.root_item.property_set_bool ( MENUITEM_PROP_VISIBLE, - this.use_playlists ); - } - - private void construct_widgets() - { - // Separator item - this.custom_items.add(new PlayerItem(CLIENT_TYPES_SEPARATOR)); - - // Metadata item - MetadataMenuitem metadata_item = new MetadataMenuitem(this); - this.custom_items.add(metadata_item); - - // Transport item - TransportMenuitem transport_item = new TransportMenuitem(this); - this.custom_items.add(transport_item); - - // Playlist item - PlaylistsMenuitem playlist_menuitem = new PlaylistsMenuitem(this); - this.custom_items.add(playlist_menuitem); - - foreach(PlayerItem item in this.custom_items){ - if (this.custom_items.index_of(item) == WIDGET_QUANTITY-1) { - PlaylistsMenuitem playlists_menuitem = item as PlaylistsMenuitem; - root_menu.child_add_position(playlists_menuitem.root_item, this.menu_offset + this.custom_items.index_of(item)); - } - else{ - root_menu.child_add_position (item, - this.menu_offset + this.custom_items.index_of(item)); - } - } - } - - private void determine_state() - { - if(this.mpris_bridge.connected() == true){ - this.update_state(state.CONNECTED); - MetadataMenuitem md = this.custom_items[widget_order.METADATA] as MetadataMenuitem; - md.toggle_active_triangle(true); - this.mpris_bridge.initial_update(); - } - else{ - this.update_state(state.DISCONNECTED); - } - } -} diff --git a/src/player-item.vala b/src/player-item.vala deleted file mode 100644 index 7867653..0000000 --- a/src/player-item.vala +++ /dev/null @@ -1,104 +0,0 @@ -/* -Copyright 2010 Canonical Ltd. - -Authors: - Conor Curran <conor.curran@canonical.com> - -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 <http://www.gnu.org/licenses/>. -*/ - -using Dbusmenu; -using Gee; - -public class PlayerItem : Dbusmenu.Menuitem -{ - public PlayerController owner {get; construct;} - public string item_type { get; construct; } - public const int EMPTY = -1; - - public PlayerItem(string type) - { - Object(item_type: type); - } - - construct { - this.property_set(MENUITEM_PROP_TYPE, item_type); - } - - public void reset(HashSet<string> attrs){ - foreach(string s in attrs){ - this.property_set_int(s, EMPTY); - } - } - - /** - * update() - * Base update method for playeritems, takes the attributes and the incoming updates - * and attmepts to update the appropriate props on the object. - * Album art is handled separately to deal with remote and local file paths. - */ - public void update(HashTable<string, Variant?> data, HashSet<string> attributes) - { - //debug("PlayerItem::update()"); - if(data == null){ - warning("PlayerItem::Update -> The hashtable was null - just leave it!"); - return; - } - - foreach(string property in attributes){ - string[] input_keys = property.split("-"); - string search_key = input_keys[input_keys.length-1 : input_keys.length][0]; - //debug("search key = %s", search_key); - Variant? v = data.lookup(search_key); - - if (v == null) continue; - - if (v.is_of_type ( VariantType.STRING )){ - string update = v.get_string().strip(); - //debug("with value : %s", update); - if(property.contains("mpris:artUrl")){ - // We know its a metadata instance because thats the only - // object with the arturl prop - MetadataMenuitem metadata = this as MetadataMenuitem; - metadata.fetch_art ( update, property ); - continue; - } - this.property_set(property, update); - } - else if (v.is_of_type (VariantType.INT32 )){ - //debug("with value : %i", v.get_int32()); - this.property_set_int(property, v.get_int32()); - } - else if (v.is_of_type (VariantType.INT64 )){ - //debug("with value : %i", (int)v.get_int64()); - this.property_set_int(property, (int)v.get_int64()); - } - else if(v.is_of_type ( VariantType.BOOLEAN )){ - //debug("with value : %s", v.get_boolean().to_string()); - this.property_set_bool(property, v.get_boolean()); - } - } - } - - public bool populated(HashSet<string> attrs) - { - foreach(string prop in attrs){ - if(property_get_int(prop) != EMPTY){ - return true; - } - } - return false; - } - -} - diff --git a/src/playlists-menu-item.vala b/src/playlists-menu-item.vala deleted file mode 100644 index 4666a50..0000000 --- a/src/playlists-menu-item.vala +++ /dev/null @@ -1,154 +0,0 @@ -/* -Copyright 2010 Canonical Ltd. - -Authors: - Conor Curran <conor.curran@canonical.com> - -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 <http://www.gnu.org/licenses/>. -*/ - -using Config; -using Dbusmenu; -using DbusmenuPlaylists; -using DbusmenuPlaylist; -using Gee; - - -public class PlaylistsMenuitem : PlayerItem -{ - private HashMap<int, Dbusmenu.Menuitem> current_playlists; - public Menuitem root_item; - - public PlaylistsMenuitem ( PlayerController parent ) - { - Object ( item_type: MENUITEM_TYPE, owner: parent ); - } - - construct{ - this.current_playlists = new HashMap<int, Dbusmenu.Menuitem>(); - this.root_item = new Menuitem(); - this.root_item.property_set ( MENUITEM_PROP_LABEL, _("Choose Playlist") ); - this.root_item.property_set ( MENUITEM_PATH, "" ); - } - - public new void update (PlaylistDetails[] playlists) - { - foreach ( PlaylistDetails detail in playlists ){ - // We don't want to list playlists which are for videos)' - if (this.already_observed(detail) || this.is_video_related(detail)) - continue; - - Dbusmenu.Menuitem menuitem = new Menuitem(); - menuitem.property_set (MENUITEM_PROP_LABEL, - truncate_item_label_if_needs_be (detail.name)); - menuitem.property_set (MENUITEM_PROP_ICON_NAME, "playlist-symbolic"); - - menuitem.property_set (MENUITEM_PATH, (string)detail.path); - menuitem.property_set_bool (MENUITEM_PROP_VISIBLE, true); - menuitem.property_set_bool (MENUITEM_PROP_ENABLED, true); - - menuitem.item_activated.connect(() => { - submenu_item_activated (menuitem.id ); - } - ); - this.current_playlists.set( menuitem.id, menuitem ); - this.root_item.child_append( menuitem ); - debug ("populating valid playlists %s", detail.name); - } - // Finally remove any that might have been deleted - foreach (Dbusmenu.Menuitem item in this.current_playlists.values) { - bool within = false; - foreach (PlaylistDetails detail in playlists){ - if (detail.path == item.property_get (MENUITEM_PATH)) { - within = true; - break; - } - } - if (within == false){ - if (this.root_item.property_get (MENUITEM_PATH) == item.property_get (MENUITEM_PATH)){ - this.root_item.property_set (MENUITEM_PROP_LABEL, _("Choose Playlist")); - } - this.root_item.child_delete (item); - } - } - } - - public void update_individual_playlist (PlaylistDetails new_detail) - { - foreach ( Dbusmenu.Menuitem item in this.current_playlists.values ){ - if (new_detail.path == item.property_get (MENUITEM_PATH)){ - item.property_set (MENUITEM_PROP_LABEL, - truncate_item_label_if_needs_be (new_detail.name)); - } - } - // If its active make sure the name is updated on the root item. - if (this.root_item.property_get (MENUITEM_PATH) == new_detail.path) { - this.root_item.property_set (MENUITEM_PROP_LABEL, - truncate_item_label_if_needs_be (new_detail.name)); - } - } - - private bool already_observed (PlaylistDetails new_detail) - { - foreach ( Dbusmenu.Menuitem item in this.current_playlists.values ){ - var path = item.property_get (MENUITEM_PATH); - if (new_detail.path == path) return true; - } - return false; - } - - private bool is_video_related (PlaylistDetails new_detail) - { - var location = (string)new_detail.path; - if (location.contains ("/VideoLibrarySource/")) return true; - return false; - } - - public void active_playlist_update (PlaylistDetails detail) - { - var update = detail.name; - if ( update == "" ) update = _("Choose Playlist"); - this.root_item.property_set (MENUITEM_PROP_LABEL, - truncate_item_label_if_needs_be(update)); - this.root_item.property_set (MENUITEM_PATH, detail.path); - } - - private void submenu_item_activated (int menu_item_id) - { - if (!this.current_playlists.has_key(menu_item_id)) { - warning( "item %i was activated but we don't have a corresponding playlist", - menu_item_id ); - return; - } - this.owner.mpris_bridge.activate_playlist ( (GLib.ObjectPath)this.current_playlists[menu_item_id].property_get (MENUITEM_PATH) ); - } - - private string truncate_item_label_if_needs_be(string item_label) - { - var result = item_label; - if (item_label.char_count(-1) > 17){ - result = item_label.slice ((long)0, (long)15); - result += "…"; - } - return result; - } - - public static HashSet<string> attributes_format() - { - HashSet<string> attrs = new HashSet<string>(); - attrs.add(MENUITEM_TITLE); - attrs.add(MENUITEM_PLAYLISTS); - return attrs; - } - -} diff --git a/src/pulseaudio-mgr.c b/src/pulseaudio-mgr.c deleted file mode 100644 index f205723..0000000 --- a/src/pulseaudio-mgr.c +++ /dev/null @@ -1,717 +0,0 @@ -/* -Copyright 2011 Canonical Ltd. - -Authors: - Conor Curran <conor.curran@canonical.com> - -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 <http://www.gnu.org/licenses/>. -*/ - -/**Notes - * - * Approach now is to set up the communication channels, query the server - * fetch its default sink/source. If this fails then fetch the list of sinks/sources - * and take the first one which is not the auto-null sink. - * TODO: need to handle the situation where one chink in this linear chain breaks - * i.e. start off the process again and count the attempts (note different to - reconnect attempts) - */ -#include <pulse/gccmacro.h> -#include <pulse/glib-mainloop.h> -#include <pulse/error.h> - -#include "pulseaudio-mgr.h" -#include "config.h" - -#define RECONNECT_DELAY 5 - - -static void pm_context_state_callback(pa_context *c, void *userdata); -static void pm_subscribed_events_callback (pa_context *c, - enum pa_subscription_event_type t, - uint32_t index, - void* userdata); -static void pm_server_info_callback (pa_context *c, - const pa_server_info *info, - void *userdata); -static void pm_default_sink_info_callback (pa_context *c, - const pa_sink_info *info, - int eol, - void *userdata); -static void pm_default_source_info_callback (pa_context *c, - const pa_source_info *info, - int eol, - void *userdata); -static void pm_sink_info_callback (pa_context *c, - const pa_sink_info *sink, - int eol, - void *userdata); -static void pm_source_info_callback (pa_context *c, - const pa_source_info *info, - int eol, - void *userdata); -static void pm_update_source_info_callback (pa_context *c, - const pa_source_info *info, - int eol, - void *userdata); -static void pm_sink_input_info_callback (pa_context *c, - const pa_sink_input_info *info, - int eol, - void *userdata); -static void pm_update_device (pa_context *c, - const pa_sink_info *info, - int eol, - void *userdata); -static void pm_toggle_mute_for_every_sink_callback (pa_context *c, - const pa_sink_info *sink, - int eol, - void* userdata); -static void pm_source_output_info_callback (pa_context *c, - const pa_source_output_info *info, - int eol, - void *userdata); - -static gboolean reconnect_to_pulse (gpointer user_data); - -static gint connection_attempts = 0; -static gint reconnect_idle_id = 0; -static pa_context *pulse_context = NULL; -static pa_glib_mainloop *pa_main_loop = NULL; - -/** - Entry Point - **/ -void -pm_establish_pulse_connection (Device* device) -{ - pa_main_loop = pa_glib_mainloop_new (g_main_context_default ()); - g_assert (pa_main_loop); - reconnect_to_pulse ((gpointer)device); -} - -/** -close_pulse_activites() -Gracefully close our connection with the Pulse async library. -**/ -void close_pulse_activites() -{ - if (pulse_context != NULL) { - pa_context_unref(pulse_context); - pulse_context = NULL; - } - pa_glib_mainloop_free(pa_main_loop); - pa_main_loop = NULL; -} - -/** -reconnect_to_pulse (gpointer user_data) -Method which connects to the pulse server and is used to track reconnects. - */ -static gboolean -reconnect_to_pulse (gpointer user_data) -{ - g_debug("Attempt a pulse connection"); - g_return_val_if_fail (IS_DEVICE (user_data), FALSE); - - connection_attempts += 1; - if (pulse_context != NULL) { - pa_context_unref(pulse_context); - pulse_context = NULL; - } - - pa_proplist *proplist; - - proplist = pa_proplist_new (); - pa_proplist_sets (proplist, - PA_PROP_APPLICATION_NAME, - "Indicator Sound"); - pa_proplist_sets (proplist, - PA_PROP_APPLICATION_ID, - "com.canonical.indicator.sound"); - pa_proplist_sets (proplist, - PA_PROP_APPLICATION_ICON_NAME, - "multimedia-volume-control"); - pa_proplist_sets (proplist, - PA_PROP_APPLICATION_VERSION, - PACKAGE_VERSION); - - pulse_context = pa_context_new_with_proplist (pa_glib_mainloop_get_api( pa_main_loop ), - NULL, - proplist); - pa_proplist_free (proplist); - g_assert(pulse_context); - pa_context_set_state_callback (pulse_context, - pm_context_state_callback, - user_data); - int result = pa_context_connect (pulse_context, - NULL, - (pa_context_flags_t)PA_CONTEXT_NOFAIL, - NULL); - - if (result < 0) { - g_warning ("Failed to connect context: %s", - pa_strerror (pa_context_errno (pulse_context))); - } - if (connection_attempts > 5){ - return FALSE; - } - else{ - return TRUE; - } -} - -void -pm_update_volume (gint sink_index, pa_cvolume new_volume) -{ - if (sink_index < 0 || pulse_context == NULL){ - g_warning ("pm_update_volume sink index is negative or the context is null"); - return; - } - - if (pa_context_get_state (pulse_context) != PA_CONTEXT_READY ){ - g_warning ("pm_update_volume context is not in a ready state"); - return; - } - - pa_operation *operation = NULL; - - operation = pa_context_set_sink_volume_by_index (pulse_context, - sink_index, - &new_volume, - NULL, - NULL); - if (!operation){ - g_warning ("pm_update_volume operation failed for some reason"); - return; - } - pa_operation_unref (operation); -} - -void -pm_update_mute (gboolean update) -{ - if (pulse_context == NULL){ - g_warning ("pm_update_mute - the context is null"); - return; - } - - if (pa_context_get_state (pulse_context) != PA_CONTEXT_READY ){ - g_warning ("pm_update_mute context is not in a ready state"); - return; - } - - pa_operation *operation = NULL; - - operation = pa_context_get_sink_info_list (pulse_context, - pm_toggle_mute_for_every_sink_callback, - GINT_TO_POINTER (update)); - if (!operation){ - g_warning ("pm_update_mute operation failed for some reason"); - return; - } - pa_operation_unref (operation); -} - -void -pm_update_mic_gain (gint source_index, pa_cvolume new_gain) -{ - if (source_index < 0 || pulse_context == NULL){ - g_warning ("pm_update_mic_gain source index is negative or the context is null"); - return; - } - - if (pa_context_get_state (pulse_context) != PA_CONTEXT_READY ){ - g_warning ("pm_update_mic_gain context is not in a ready state"); - return; - } - - pa_operation *operation = NULL; - - operation = pa_context_set_source_volume_by_index (pulse_context, - source_index, - &new_gain, - NULL, - NULL); - if (!operation){ - g_warning ("pm_update_mic_gain operation failed for some reason"); - return; - } - pa_operation_unref (operation); -} - -void -pm_update_mic_mute (gint source_index, gint mute_update) -{ - if (source_index < 0){ - return; - } - - if (pa_context_get_state (pulse_context) != PA_CONTEXT_READY ){ - g_warning ("pm_update_mic_mute context is not in a ready state"); - return; - } - - pa_operation *operation = NULL; - - operation = pa_context_set_source_mute_by_index (pulse_context, - source_index, - mute_update, - NULL, - NULL); - if (!operation){ - g_warning ("pm_update_mic_mute operation failed for some reason"); - return; - } - pa_operation_unref (operation); -} - -/**********************************************************************************************************************/ -// Pulse-Audio asychronous call-backs -/**********************************************************************************************************************/ - - -static void -pm_subscribed_events_callback (pa_context *c, - enum pa_subscription_event_type t, - uint32_t index, - void* userdata) -{ - if (IS_DEVICE (userdata) == FALSE){ - g_critical ("subscribed events callback - our userdata is not what we think it should be"); - return; - } - Device* sink = DEVICE (userdata); - - switch (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) { - case PA_SUBSCRIPTION_EVENT_SINK: - - // We don't care about any other sink other than the active one. - if (index != device_get_sink_index (sink)) - return; - - if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { - device_sink_deactivated (sink); - - } - else{ - pa_operation_unref (pa_context_get_sink_info_by_index (c, - index, - pm_update_device, - userdata) ); - } - break; - case PA_SUBSCRIPTION_EVENT_SOURCE: - g_debug ("Looks like source event of some description - index = %i", index); - // We don't care about any other sink other than the active one. - if (index != device_get_source_index (sink)) - return; - if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { - g_debug ("Source removal event - index = %i", index); - device_deactivate_voip_source (sink, FALSE); - } - else{ - pa_operation_unref (pa_context_get_source_info_by_index (c, - index, - pm_update_source_info_callback, - userdata) ); - } - break; - case PA_SUBSCRIPTION_EVENT_SINK_INPUT: - if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) { - g_debug ("some new sink input event ? - index = %i", index); - // Maybe blocking state ?. - pa_operation_unref (pa_context_get_sink_input_info (c, - index, - pm_sink_input_info_callback, userdata)); - } - break; - case PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT: - g_debug ("source output event"); - if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { - gint cached_source_output_index = device_get_voip_source_output_index (sink); - if (index == cached_source_output_index){ - g_debug ("Just saw a source output removal event - index = %i and cached index = %i", index, cached_source_output_index); - device_deactivate_voip_client (sink); - } - } - else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) { - g_debug ("some new source output event ? - index = %i", index); - // Determine if its a VOIP app. - pa_operation_unref (pa_context_get_source_output_info (c, - index, - pm_source_output_info_callback, userdata)); - } - break; - case PA_SUBSCRIPTION_EVENT_SERVER: - g_debug("PA_SUBSCRIPTION_EVENT_SERVER event triggered."); - pa_operation *o; - if (!(o = pa_context_get_server_info (c, pm_server_info_callback, userdata))) { - g_warning("subscribed_events_callback - pa_context_get_server_info() failed"); - return; - } - pa_operation_unref(o); - break; - } -} - -static void -pm_context_state_callback (pa_context *c, void *userdata) -{ - switch (pa_context_get_state(c)) { - case PA_CONTEXT_UNCONNECTED: - g_debug("unconnected"); - break; - case PA_CONTEXT_CONNECTING: - g_debug("connecting - waiting for the server to become available"); - break; - case PA_CONTEXT_AUTHORIZING: - g_debug ("Authorizing"); - break; - case PA_CONTEXT_SETTING_NAME: - g_debug ("Setting name"); - break; - case PA_CONTEXT_FAILED: - g_warning("PA_CONTEXT_FAILED - Is PulseAudio Daemon running ?"); - device_sink_deactivated (DEVICE (userdata)); - if (reconnect_idle_id == 0){ - reconnect_idle_id = g_timeout_add_seconds (RECONNECT_DELAY, - reconnect_to_pulse, - (gpointer)userdata); - } - break; - case PA_CONTEXT_TERMINATED: - g_debug ("Terminated"); - device_sink_deactivated (DEVICE (userdata)); - - if (reconnect_idle_id != 0){ - g_source_remove (reconnect_idle_id); - reconnect_idle_id = 0; - } - break; - case PA_CONTEXT_READY: - connection_attempts = 0; - g_debug("PA_CONTEXT_READY"); - - if (reconnect_idle_id != 0){ - g_source_remove (reconnect_idle_id); - reconnect_idle_id = 0; - } - - pa_context_set_subscribe_callback(c, pm_subscribed_events_callback, userdata); - pa_operation *o = NULL; - - o = pa_context_subscribe (c, (pa_subscription_mask_t) - (PA_SUBSCRIPTION_MASK_SINK| - PA_SUBSCRIPTION_MASK_SOURCE| - PA_SUBSCRIPTION_MASK_SINK_INPUT| - PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT| - PA_SUBSCRIPTION_MASK_SERVER), - NULL, - NULL); - - - if (!o){ - g_critical("pa_context_subscribe() failed - ?"); - return; - } - - pa_operation_unref(o); - - o = pa_context_get_server_info (c, pm_server_info_callback, userdata); - - if (!o){ - g_warning("pa_context_get_server_info() failed - ?"); - return; - } - - pa_operation_unref(o); - - break; - } -} - -/** - After startup we go straight for the server info to see if it has details of - the default sink and source. Normally these are valid, if there is none set - fetch the list of each and try to determine the sink. - **/ -static void -pm_server_info_callback (pa_context *c, - const pa_server_info *info, - void *userdata) -{ - pa_operation *operation; - g_debug ("server info callback"); - - if (info == NULL) { - g_warning("No PA server - get the hell out of here"); - device_sink_deactivated (DEVICE (userdata)); - return; - } - // Go for the default sink - if (info->default_sink_name != NULL) { - g_debug ("default sink name from the server ain't null'"); - if (!(operation = pa_context_get_sink_info_by_name (c, - info->default_sink_name, - pm_default_sink_info_callback, - userdata) )) { - g_warning("pa_context_get_sink_info_by_namet() failed"); - device_sink_deactivated (DEVICE (userdata)); - pa_operation_unref(operation); - return; - } - } // If there is no default sink, try to determine a sink from the list of sinks - else if (!(operation = pa_context_get_sink_info_list(c, - pm_sink_info_callback, - userdata))) { - g_warning("pa_context_get_sink_info_list() failed"); - device_sink_deactivated (DEVICE (userdata)); - pa_operation_unref(operation); - return; - } - // And the source - if (info->default_source_name != NULL) { - g_debug ("default source name from the server is not null'"); - if (!(operation = pa_context_get_source_info_by_name (c, - info->default_source_name, - pm_default_source_info_callback, - userdata) )) { - g_warning("pa_context_get_default_source_info() failed"); - // TODO: call some input deactivate method on active sink - pa_operation_unref(operation); - return; - } - } - else if (!(operation = pa_context_get_source_info_list(c, - pm_source_info_callback, - userdata))) { - g_warning("pa_context_get_sink_info_list() failed"); - // TODO: call some input deactivate method for the source - } - pa_operation_unref(operation); -} - -// If the server doesn't have a default sink to give us -// we should attempt to pick up the first of the list of sinks which doesn't have -// the name 'auto_null' (that was all really I was doing before) -static void -pm_sink_info_callback (pa_context *c, - const pa_sink_info *sink, - int eol, - void* userdata) -{ - if (eol > 0) { - return; - } - else { - if (IS_DEVICE (userdata) == FALSE || sink == NULL){ - g_warning ("sink info callback - our user data is not what we think it should be or the sink parameter is null"); - return; - } - Device* a_sink = DEVICE (userdata); - if (device_is_sink_populated (a_sink) == FALSE && - g_ascii_strncasecmp("auto_null", sink->name, 9) != 0){ - device_sink_populate (a_sink, sink); - } - } -} - -static void -pm_default_sink_info_callback (pa_context *c, - const pa_sink_info *info, - int eol, - void *userdata) -{ - if (eol > 0) { - return; - } - else { - if (IS_DEVICE (userdata) == FALSE || info == NULL){ - g_warning ("Default sink info callback - our user data is not what we think it should be or the info parameter is null"); - return; - } - // Only repopulate if there is a change with regards the index - if (device_get_sink_index (DEVICE (userdata)) == info->index) - return; - - g_debug ("Pulse Server has handed us a new default sink"); - device_sink_populate (DEVICE (userdata), info); - } -} - -static void -pm_sink_input_info_callback (pa_context *c, - const pa_sink_input_info *info, - int eol, - void *userdata) -{ - if (eol > 0) { - return; - } - else { - if (info == NULL || IS_DEVICE (userdata) == FALSE) { - g_warning("Sink input info callback : SINK INPUT INFO IS NULL or our user_data is not what we think it should be"); - return; - } - Device* a_sink = DEVICE (userdata); - // And finally check for the mute blocking state - if (device_get_sink_index (a_sink) == info->sink){ - device_determine_blocking_state (a_sink); - } - } -} - -static void -pm_source_output_info_callback (pa_context *c, - const pa_source_output_info *info, - int eol, - void *userdata) -{ - if (eol > 0) { - return; - } - else { - if (info == NULL || IS_DEVICE (userdata) == FALSE) { - g_warning("Source output callback: SOURCE OUTPUT INFO IS NULL or our user_data is not what we think it should be"); - return; - } - - // Check if this is Voip sink input - gint result = pa_proplist_contains (info->proplist, PA_PROP_MEDIA_ROLE); - Device* a_sink = DEVICE (userdata); - - if (result == 1){ - //g_debug ("Source output info has media role property"); - const char* value = pa_proplist_gets (info->proplist, PA_PROP_MEDIA_ROLE); - //g_debug ("prop role = %s", value); - if (g_strcmp0 (value, "phone") == 0 || g_strcmp0 (value, "production") == 0) { - g_debug ("We have a VOIP/PRODUCTION ! - index = %i", info->index); - device_activate_voip_item (a_sink, (gint)info->index, (gint)info->client); - // TODO to start with we will assume our source is the same as what this 'client' - // is pointing at. This should probably be more intelligent : - // query for the list of source output info's and going on the name of the client - // from the sink input ensure our voip item is using the right source. - } - } - } -} - -static void -pm_update_device (pa_context *c, - const pa_sink_info *info, - int eol, - void *userdata) -{ - if (eol > 0) { - return; - } - else{ - if (IS_DEVICE (userdata) == FALSE || info == NULL){ - g_warning ("update_device - our user data is not what we think it should be or the info parameter is null"); - return; - } - device_sink_update (DEVICE(userdata), info); - } -} - -static void -pm_toggle_mute_for_every_sink_callback (pa_context *c, - const pa_sink_info *sink, - int eol, - void* userdata) -{ - if (eol > 0) { - return; - } - - if (sink == NULL) { - g_warning ("toggle_mute cb - sink parameter is null - why ?"); - return; - } - - pa_operation *operation = NULL; - operation = pa_context_set_sink_mute_by_index (c, - sink->index, - GPOINTER_TO_INT(userdata), - NULL, - NULL); - if (!operation){ - g_warning ("pm_update_mic_mute operation failed for some reason"); - return; - } - pa_operation_unref (operation); -} - -// Source info related callbacks -static void -pm_default_source_info_callback (pa_context *c, - const pa_source_info *info, - int eol, - void *userdata) -{ - if (eol > 0) { - return; - } - else { - if (IS_DEVICE (userdata) == FALSE || info == NULL){ - g_warning ("Default source info callback - our user data is not what we think it should be or the source info parameter is null"); - return; - } - // If there is an index change we need to change our cached source - if (device_get_source_index (DEVICE (userdata)) == info->index) - return; - g_debug ("Pulse Server has handed us a new default source"); - device_deactivate_voip_source (DEVICE (userdata), TRUE); - device_update_voip_input_source (DEVICE (userdata), info); - } -} - -static void -pm_source_info_callback (pa_context *c, - const pa_source_info *info, - int eol, - void *userdata) -{ - if (eol > 0) { - return; - } - else { - if (IS_DEVICE (userdata) == FALSE || info == NULL){ - g_warning ("source info callback - our user data is not what we think it should be or the source info parameter is null"); - return; - } - // For now we will take the first available - if (device_is_voip_source_populated (DEVICE (userdata)) == FALSE){ - device_update_voip_input_source (DEVICE (userdata), info); - } - } -} - -static void -pm_update_source_info_callback (pa_context *c, - const pa_source_info *info, - int eol, - void *userdata) -{ - if (eol > 0) { - return; - } - else { - if (IS_DEVICE (userdata) == FALSE || info == NULL ){ - g_warning ("source info update callback - our user data is not what we think it should be or the source info paramter is null"); - return; - } - g_debug ("Got a source update for %s , index %i", info->name, info->index); - device_update_voip_input_source (DEVICE (userdata), info); - } -} diff --git a/src/pulseaudio-mgr.h b/src/pulseaudio-mgr.h deleted file mode 100644 index ace47f3..0000000 --- a/src/pulseaudio-mgr.h +++ /dev/null @@ -1,33 +0,0 @@ -/* -Copyright 2011 Canonical Ltd. - -Authors: - Conor Curran <conor.curran@canonical.com> - -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 <http://www.gnu.org/licenses/>. -*/ - -#include "device.h" - -void pm_establish_pulse_connection (Device* device); -void close_pulse_activites(); -void pm_update_volume (gint sink_index, pa_cvolume new_volume); -void pm_update_mic_gain (gint source_index, pa_cvolume new_gain); -void pm_update_mic_mute (gint source_index, int mute_update); -void pm_update_mute (gboolean update); - - - - - - diff --git a/src/scrub-menu-item.vala b/src/scrub-menu-item.vala deleted file mode 100644 index e300050..0000000 --- a/src/scrub-menu-item.vala +++ /dev/null @@ -1,56 +0,0 @@ -/* -Copyright 2010 Canonical Ltd. - -Authors: - Conor Curran <conor.curran@canonical.com> - -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 <http://www.gnu.org/licenses/>. -*/ - -using Dbusmenu; -using DbusmenuScrub; -using Gee; - -public class ScrubMenuitem : PlayerItem -{ - public ScrubMenuitem(PlayerController parent) - { - Object(item_type: MENUITEM_TYPE, owner: parent); - reset(attributes_format()); - } - - public override void handle_event(string name, GLib.Value input_value, uint timestamp) - { - debug("handle_event for owner %s with value: %f", this.owner.name, input_value.get_double()); - this.owner.mpris_bridge.set_track_position(input_value.get_double()); - } - - public void update_position(int32 new_position) - { - this.property_set_int(MENUITEM_POSITION, new_position); - } - - public void update_playstate(int state) - { - this.property_set_int(MENUITEM_PLAY_STATE, state); - } - - public static HashSet<string> attributes_format() - { - HashSet<string> attrs = new HashSet<string>(); - attrs.add(MENUITEM_DURATION); - attrs.add(MENUITEM_POSITION); - attrs.add(MENUITEM_PLAY_STATE); - return attrs; - } -}
\ No newline at end of file diff --git a/src/settings-manager.vala b/src/settings-manager.vala deleted file mode 100644 index 458ac21..0000000 --- a/src/settings-manager.vala +++ /dev/null @@ -1,136 +0,0 @@ -/* -Copyright 2010 Canonical Ltd. - -Authors: - Conor Curran <conor.curran@canonical.com> - -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 <http://www.gnu.org/licenses/>. -*/ -using Gee; - -public class SettingsManager : GLib.Object -{ - private Settings settings; - public signal void blacklist_updates ( string[] new_blacklist ); - public signal void preferred_updates (Gee.ArrayList<string> new_preferred); - - public SettingsManager ( ){ - } - construct{ - this.settings = new Settings ("com.canonical.indicator.sound"); - this.settings.changed["blacklisted-media-players"].connect (on_blacklist_event); - this.settings.changed["preferred-media-players"].connect (on_preferred_event); - } - - public string[] fetch_blacklist() - { - return this.settings.get_strv ("blacklisted-media-players"); - } - - public ArrayList<string> fetch_preferred() - { - var list = new ArrayList<string>(); - - var preferred = this.settings.get_strv ("preferred-media-players"); - var interested = fetch_interested (); - - foreach (var s in preferred) { - if (!(s in list) && interested.contains (s)) - list.add (s); - } - - return list; - } - - public ArrayList<string> fetch_interested() - { - var blacklisted = fetch_blacklist (); - var interested = this.settings.get_strv ("interested-media-players"); - var list = new ArrayList<string>(); - foreach(var s in interested){ - if (s == "banshee-1"){ - s = "banshee"; - } - if (s in list) continue; - if (s in blacklisted) continue; - list.add(s); - } - return list; - } - - public void clear_list() - { - this.settings.reset("interested-media-players"); - } - - public void remove_interested (string app_desktop_name) - { - const string key = "interested-media-players"; - var players = new GLib.VariantBuilder (new VariantType ("as")); // array of strings - - foreach (var player in this.settings.get_strv (key)) { - if (player != app_desktop_name) - players.add ("s", player); - } - - this.settings.set_value(key, players.end()); - this.settings.apply(); - } - - public void add_interested (string app_desktop_name) - { - const string key = "interested-media-players"; - var players = new GLib.VariantBuilder (new VariantType ("as")); // array of strings - - foreach (var player in this.settings.get_strv (key)) { - if (player == app_desktop_name) - return; - players.add ("s", player); - } - - players.add ("s", app_desktop_name); - this.settings.set_value(key, players.end()); - this.settings.apply(); - } - - private void on_blacklist_event() - { - this.blacklist_updates(this.settings.get_strv ("blacklisted-media-players")); - } - - private void on_preferred_event() - { - this.preferred_updates (this.fetch_preferred()); - } - - // Convenient debug method inorder to provide visability over - // the contents of both interested and blacklisted containers in its gsettings -/** - private void reveal_contents() - { - var already_interested = this.settings.get_strv ("interested-media-players"); - foreach (var s in already_interested) - { - debug ("client %s is in interested array", s); - } - var blacklisted = this.settings.get_strv ("blacklisted-media-players"); - foreach (var s in blacklisted) - { - debug ("client %s is in blacklisted array", s); - } - - debug ("interested array size = %i", already_interested.length); - debug ("blacklisted array size = %i", blacklisted.length); - } -**/ -} diff --git a/src/slider-menu-item.c b/src/slider-menu-item.c deleted file mode 100644 index dc0671c..0000000 --- a/src/slider-menu-item.c +++ /dev/null @@ -1,258 +0,0 @@ -/* -Copyright 2010 Canonical Ltd. - -Authors: - Conor Curran <conor.curran@canonical.com> - -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 <http://www.gnu.org/licenses/>. -*/ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <glib/gi18n.h> -#include "slider-menu-item.h" -#include "common-defs.h" -#include "pulseaudio-mgr.h" - -typedef struct _SliderMenuItemPrivate SliderMenuItemPrivate; - -struct _SliderMenuItemPrivate { - Device* a_sink; - gint index; - gchar* name; - gboolean mute; - pa_cvolume volume; - pa_channel_map channel_map; - pa_volume_t base_volume; -}; - -#define SLIDER_MENU_ITEM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SLIDER_MENU_ITEM_TYPE, SliderMenuItemPrivate)) - -/* Prototypes */ -static void slider_menu_item_class_init (SliderMenuItemClass *klass); -static void slider_menu_item_init (SliderMenuItem *self); -static void slider_menu_item_dispose (GObject *object); -static void slider_menu_item_finalize (GObject *object); -static void handle_event (DbusmenuMenuitem * mi, const gchar * name, - GVariant * value, guint timestamp); -static pa_cvolume slider_menu_item_construct_mono_volume (const pa_cvolume* vol); -static void slider_menu_item_update_volume (SliderMenuItem* self, gdouble percent); - -G_DEFINE_TYPE (SliderMenuItem, slider_menu_item, DBUSMENU_TYPE_MENUITEM); - -static void -slider_menu_item_class_init (SliderMenuItemClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - g_type_class_add_private (klass, sizeof (SliderMenuItemPrivate)); - - object_class->dispose = slider_menu_item_dispose; - object_class->finalize = slider_menu_item_finalize; - - DbusmenuMenuitemClass * mclass = DBUSMENU_MENUITEM_CLASS(klass); - mclass->handle_event = handle_event; - return; -} - -static void -slider_menu_item_init (SliderMenuItem *self) -{ - dbusmenu_menuitem_property_set( DBUSMENU_MENUITEM(self), - DBUSMENU_MENUITEM_PROP_TYPE, - DBUSMENU_VOLUME_MENUITEM_TYPE ); - - SliderMenuItemPrivate* priv = SLIDER_MENU_ITEM_GET_PRIVATE (self); - - priv->index = NOT_ACTIVE; - priv->name = NULL; - - return; -} - -static void -slider_menu_item_dispose (GObject *object) -{ - G_OBJECT_CLASS (slider_menu_item_parent_class)->dispose (object); - return; -} - -static void -slider_menu_item_finalize (GObject *object) -{ - G_OBJECT_CLASS (slider_menu_item_parent_class)->finalize (object); -} - -static void -handle_event (DbusmenuMenuitem * mi, - const gchar * name, - GVariant * value, - guint timestamp) -{ - g_return_if_fail (g_variant_is_of_type (value, G_VARIANT_TYPE_DOUBLE)); - g_return_if_fail (IS_SLIDER_MENU_ITEM (mi)); - - SliderMenuItemPrivate* priv = SLIDER_MENU_ITEM_GET_PRIVATE (SLIDER_MENU_ITEM (mi)); - gdouble volume_input = g_variant_get_double (value); - -/* - g_debug ("slider menu item handle event with value %f on name %s", - volume_input, - name); -*/ - - slider_menu_item_update_volume (SLIDER_MENU_ITEM (mi), volume_input); - if (volume_input > 0) - device_ensure_sink_is_unmuted (priv->a_sink); -} - - -void -slider_menu_item_populate (SliderMenuItem* self, const pa_sink_info* update) -{ - SliderMenuItemPrivate* priv = SLIDER_MENU_ITEM_GET_PRIVATE (self); - priv->name = g_strdup (update->name); - priv->index = update->index; - priv->volume = slider_menu_item_construct_mono_volume (&update->volume); - priv->base_volume = update->base_volume; - priv->channel_map = update->channel_map; - priv->mute = update->mute; - - pa_volume_t vol = pa_cvolume_max (&update->volume); - gdouble volume_percent = ((gdouble) vol * 100) / PA_VOLUME_NORM; - GVariant* new_volume = g_variant_new_double (volume_percent); - dbusmenu_menuitem_property_set_variant (DBUSMENU_MENUITEM(self), - DBUSMENU_VOLUME_MENUITEM_LEVEL, - new_volume); - GVariant* new_mute_update = g_variant_new_boolean (update->mute == 1); - dbusmenu_menuitem_property_set_variant (DBUSMENU_MENUITEM(self), - DBUSMENU_VOLUME_MENUITEM_MUTE, - new_mute_update); - - slider_menu_item_enable (self, TRUE); -} - -// From the UI -static void -slider_menu_item_update_volume (SliderMenuItem* self, gdouble percent) -{ - g_return_if_fail (IS_SLIDER_MENU_ITEM (self)); - - pa_cvolume mono_new_volume; - pa_cvolume_init(&mono_new_volume); - mono_new_volume.channels = 1; - pa_volume_t new_volume_value = (pa_volume_t) ((percent * PA_VOLUME_NORM) / 100); - - if (new_volume_value == PA_VOLUME_INVALID || new_volume_value >= PA_VOLUME_MAX){ - g_warning ("slider_menu_item_update_volume - volume is out of range !"); - return; - } - - pa_cvolume_set(&mono_new_volume, 1, new_volume_value); - - SliderMenuItemPrivate* priv = SLIDER_MENU_ITEM_GET_PRIVATE (self); - if (!pa_cvolume_valid (&mono_new_volume)){ - g_warning ("Invalid volume - ignore it!"); - return; - } - if (!pa_channel_map_valid(&priv->channel_map)){ - g_warning ("Invalid channel map - ignore update volume!"); - return; - } - pa_cvolume_set(&priv->volume, priv->channel_map.channels, new_volume_value); - pm_update_volume (priv->index, mono_new_volume); -} - -// To the UI -void -slider_menu_item_update (SliderMenuItem* self, const pa_sink_info* update) -{ - SliderMenuItemPrivate* priv = SLIDER_MENU_ITEM_GET_PRIVATE (self); - - priv->volume = slider_menu_item_construct_mono_volume (&update->volume); - priv->base_volume = update->base_volume; - priv->channel_map = update->channel_map; - - pa_volume_t vol = pa_cvolume_max (&update->volume); - gdouble volume_percent = ((gdouble) vol * 100) / PA_VOLUME_NORM; - - GVariant* new_volume = g_variant_new_double (volume_percent); - -/* - g_debug ("slider menu item update - volume update to ui to %f", volume_percent); -*/ - - dbusmenu_menuitem_property_set_variant (DBUSMENU_MENUITEM(self), - DBUSMENU_VOLUME_MENUITEM_LEVEL, - new_volume); - - if (priv->mute != update->mute){ - priv->mute = update->mute; -/* - g_debug ("volume menu item - update - mute on ui = %i", update->mute); -*/ - GVariant* new_mute_update = g_variant_new_boolean (update->mute == 1); - dbusmenu_menuitem_property_set_variant (DBUSMENU_MENUITEM(self), - DBUSMENU_VOLUME_MENUITEM_MUTE, - new_mute_update); - } -} - -/* - * Enable/Disabled can be considered the equivalent of whether we have an active - * sink or not, let the widget have inherent state. - */ -void -slider_menu_item_enable (SliderMenuItem* self, gboolean active) -{ - SliderMenuItemPrivate* priv = SLIDER_MENU_ITEM_GET_PRIVATE (self); - - dbusmenu_menuitem_property_set_bool (DBUSMENU_MENUITEM(self), - DBUSMENU_MENUITEM_PROP_ENABLED, - active); - if(active == FALSE){ - priv->index = NOT_ACTIVE; - if(priv->name != NULL){ - g_free(priv->name); - priv->name = NULL; - } - } -} - -gint -slider_menu_item_get_sink_index (SliderMenuItem* self) -{ - SliderMenuItemPrivate* priv = SLIDER_MENU_ITEM_GET_PRIVATE (self); - return priv->index; -} - -static pa_cvolume -slider_menu_item_construct_mono_volume (const pa_cvolume* vol) -{ - pa_cvolume new_volume; - pa_cvolume_init(&new_volume); - new_volume.channels = 1; - pa_volume_t max_vol = pa_cvolume_max(vol); - pa_cvolume_set(&new_volume, 1, max_vol); - return new_volume; -} - -SliderMenuItem* -slider_menu_item_new (Device* sink) -{ - SliderMenuItem *self = g_object_new(SLIDER_MENU_ITEM_TYPE, NULL); - SliderMenuItemPrivate* priv = SLIDER_MENU_ITEM_GET_PRIVATE (self); - priv->a_sink = sink; - return self; -} diff --git a/src/slider-menu-item.h b/src/slider-menu-item.h deleted file mode 100644 index 4375971..0000000 --- a/src/slider-menu-item.h +++ /dev/null @@ -1,64 +0,0 @@ -/* -Copyright 2010 Canonical Ltd. - -Authors: - Conor Curran <conor.curran@canonical.com> - -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 <http://www.gnu.org/licenses/>. -*/ -#ifndef __SLIDER_MENU_ITEM_H__ -#define __SLIDER_MENU_ITEM_H__ - -#include <glib.h> -#include <glib-object.h> - -#include <libdbusmenu-glib/menuitem.h> -#include "device.h" - -G_BEGIN_DECLS - -#define SLIDER_MENU_ITEM_TYPE (slider_menu_item_get_type ()) -#define SLIDER_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SLIDER_MENU_ITEM_TYPE, SliderMenuItem)) -#define SLIDER_MENU_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SLIDER_MENU_ITEM_TYPE, SliderMenuItemClass)) -#define IS_SLIDER_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SLIDER_MENU_ITEM_TYPE)) -#define IS_SLIDER_MENU_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SLIDER_MENU_ITEM_TYPE)) -#define SLIDER_MENU_ITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SLIDER_MENU_ITEM_TYPE, SliderMenuItemClass)) - -typedef struct _SliderMenuItem SliderMenuItem; -typedef struct _SliderMenuItemClass SliderMenuItemClass; - -struct _SliderMenuItemClass { - DbusmenuMenuitemClass parent_class; -}; - -struct _SliderMenuItem { - DbusmenuMenuitem parent; -}; - -GType slider_menu_item_get_type (void); - -void slider_menu_item_update(SliderMenuItem* item, const pa_sink_info* update); -void slider_menu_item_enable(SliderMenuItem* item, gboolean active); -void slider_menu_item_populate (SliderMenuItem* self, const pa_sink_info* update); -//void -//active_sink_update (ActiveSink* sink, -// const pa_sink_info* update) - -gint slider_menu_item_get_sink_index (SliderMenuItem* self); - -SliderMenuItem* slider_menu_item_new (Device* sink); - -G_END_DECLS - -#endif - diff --git a/src/sound-state.c b/src/sound-state.c deleted file mode 100644 index 72e411a..0000000 --- a/src/sound-state.c +++ /dev/null @@ -1,43 +0,0 @@ -/* -Copyright 2010 Canonical Ltd. - -Authors: - Conor Curran <conor.curran@canonical.com> - -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 <http://www.gnu.org/licenses/>. -*/ - -#include "config.h" - -#include "sound-state.h" - -SoundState -sound_state_get_from_volume (int volume_percent) -{ - SoundState state = LOW_LEVEL; - - if (volume_percent < 30 && volume_percent > 0) { - state = LOW_LEVEL; - } - else if (volume_percent < 70 && volume_percent >= 30) { - state = MEDIUM_LEVEL; - } - else if (volume_percent >= 70) { - state = HIGH_LEVEL; - } - else if (volume_percent <= 0) { - state = ZERO_LEVEL; - } - return state; -} - diff --git a/src/sound-state.h b/src/sound-state.h deleted file mode 100644 index 9527c8e..0000000 --- a/src/sound-state.h +++ /dev/null @@ -1,31 +0,0 @@ -/* -Copyright 2011 Canonical Ltd. - -Authors: - Conor Curran <conor.curran@canonical.com> - -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 <http://www.gnu.org/licenses/>. -*/ - -#ifndef _SOUND_STATE_H_ -#define _SOUND_STATE_H_ - -#include <glib.h> -#include "common-defs.h" - -/* Helper functions for determining SOUNDSTATE */ - -SoundState sound_state_get_from_volume (int volume_percent); - -#endif /* _SOUND_STATE_H_ */ - diff --git a/src/specific-items-manager.vala b/src/specific-items-manager.vala deleted file mode 100644 index 923cf3f..0000000 --- a/src/specific-items-manager.vala +++ /dev/null @@ -1,109 +0,0 @@ -/* -Copyright 2011 Canonical Ltd. - -Authors: - Conor Curran <conor.curran@canonical.com> - -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 <http://www.gnu.org/licenses/>. -*/ - -using Dbusmenu; -using Gee; - -public class SpecificItemsManager : GLib.Object -{ - public enum category{ - TRACK, - PLAYER - } - - private PlayerController owner {get; set;} - private string dbus_path; - private Dbusmenu.Client client; - public Gee.ArrayList<Dbusmenu.MenuitemProxy> proxy_items {get; construct;} - private int of_type; - - public SpecificItemsManager (PlayerController controller, - string path, - category which_type) - { - this.of_type = which_type; - this.owner = controller; - this.dbus_path = path; - this.client = new Dbusmenu.Client (this.owner.dbus_name, this.dbus_path); - this.client.root_changed.connect (on_root_changed); - } - construct{ - this.proxy_items = new ArrayList<Dbusmenu.MenuitemProxy>(); - } - - private int figure_out_positioning() - { - int result = 0 ; - if (this.of_type == category.TRACK){ - result = this.owner.menu_offset + this.owner.WIDGET_QUANTITY + this.proxy_items.size; - } - else if (this.of_type == category.PLAYER){ - int pos = this.owner.menu_offset + this.owner.WIDGET_QUANTITY + this.owner.track_specific_count(); - //Surely the playlists item is there whether its visible or not ? - //TODO test playlists and player specific item positioning. - pos += this.owner.use_playlists == true ? 1 : 0; - result = pos; - } - debug ("!!!!! Menu pos of type %i is = %i", this.of_type, result); - return result; - } - - private void on_root_changed (GLib.Object? newroot) - { - if (newroot == null){ - debug ("root disappeared -remove proxyitems"); - foreach(var p in proxy_items){ - this.owner.root_menu.child_delete (p); - } - this.proxy_items.clear(); - debug ("array list size is now %i", this.proxy_items.size); - //this.proxy_items = new ArrayList<Dbusmenu.MenuitemProxy>(); - return; - } - - Dbusmenu.Menuitem? root = this.client.get_root(); - root.child_added.connect (on_child_added); - root.child_removed.connect (on_child_removed); - - // Fetch what children are there already. - GLib.List<weak void*> children = root.get_children().copy(); - - foreach (void* child in children) { - int pos = figure_out_positioning(); - unowned Dbusmenu.Menuitem item = (Dbusmenu.Menuitem)child; - Dbusmenu.MenuitemProxy proxy = new Dbusmenu.MenuitemProxy(item); - proxy_items.add (proxy); - debug ("Proxy item of label = %s added to collection", - item.property_get (MENUITEM_PROP_LABEL)); - this.owner.root_menu.child_add_position (proxy, pos); - - } - } - - private void on_child_added (GLib.Object child, uint position) - { - debug ("On child added Specific root node"); - } - - private void on_child_removed (GLib.Object child) - { - debug ("On child removed Specific root node"); - } - -} diff --git a/src/transport-menu-item.vala b/src/transport-menu-item.vala deleted file mode 100644 index 4ec7dad..0000000 --- a/src/transport-menu-item.vala +++ /dev/null @@ -1,97 +0,0 @@ -/* -Copyright 2010 Canonical Ltd. - -Authors: - Conor Curran <conor.curran@canonical.com> - -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 <http://www.gnu.org/licenses/>. -*/ - -using Dbusmenu; -using Gee; -using DbusmenuTransport; -using Transport; - -public class TransportMenuitem : PlayerItem -{ - private Transport.Action cached_action; - - private bool running { - get{ - return this.owner.current_state == PlayerController.state.CONNECTED; - } - } - - public TransportMenuitem(PlayerController parent) - { - Object(item_type: MENUITEM_TYPE, owner: parent); - } - construct{ - this.property_set_int(MENUITEM_PLAY_STATE, (int)Transport.State.PAUSED); - this.property_set (MENUITEM_PROP_LABEL, this.owner.app_info.get_name()); - this.cached_action = Transport.Action.NO_ACTION; - } - - /** - Please remove this timeout when the default player can handle mpris commands - immediately once it raises its dbus interface - **/ - public void handle_cached_action() - { - if (this.cached_action != Transport.Action.NO_ACTION){ - Timeout.add_seconds (1, send_cached_action); - } - } - - private bool send_cached_action() - { - this.owner.mpris_bridge.transport_update(this.cached_action); - this.cached_action = Transport.Action.NO_ACTION; - return false; - } - - public void change_play_state (Transport.State update) - { - int temp = (int)update; - this.property_set_int(MENUITEM_PLAY_STATE, temp); - } - - public override void handle_event(string name, - Variant input_value, - uint timestamp) - { - Variant v = input_value; - if ( input_value.is_of_type (VariantType.VARIANT)){ - v = input_value.get_variant(); - } - - int32 input = v.get_int32(); - - if (this.running == true){ - this.owner.mpris_bridge.transport_update((Transport.Action)input); - } - else{ - this.cached_action = (Transport.Action)input; - this.owner.instantiate(); - this.property_set_int (MENUITEM_PLAY_STATE, (int)Transport.State.LAUNCHING); - } - } - - public static HashSet<string> attributes_format() - { - HashSet<string> attrs = new HashSet<string>(); - attrs.add(MENUITEM_PLAY_STATE); - return attrs; - } - -} diff --git a/src/voip-input-menu-item.c b/src/voip-input-menu-item.c deleted file mode 100644 index 7cbdd45..0000000 --- a/src/voip-input-menu-item.c +++ /dev/null @@ -1,278 +0,0 @@ -/* -Copyright 2011 Canonical Ltd. - -Authors: - Conor Curran <conor.curran@canonical.com> - -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 <http://www.gnu.org/licenses/>. -*/ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <glib/gi18n.h> -#include "voip-input-menu-item.h" -#include "common-defs.h" -#include "pulseaudio-mgr.h" - -typedef struct _VoipInputMenuItemPrivate VoipInputMenuItemPrivate; - -struct _VoipInputMenuItemPrivate { - Device* a_sink; - pa_cvolume volume; - gint mute; - guint32 volume_steps; - pa_channel_map channel_map; - pa_volume_t base_volume; - gint source_index; - gint source_output_index; - gint client_index; -}; - -#define VOIP_INPUT_MENU_ITEM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), VOIP_INPUT_MENU_ITEM_TYPE, VoipInputMenuItemPrivate)) - -/* Prototypes */ -static void voip_input_menu_item_class_init (VoipInputMenuItemClass *klass); -static void voip_input_menu_item_init (VoipInputMenuItem *self); -static void voip_input_menu_item_dispose (GObject *object); -static void voip_input_menu_item_finalize (GObject *object); -static void handle_event (DbusmenuMenuitem * mi, const gchar * name, - GVariant * value, guint timestamp); -// TODO: -// This method should really be shared between this and the volume slider obj -// perfectly static - wait until the device mgr wrapper is properly sorted and -// then consolidate -static pa_cvolume voip_input_menu_item_construct_mono_volume (const pa_cvolume* vol); - -G_DEFINE_TYPE (VoipInputMenuItem, voip_input_menu_item, DBUSMENU_TYPE_MENUITEM); - -static void -voip_input_menu_item_class_init (VoipInputMenuItemClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - g_type_class_add_private (klass, sizeof (VoipInputMenuItemPrivate)); - - object_class->dispose = voip_input_menu_item_dispose; - object_class->finalize = voip_input_menu_item_finalize; - - DbusmenuMenuitemClass * mclass = DBUSMENU_MENUITEM_CLASS(klass); - mclass->handle_event = handle_event; -} - -static void -voip_input_menu_item_init (VoipInputMenuItem *self) -{ - dbusmenu_menuitem_property_set( DBUSMENU_MENUITEM(self), - DBUSMENU_MENUITEM_PROP_TYPE, - DBUSMENU_VOIP_INPUT_MENUITEM_TYPE ); - VoipInputMenuItemPrivate* priv = VOIP_INPUT_MENU_ITEM_GET_PRIVATE (self); - dbusmenu_menuitem_property_set_bool( DBUSMENU_MENUITEM(self), - DBUSMENU_MENUITEM_PROP_VISIBLE, - FALSE ); - - priv->source_index = NOT_ACTIVE; - priv->source_output_index = NOT_ACTIVE; - priv->client_index = NOT_ACTIVE; - priv->mute = NOT_ACTIVE; -} - -static void -voip_input_menu_item_dispose (GObject *object) -{ - G_OBJECT_CLASS (voip_input_menu_item_parent_class)->dispose (object); - return; -} - -static void -voip_input_menu_item_finalize (GObject *object) -{ - G_OBJECT_CLASS (voip_input_menu_item_parent_class)->finalize (object); -} - -static void -handle_event (DbusmenuMenuitem * mi, - const gchar * name, - GVariant * value, - guint timestamp) -{ - GVariant* input = NULL; - input = value; - if (g_variant_is_of_type(value, G_VARIANT_TYPE_VARIANT) == TRUE) { - input = g_variant_get_variant(value); - } - - gdouble percent = g_variant_get_double(input); - if (value != NULL){ - if (IS_VOIP_INPUT_MENU_ITEM (mi)) { - VoipInputMenuItemPrivate* priv = VOIP_INPUT_MENU_ITEM_GET_PRIVATE (VOIP_INPUT_MENU_ITEM (mi)); -/* - g_debug ("Handle event in the voip input level backend instance - %f", percent); -*/ - pa_cvolume new_volume; - pa_cvolume_init(&new_volume); - new_volume.channels = 1; - pa_volume_t new_volume_value = (pa_volume_t) ((percent * PA_VOLUME_NORM) / 100); - pa_cvolume_set(&new_volume, 1, new_volume_value); - - pm_update_mic_gain (priv->source_index, new_volume); - // finally unmute if needed - if (priv->mute == 1) { - pm_update_mic_mute (priv->source_index, 0); - } - } - } -} - -static pa_cvolume -voip_input_menu_item_construct_mono_volume (const pa_cvolume* vol) -{ - pa_cvolume new_volume; - pa_cvolume_init(&new_volume); - new_volume.channels = 1; - pa_volume_t max_vol = pa_cvolume_max(vol); - pa_cvolume_set(&new_volume, 1, max_vol); - return new_volume; -} - -void -voip_input_menu_item_update (VoipInputMenuItem* item, - const pa_source_info* source) -{ - VoipInputMenuItemPrivate* priv = VOIP_INPUT_MENU_ITEM_GET_PRIVATE (item); - // only overwrite the constants of each source if the device has changed - if (priv->source_index == NOT_ACTIVE){ - priv->base_volume = source->base_volume; - priv->volume_steps = source->n_volume_steps; - priv->channel_map = source->channel_map; - priv->source_index = source->index; - } - priv->volume = voip_input_menu_item_construct_mono_volume (&source->volume); - pa_volume_t vol = pa_cvolume_max (&source->volume); - gdouble update = ((gdouble) vol * 100) / PA_VOLUME_NORM; - - GVariant* new_volume = g_variant_new_double(update); - dbusmenu_menuitem_property_set_variant(DBUSMENU_MENUITEM(item), - DBUSMENU_VOIP_INPUT_MENUITEM_LEVEL, - new_volume); - // Only send over the mute updates if the state has changed. - // in this order - volume first mute last!! - if (priv->mute != source->mute){ -/* - g_debug ("voip menu item - update - mute = %i", priv->mute); -*/ - GVariant* new_mute_update = g_variant_new_int32 (source->mute); - dbusmenu_menuitem_property_set_variant (DBUSMENU_MENUITEM(item), - DBUSMENU_VOIP_INPUT_MENUITEM_MUTE, - new_mute_update); - } - - priv->mute = source->mute; - -} - -gboolean -voip_input_menu_item_is_interested (VoipInputMenuItem* item, - gint source_output_index, - gint client_index) -{ - VoipInputMenuItemPrivate* priv = VOIP_INPUT_MENU_ITEM_GET_PRIVATE (item); - // Check to make sure we are not handling another voip beforehand and that we - // have an active sink (might need to match up at start up) - if (priv->source_output_index != NOT_ACTIVE && - priv->source_index != NOT_ACTIVE){ - return FALSE; - } - - priv->source_output_index = source_output_index; - priv->client_index = client_index; - - return TRUE; -} - -gboolean -voip_input_menu_item_is_active (VoipInputMenuItem* item) -{ - VoipInputMenuItemPrivate* priv = VOIP_INPUT_MENU_ITEM_GET_PRIVATE (item); - return (priv->source_output_index != NOT_ACTIVE && priv->client_index != NOT_ACTIVE); -} - - -gboolean -voip_input_menu_item_is_populated (VoipInputMenuItem* item) -{ - VoipInputMenuItemPrivate* priv = VOIP_INPUT_MENU_ITEM_GET_PRIVATE (item); - return priv->source_index != NOT_ACTIVE; -} - -gint -voip_input_menu_item_get_index (VoipInputMenuItem* item) -{ - VoipInputMenuItemPrivate* priv = VOIP_INPUT_MENU_ITEM_GET_PRIVATE (item); - return priv->source_index; -} - -gint -voip_input_menu_item_get_source_output_index (VoipInputMenuItem* item) -{ - VoipInputMenuItemPrivate* priv = VOIP_INPUT_MENU_ITEM_GET_PRIVATE (item); - - return priv->source_output_index; -} - -/** - * If the pulse server informs of a default source change - * or the source in question is removed. - * @param item - */ -void -voip_input_menu_item_deactivate_source (VoipInputMenuItem* item, gboolean visible) -{ - VoipInputMenuItemPrivate* priv = VOIP_INPUT_MENU_ITEM_GET_PRIVATE (item); - priv->source_index = NOT_ACTIVE; - dbusmenu_menuitem_property_set_bool( DBUSMENU_MENUITEM(item), - DBUSMENU_MENUITEM_PROP_VISIBLE, - visible ); -} - -void -voip_input_menu_item_deactivate_voip_client (VoipInputMenuItem* item) -{ - VoipInputMenuItemPrivate* priv = VOIP_INPUT_MENU_ITEM_GET_PRIVATE (item); - priv->client_index = NOT_ACTIVE; - priv->source_output_index = NOT_ACTIVE; - voip_input_menu_item_enable (item, FALSE); -} - -void -voip_input_menu_item_enable (VoipInputMenuItem* item, - gboolean active) -{ - VoipInputMenuItemPrivate* priv = VOIP_INPUT_MENU_ITEM_GET_PRIVATE (item); - if (priv->source_index == NOT_ACTIVE && active == TRUE) { - g_warning ("Tried to enable the VOIP menuitem but we don't have an active source ??"); - active = FALSE; - } - dbusmenu_menuitem_property_set_bool( DBUSMENU_MENUITEM(item), - DBUSMENU_MENUITEM_PROP_VISIBLE, - active ); -} - -VoipInputMenuItem* -voip_input_menu_item_new (Device* sink) -{ - VoipInputMenuItem *self = g_object_new(VOIP_INPUT_MENU_ITEM_TYPE, NULL); - VoipInputMenuItemPrivate* priv = VOIP_INPUT_MENU_ITEM_GET_PRIVATE (self); - priv->a_sink = sink; - return self; -}
\ No newline at end of file |