← Back to team overview

ayatana-commits team mailing list archive

[Merge] lp:~cjcurran/indicator-sound/mpris2-implementation into lp:indicator-sound

 

Conor Curran has proposed merging lp:~cjcurran/indicator-sound/mpris2-implementation into lp:indicator-sound.

Requested reviews:
  Indicator Applet Developers (indicator-applet-developers)


Implements the start of the mpris 2 stuff. Its all going to change again so there is little I can do right now. For freeze we will at least have the beginnings of mpris 2. 
A fun few weeks ahead with this. 

A few bugs also have been fixed with this branch now, like start-up spacing, now when the player starts the transport is added but the metadata item does not become visible until it has content.

Also when you now kill the player the menu should hide all the items and return to the state where the title is only visible, as spec'd.

-- 
https://code.launchpad.net/~cjcurran/indicator-sound/mpris2-implementation/+merge/32368
Your team ayatana-commits is subscribed to branch lp:indicator-sound.
=== modified file 'src/Makefile.am'
--- src/Makefile.am	2010-07-30 17:51:03 +0000
+++ src/Makefile.am	2010-08-11 19:11:21 +0000
@@ -65,13 +65,14 @@
 	scrub-menu-item.vala \
 	title-menu-item.vala \
 	player-controller.vala \
-	mpris-controller-v2.vala \
 	mpris-controller.vala \
+	mpris2-controller.vala \
 	player-item.vala \
 	familiar-players-db.vala
 
 music_bridge_VALAFLAGS = \
   --ccode \
+  --disable-dbus-transformation \
   -H music-player-bridge.h -d . \
   --vapidir=$(top_srcdir)/vapi/ \
   --vapidir=./ \

=== modified file 'src/mpris-controller.vala'
--- src/mpris-controller.vala	2010-07-22 17:56:43 +0000
+++ src/mpris-controller.vala	2010-08-11 19:11:21 +0000
@@ -124,17 +124,23 @@
 	private void onTrackChange(dynamic DBus.Object mpris_client, HashTable<string,Value?> ht)
 	{
 		debug("onTrackChange");
+		
 		this.owner.custom_items[PlayerController.widget_order.METADATA].reset(MetadataMenuitem.attributes_format());
 		this.owner.custom_items[PlayerController.widget_order.SCRUB].reset(ScrubMenuitem.attributes_format());
+		HashTable<string, Value?> status_hash = new HashTable<string, Value?>(str_hash, str_equal);
+
+		status st = this.mpris_player.GetStatus();
+		int play_state =  st.playback;
+		debug("GetStatusChange, about to update scrub with play state - %i", play_state);
+
+		ScrubMenuitem scrub = this.owner.custom_items[PlayerController.widget_order.SCRUB] as ScrubMenuitem;
+		scrub.update_playstate(play_state);
+		this.owner.custom_items[PlayerController.widget_order.SCRUB].update(this.mpris_player.GetMetadata(),
+		                        ScrubMenuitem.attributes_format());		
 		this.owner.custom_items[PlayerController.widget_order.METADATA].update(ht,
 		                            MetadataMenuitem.attributes_format());
 		debug("about to update the duration on the scrub bar");
-		this.owner.custom_items[PlayerController.widget_order.SCRUB].update(this.mpris_player.GetMetadata(),
-		                        ScrubMenuitem.attributes_format());		
 		// temporary fix
-		ScrubMenuitem scrub = this.owner.custom_items[PlayerController.widget_order.SCRUB] as ScrubMenuitem;
 		scrub.update_position(this.mpris_player.PositionGet());
 	}
-		
-	
 }

=== renamed file 'src/mpris-controller-v2.vala' => 'src/mpris2-controller.vala'
--- src/mpris-controller-v2.vala	2010-07-09 15:37:51 +0000
+++ src/mpris2-controller.vala	2010-08-11 19:11:21 +0000
@@ -19,10 +19,165 @@
 */
 using Gee;
 
-public class MprisControllerV2 : MprisController
+[DBus (name = "org.mpris.MediaPlayer.Player")]
+public interface MprisPlayer : Object {
+	
+	public struct Status { 
+    public int32 Playback_State;
+    public double Playback_Rate;
+    public bool Repeat_State;
+    public bool Shuffle_State;
+		public bool Endless_State;
+	}
+	
+	public abstract HashTable<string, Value?> Metadata{owned get;}
+	public abstract double Volume{get;}
+	public abstract int32 Capabilities{get;}
+	public abstract int32 Position{get;}
+	
+	public abstract void SetPosition(string prop, int32 pos) throws DBus.Error;
+	public abstract void PlayPause() throws DBus.Error;
+	public abstract void Pause() throws DBus.Error;
+	public abstract void Next() throws DBus.Error;
+	public abstract void Previous() throws DBus.Error;
+
+	public abstract signal void StatusChanged(Status update);
+	public abstract signal void TrackChanged(HashTable<string,Value?> Metadata);
+}
+
+/*
+ This class will entirely replace mpris-controller.vala hence why there is no
+ point in trying to get encorporate both into the same object model. 
+ */
+public class Mpris2Controller : GLib.Object
 {		
-	public MprisControllerV2(PlayerController ctrl, string inter="org.mpris.MediaPlayer.Player"){
-		Object(owner: ctrl, mpris_interface: inter);				
-	}
-
+	private DBus.Connection connection;
+	public dynamic DBus.Object mpris2_root {get; construct;}		
+	public MprisPlayer mpris2_player {get; construct;}		
+	public PlayerController owner {get; construct;}	
+	
+	public Mpris2Controller(PlayerController ctrl)
+	{
+		Object(owner: ctrl);				
+	}
+	
+	construct{
+    try {
+			debug("going to create this mpris 2 controller");			
+      this.connection = DBus.Bus.get (DBus.BusType.SESSION);
+    } catch (Error e) {
+      error("Problems connecting to the session bus - %s", e.message);
+    }		
+		this.mpris2_root = this.connection.get_object ("org.mpris.mediaplayers.".concat(this.owner.name.down()),
+		                                              "/org/mpris/MediaPlayer", 
+		                                              "org.mpris.MediaPlayer");				
+
+		this.mpris2_player = (MprisPlayer)this.connection.get_object ("org.mpris.mediaplayers.".concat(this.owner.name.down()) ,
+		                                                							"/org/mpris/MediaPlayer/Player", 
+		                                                							"org.mpris.MediaPlayer.Player");			
+		this.mpris2_player.TrackChanged += onTrackChanged;	
+    this.mpris2_player.StatusChanged += onStatusChanged;
+		initial_update();
+	}
+	
+	private void initial_update()
+	{
+		bool r  =  (bool)this.mpris2_player.Status.Shuffle_State;
+		int32 p  =  (int32)this.mpris2_player.Status.Playback_State;
+
+		debug("initial update - play state %i", p);
+		debug("initial update - shuffle state %s", r.to_string());
+		
+		(this.owner.custom_items[PlayerController.widget_order.TRANSPORT] as TransportMenuitem).change_play_state(p);
+		this.owner.custom_items[PlayerController.widget_order.METADATA].update(this.mpris2_player.Metadata,
+			                          MetadataMenuitem.attributes_format());
+		this.owner.custom_items[PlayerController.widget_order.SCRUB].update(this.mpris2_player.Metadata,
+			                      ScrubMenuitem.attributes_format());		
+		ScrubMenuitem scrub = this.owner.custom_items[PlayerController.widget_order.SCRUB] as ScrubMenuitem;
+		scrub.update_position(this.mpris2_player.Position);
+		
+	}
+
+	public void transport_event(TransportMenuitem.action command)
+	{		
+		debug("transport_event input = %i", (int)command);
+		if(command == TransportMenuitem.action.PLAY_PAUSE){
+			debug("transport_event PLAY_PAUSE");
+			this.mpris2_player.PlayPause();							
+		}
+		else if(command == TransportMenuitem.action.PREVIOUS){
+			this.mpris2_player.Previous();
+		}
+		else if(command == TransportMenuitem.action.NEXT){
+			this.mpris2_player.Next();
+		}		
+	}
+
+	public void set_position(double position)
+	{		
+		debug("Set position with pos (0-100) %f", position);
+		HashTable<string, Value?> data = this.mpris2_player.Metadata;
+		Value? time_value = data.lookup("time");
+		if(time_value == null){
+			warning("Can't fetch the duration of the track therefore cant set the position");
+			return;
+		}
+		uint32 total_time = time_value.get_uint();
+		debug("total time of track = %i", (int)total_time);				
+		double new_time_position = total_time * position/100.0;
+		debug("new position = %f", (new_time_position * 1000));		
+
+		Value? v = this.mpris2_player.Metadata.lookup("trackid");
+		if(v != null){
+			if(v.holds (typeof (int))){
+				debug("the trackid = %i", v.get_int());			
+			}
+			else if(v.holds (typeof (string))){
+				debug("the trackid = %s", v.get_string());
+			}
+		}
+			        
+		//this.mpris2_player.SetPosition((int32)(new_time_position));
+		ScrubMenuitem scrub = this.owner.custom_items[PlayerController.widget_order.SCRUB] as ScrubMenuitem;
+		scrub.update_position(this.mpris2_player.Position);				
+	}
+	
+	public bool connected()
+	{
+		return (this.mpris2_player != null);
+	}
+	
+	private void onStatusChanged(MprisPlayer.Status st)
+  {
+		debug("onStatusChange - play state %i", st.Playback_State);
+		HashTable<string, Value?> ht = new HashTable<string, Value?>(str_hash, str_equal);
+		Value v = Value(typeof(int));
+		v.set_int(st.Playback_State);
+		ht.insert("state", v); 
+		this.owner.custom_items[PlayerController.widget_order.TRANSPORT].update(ht, TransportMenuitem.attributes_format());
+		this.owner.custom_items[PlayerController.widget_order.SCRUB].update(ht, ScrubMenuitem.attributes_format());		
+	}
+	
+	private void onTrackChanged(HashTable<string,Value?> ht)
+	{
+		this.owner.custom_items[PlayerController.widget_order.METADATA].reset(MetadataMenuitem.attributes_format());
+		this.owner.custom_items[PlayerController.widget_order.SCRUB].reset(ScrubMenuitem.attributes_format());
+		this.owner.custom_items[PlayerController.widget_order.METADATA].update(ht,
+		                            MetadataMenuitem.attributes_format());
+		debug("about to update the duration on the scrub bar");
+		Value? v = ht.lookup("time");
+		if(v != null)
+		{
+			debug("with the duration of %i", (int)v.get_uint()); 
+			debug("with Position of %i", this.mpris2_player.Position); 
+		}
+		this.owner.custom_items[PlayerController.widget_order.SCRUB].update(ht,
+		                        ScrubMenuitem.attributes_format());		
+		ScrubMenuitem scrub = this.owner.custom_items[PlayerController.widget_order.SCRUB] as ScrubMenuitem;
+		scrub.update_position(this.mpris2_player.Position);
+	}
+	
 }
+
+
+

=== modified file 'src/music-player-bridge.vala'
--- src/music-player-bridge.vala	2010-07-22 17:56:43 +0000
+++ src/music-player-bridge.vala	2010-08-11 19:11:21 +0000
@@ -116,10 +116,8 @@
 		if(server_is_not_of_interest(type)) return;
 		string client_name = type.split(".")[1];
 		if (root_menu != null && client_name != null){
-			registered_clients[client_name].vanish();
-			registered_clients.remove(client_name);
-			debug("Successively removed menu_item for client %s from registered_clients",
-			      client_name);
+			registered_clients[client_name].hibernate();
+			debug("Successively offlined client %s", client_name);
 		}
 	}
 	

=== modified file 'src/play-button.c'
--- src/play-button.c	2010-08-06 12:22:25 +0000
+++ src/play-button.c	2010-08-11 19:11:21 +0000
@@ -28,7 +28,7 @@
 #include "play-button.h"
 
 #define RECT_WIDTH 130.0f
-#define Y 5.0f
+#define Y 7.0f
 #define X	37.0f
 #define INNER_RADIUS 12.5
 #define	MIDDLE_RADIUS 13.5f
@@ -42,16 +42,16 @@
 #define TRI_HEIGHT 13.0f
 #define TRI_OFFSET  6.0f
 #define PREV_X 35.0f
-#define PREV_Y 11.0f
+#define PREV_Y 13.0f
 #define NEXT_X 113.0f
-#define NEXT_Y 11.0f //prev_y
+#define NEXT_Y 13.0f //prev_y
 #define PAUSE_WIDTH 21.0f
 #define PAUSE_HEIGHT 27.0f
 #define BAR_WIDTH 4.5f
 #define BAR_HEIGHT 24.0f
 #define BAR_OFFSET 10.0f
 #define PAUSE_X 78.0f
-#define	PAUSE_Y 5.0f
+#define	PAUSE_Y 7.0f
 #define PLAY_WIDTH 28.0f
 #define PLAY_HEIGHT 29.0f
 #define PLAY_PADDING 5.0f

=== modified file 'src/player-controller.vala'
--- src/player-controller.vala	2010-07-29 12:19:00 +0000
+++ src/player-controller.vala	2010-08-11 19:11:21 +0000
@@ -48,12 +48,15 @@
 	private Dbusmenu.Menuitem root_menu;
 	public string name { get; set;}	
 	public ArrayList<PlayerItem> custom_items;	
+	public Mpris2Controller mpris2_adaptor;
 	public MprisController mpris_adaptor;
+	public bool mpris2;
 	public AppInfo? app_info { get; set;}
 	public int menu_offset { get; set;}
 		
 	public PlayerController(Dbusmenu.Menuitem root, string client_name, int offset, state initial_state)
 	{
+		this.mpris2 = false;
 		this.root_menu = root;
 		this.name = format_client_name(client_name.strip());
 		this.custom_items = new ArrayList<PlayerItem>();
@@ -74,7 +77,7 @@
 	public void activate()
 	{
 		this.establish_mpris_connection();	
-		this.custom_items[widget_order.METADATA].property_set_bool(MENUITEM_PROP_VISIBLE, true);		
+		//this.custom_items[widget_order.METADATA].property_set_bool(MENUITEM_PROP_VISIBLE, true);		
 	}
 
 	/*
@@ -100,23 +103,16 @@
 		if(this.current_state != state.READY){
 			debug("establish_mpris_connection - Not ready to connect");
 			return;
-		}
-
+		}		
 		if(this.name == "Vlc"){
 			debug("establishing a vlc mpris controller");
-			this.mpris_adaptor = new MprisController(this, "org.mpris.MediaPlayer.Player");
+			this.mpris2_adaptor = new Mpris2Controller(this);
+			this.mpris2 = true;
 		}
 		else{
 			this.mpris_adaptor = new MprisController(this);
 		}
-		// TODO refactor
-		if(this.mpris_adaptor.connected() == true){
-			debug("yup I'm connected");
-			this.update_state(state.CONNECTED);
-		}
-		else{
-			this.update_state(state.DISCONNECTED);
-		}
+		this.determine_state();
 	}
 	
 	public void vanish()
@@ -126,8 +122,17 @@
 		}
 	}
 
+	public void hibernate()
+	{
+		update_state(PlayerController.state.OFFLINE);
+		this.custom_items[widget_order.TRANSPORT].reset(TransportMenuitem.attributes_format());
+		this.custom_items[widget_order.METADATA].reset(MetadataMenuitem.attributes_format());
+		this.custom_items[widget_order.SCRUB].reset(ScrubMenuitem.attributes_format());			
+	}
+
 	public void update_layout()
-	{		
+	{	
+		
 		if(this.current_state != state.CONNECTED){
 			this.custom_items[widget_order.TRANSPORT].property_set_bool(MENUITEM_PROP_VISIBLE,
 			                                                            false);
@@ -137,12 +142,13 @@
 			                                                           false);
 	  	this.custom_items[widget_order.PLAYLIST].property_set_bool(MENUITEM_PROP_VISIBLE,
 			                                                           false);		
-			return;			
+			return;	
 		}
-		
 		debug("update layout - metadata %s", this.custom_items[widget_order.METADATA].populated(MetadataMenuitem.attributes_format()).to_string());
 		this.custom_items[widget_order.METADATA].property_set_bool(MENUITEM_PROP_VISIBLE,
 			                                                        this.custom_items[widget_order.METADATA].populated(MetadataMenuitem.attributes_format()));
+		//debug("metadata id %i", this.custom_items[widget_order.METADATA].id);
+		
 		debug("update layout - scrub %s", this.custom_items[widget_order.SCRUB].populated(ScrubMenuitem.attributes_format()).to_string());
 		this.custom_items[widget_order.SCRUB].property_set_bool(MENUITEM_PROP_VISIBLE,
 		                                                        this.custom_items[widget_order.SCRUB].populated(ScrubMenuitem.attributes_format()));
@@ -152,7 +158,7 @@
 		                                                            true);
 
 	  this.custom_items[widget_order.PLAYLIST].property_set_bool(MENUITEM_PROP_VISIBLE,
-		                                                            true);
+		                                                         true);	
 	}
 		
 	private void construct_widgets()
@@ -214,4 +220,48 @@
 		return formatted;
 	}
 
+	// Temporarily we will need to handle to different mpris implemenations
+	// Do it for now - a couple of weeks should see this messy carry on out of
+	// the codebase.
+	public void set_track_position(double pos)
+	{
+		if(this.mpris2 == true){ 
+			this.mpris2_adaptor.set_position(pos);
+		}
+		else{
+			this.mpris_adaptor.set_position(pos);			
+		}
+	}
+
+	public void transport_update(TransportMenuitem.action update)
+	{
+		if(this.mpris2 == true){ 
+			this.mpris2_adaptor.transport_event(update);
+		}
+		else{
+			this.mpris_adaptor.transport_event(update);			
+		}		
+	}
+
+	public void determine_state()
+	{
+		if(this.mpris2 == true){ 
+			if(this.mpris2_adaptor.connected() == true){
+				debug("yup I'm connected");
+				this.update_state(state.CONNECTED);
+			}
+			else{
+				this.update_state(state.DISCONNECTED);
+			}
+		}
+		else{
+			if(this.mpris_adaptor.connected() == true){
+				debug("yup I'm connected");
+				this.update_state(state.CONNECTED);
+			}
+			else{
+				this.update_state(state.DISCONNECTED);
+			}			
+		}			
+	}
 }
\ No newline at end of file

=== modified file 'src/player-item.vala'
--- src/player-item.vala	2010-07-27 11:39:51 +0000
+++ src/player-item.vala	2010-08-11 19:11:21 +0000
@@ -79,9 +79,11 @@
 				this.property_set_int(property, (int)v.get_uint());
 			}
 			else if(v.holds (typeof (bool))){
+				debug("with value : %s", v.get_boolean().to_string());				
 				this.property_set_bool(property, v.get_boolean());
 			}
 		}
+
 		if(this.property_get_bool(MENUITEM_PROP_VISIBLE) == false){
 			this.property_set_bool(MENUITEM_PROP_VISIBLE, true);
 		}

=== modified file 'src/scrub-menu-item.vala'
--- src/scrub-menu-item.vala	2010-07-27 11:39:51 +0000
+++ src/scrub-menu-item.vala	2010-08-11 19:11:21 +0000
@@ -32,13 +32,18 @@
 	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_adaptor.set_position(input_value.get_double());		
+		this.owner.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()
 	{

=== modified file 'src/scrub-widget.c'
--- src/scrub-widget.c	2010-07-29 12:19:00 +0000
+++ src/scrub-widget.c	2010-08-11 19:11:21 +0000
@@ -174,7 +174,7 @@
 	ScrubWidgetPrivate * priv = SCRUB_WIDGET_GET_PRIVATE(self);
 	gint play_state = dbusmenu_menuitem_property_get_int(priv->twin_item,
 	                                                     DBUSMENU_SCRUB_MENUITEM_PLAY_STATE);
-	
+	g_debug("play-state = %i", play_state);
 	if(play_state == 0){
 		g_debug("START TIMELINE");
 		ido_timeline_start(priv->time_line);

=== modified file 'src/transport-menu-item.vala'
--- src/transport-menu-item.vala	2010-07-22 17:56:43 +0000
+++ src/transport-menu-item.vala	2010-08-11 19:11:21 +0000
@@ -45,7 +45,7 @@
 		int input = input_value.get_int();
 		debug("handle_event with value %s", input.to_string());
 		debug("transport owner name = %s", this.owner.name);
-		this.owner.mpris_adaptor.transport_event((action)input);
+		this.owner.transport_update((action)input);
 	}	
 
 	public static HashSet<string> attributes_format()


Follow ups