Re: [Banshee-List] Multimediakeys Plugin



Hello Aaron,

i did no changes to specialkeys.cs file. I copied it over to a new class
MMKeysSpecialKeys. Mainly because i dont know much about c# (it was my
the first try :) ). But you are right, it would be better to modify
specialkeys.cs with my changes. I made a diff/patch but the filename
must be changed inside the patch must be changed :)

I also modified the plugin itself to use the SpecialKeys inside
Banshee.Base, hopefully it works, i did'nt tried it, but if there are
problems they should be only small ones.

Did you plan any other plugins at the moment? 

Bye Danilo

Am Donnerstag, den 26.01.2006, 15:52 -0500 schrieb Aaron Bockover:
> Also, I'd like the SpecialKeys.cs code to actually remain in
> Banshee.Base, as it can potentially be used for more than just
> MM-specific bindings. The actual binding of the MM-keys to control
> playback should be done in the plugin, like you have.
> 
> Thanks,
> Aaron
> 
> On Thu, 2006-01-26 at 19:15 +0100, Danilo Reinhardt wrote:
> > Hello,
> > 
> > im new to banshee and this list. I like banshee and it fits my needs.
> > The only thing i missed was the support for x11 multimedia keys. I found
> > this support in the code, but it is commented out. To readd it again
> > i've create a small plugin
> > 
> > I have "copied" the commented out code in latest banshee release 0.10.4
> > for multimedia key handling to a separate plugin. My changes are some
> > error handling and code for proper ungrabbing the keys.
> > 
> > I dont know why there was a decision to exclude this code from banshee,
> > but i think to add a plugin would be a good solution for the moment (or
> > longer) to get back this x11 integration capability. A least i hope
> > it :) And I hope this plugin will be added to the main plugins.
> > 
> > I doesnt tried to compile using the makefiles, maybe is miss something
> > to add in it.
> > 
> > Bye Danilo
> > 
> > _______________________________________________
> > Banshee-list mailing list
> > Banshee-list gnome org
> > http://mail.gnome.org/mailman/listinfo/banshee-list
> 
> _______________________________________________
> Banshee-list mailing list
> Banshee-list gnome org
> http://mail.gnome.org/mailman/listinfo/banshee-list
> 
--- Banshee.Base/SpecialKeys.cs	2005-12-04 22:53:16.000000000 +0100
+++ Banshee.Plugins/MMKeys/SpecialKeys.cs	2006-01-27 10:18:14.000000000 +0100
@@ -2,8 +2,8 @@
 /***************************************************************************
  *  SpecialKeys.cs
  *
- *  Copyright (C) 2005 Novell
- *  Written by Aaron Bockover (aaron aaronbock net)
+ *  Written by  Aaron Bockover (aaron aaronbock net)
+ *  Modified by Danilo Reinhardt (danilo reinhardt gmx net)
  ****************************************************************************/
 
 /*  THIS FILE IS LICENSED UNDER THE MIT LICENSE AS OUTLINED IMMEDIATELY BELOW: 
@@ -53,46 +53,102 @@
         private TimeSpan raise_delay = new TimeSpan(0);
         private DateTime last_raise = DateTime.MinValue;
         
+        private bool keysInited;
+        
         public SpecialKeys()
         {
             InitializeKeys();
         }
         
+        ~SpecialKeys() {
+        	UnitializeKeys();
+        }
+        
         public void RegisterHandler(SpecialKeyPressedHandler handler, params SpecialKey [] specialKeys)
         {
-            foreach(SpecialKey specialKey in specialKeys) {
-                int key = (int)key_map[specialKey];
-                key_registrations[key] = Delegate.Combine(key_registrations[key] as Delegate, handler);
+        	foreach(SpecialKey specialKey in specialKeys) {
+        		if (key_map.Contains(specialKey)) {
+	        		int key = (int)key_map[specialKey];
+		            key_registrations[key] = Delegate.Combine(key_registrations[key] as Delegate, handler);
+		        }
             }
         }
         
         public void UnregisterHandler(SpecialKeyPressedHandler handler, params SpecialKey [] specialKeys)
         {
             foreach(SpecialKey specialKey in specialKeys) {
-                int key = (int)key_map[specialKey];
-                key_registrations[key] = Delegate.Remove(key_registrations[key] as Delegate, handler); 
+            	if (key_map.Contains(specialKey)) {
+	                int key = (int)key_map[specialKey];
+	                key_registrations[key] = Delegate.Remove(key_registrations[key] as Delegate, handler); 
+	            }
             }
         }
         
+        public void UngrabKeys() {
+        	UnitializeKeys();	
+        }
+        
         private void InitializeKeys()
         {
-            ArrayList kc_list = new ArrayList();
+            if (!keysInited) {
+            	ArrayList kc_list = new ArrayList();
+            
+	            foreach(SpecialKey key in Enum.GetValues(typeof(SpecialKey))) {
+	               	IntPtr xdisplay = gdk_x11_get_default_xdisplay();
+	            	if (!xdisplay.Equals(IntPtr.Zero))
+	            	{
+		                int keycode = XKeysymToKeycode(xdisplay, key);
+		                if (keycode != 0) 
+		                {
+		                	key_map[keycode] = key;
+			                key_map[key] = keycode;
+			                kc_list.Add(keycode);
+			            }
+		            }
+	            }
+	            
+	            for(int i = 0; i < Gdk.Display.Default.NScreens; i++) {
+	                Gdk.Screen screen = Gdk.Display.Default.GetScreen(i);
+	                foreach(int keycode in kc_list) 
+	                {
+	                	GrabKey(screen.RootWindow, keycode);
+	                }
+	                screen.RootWindow.AddFilter(FilterKey);
+	            }
+	            keysInited = true;
+	        }
+            
+            
+        }
+        
+   
+        private void UnitializeKeys() {
+            if (keysInited) {
+    	    	ArrayList kc_list = new ArrayList();
+    	    	foreach(SpecialKey key in Enum.GetValues(typeof(SpecialKey))) {
+	               	IntPtr xdisplay = gdk_x11_get_default_xdisplay();
+	            	if (!xdisplay.Equals(IntPtr.Zero))
+	            	{
+		                int keycode = XKeysymToKeycode(xdisplay, key);
+		                if (keycode != 0) 
+		                {
+			                key_map[keycode] = key;
+			                key_map[key] = keycode;
+			                kc_list.Add(keycode);
+			    	}
+		            }
+	            }
+	        	for(int i = 0; i < Gdk.Display.Default.NScreens; i++) {
+	                Gdk.Screen screen = Gdk.Display.Default.GetScreen(i);
+	                foreach(int keycode in kc_list) 
+	                {
+	                    UngrabKey(screen.RootWindow, keycode);
+	                }
+	                screen.RootWindow.RemoveFilter(FilterKey);
+	            }
+	            keysInited = false;
+	        }
             
-            foreach(SpecialKey key in Enum.GetValues(typeof(SpecialKey))) {
-                int keycode = XKeysymToKeycode(gdk_x11_get_default_xdisplay(), key);
-                key_map[keycode] = key;
-                key_map[key] = keycode;
-                kc_list.Add(keycode);
-            }
-            
-            for(int i = 0; i < Gdk.Display.Default.NScreens; i++) {
-                Gdk.Screen screen = Gdk.Display.Default.GetScreen(i);
-                foreach(int keycode in kc_list) {
-                    GrabKey(screen.RootWindow, keycode);
-                }
-                
-                screen.RootWindow.AddFilter(FilterKey);
-            }
         }
         
         private void GrabKey(Gdk.Window root, int keycode)
@@ -112,8 +168,31 @@
             XGrabKey(xdisplay, keycode, XModMask.Mod2 | XModMask.Mod5 | XModMask.Lock, xid, true, 
                 XGrabMode.Async, XGrabMode.Async);
         
+        	gdk_flush ();
             if(gdk_error_trap_pop() != 0) {
-                Console.Error.WriteLine("Could not grab key {0}", keycode);
+                Console.Error.WriteLine(": Could not grab key {0} (maybe another application has grabbed this key)", keycode);
+            }
+        }
+        
+        private void UngrabKey(Gdk.Window root, int keycode)
+        {
+            IntPtr xid = gdk_x11_drawable_get_xid(root.Handle);
+            IntPtr xdisplay = gdk_x11_get_default_xdisplay();
+            
+            gdk_error_trap_push();
+            
+            XUngrabKey(xdisplay, keycode, XModMask.None, xid);
+            XUngrabKey(xdisplay, keycode, XModMask.Mod2, xid);
+            XUngrabKey(xdisplay, keycode, XModMask.Mod5, xid);
+            XUngrabKey(xdisplay, keycode, XModMask.Lock, xid);
+            XUngrabKey(xdisplay, keycode, XModMask.Mod2 | XModMask.Mod5, xid);
+            XUngrabKey(xdisplay, keycode, XModMask.Mod2 | XModMask.Lock, xid);
+            XUngrabKey(xdisplay, keycode, XModMask.Mod5 | XModMask.Lock, xid);
+            XUngrabKey(xdisplay, keycode, XModMask.Mod2 | XModMask.Mod5 | XModMask.Lock,xid);
+        
+            gdk_flush ();
+            if(gdk_error_trap_pop() != 0) {
+                Console.Error.WriteLine(": Could not ungrab key {0} (maybe another application has grabbed this key)", keycode);
             }
         }
         
@@ -131,20 +210,20 @@
             
             last_raise = DateTime.Now;
 
-                int keycode = (int)xevent.keycode;
-		object x = key_map [keycode];
-		if (x == null)
-			return Gdk.FilterReturn.Continue;
-
-                SpecialKey key = (SpecialKey)key_map[keycode];
-                
-                if(key_registrations[keycode] != null) {
-		    x = key_registrations [keycode];
-		    if (x is SpecialKeyPressedHandler){
+            int keycode = (int)xevent.keycode;
+			object x = key_map [keycode];
+			if (x == null)
+				return Gdk.FilterReturn.Continue;
+
+            SpecialKey key = (SpecialKey)key_map[keycode];
+            
+            if(key_registrations[keycode] != null) {
+		    	x = key_registrations [keycode];
+		    	if (x is SpecialKeyPressedHandler){
                         ((SpecialKeyPressedHandler)x)(this, key);	
-		    }
-                    return Gdk.FilterReturn.Remove;
-                }
+		    	}
+                return Gdk.FilterReturn.Remove;
+            }
             
             return Gdk.FilterReturn.Continue;
         }
@@ -185,18 +264,25 @@
         [DllImport("libX11")]
         extern static void XGrabKey(IntPtr display, int keycode, XModMask modifiers, 
             IntPtr window, bool owner_events, XGrabMode pointer_mode, XGrabMode keyboard_mode);
+            
+        [DllImport("libX11")]
+        extern static void XUngrabKey(IntPtr display, int keycode, XModMask modifiers, 
+            IntPtr window);
 
-        [DllImport("gdk-x11-2.0")]
-        static extern IntPtr gdk_x11_drawable_get_xid(IntPtr window);
+        [DllImport("libgdk-x11-2.0")]
+        extern static IntPtr gdk_x11_drawable_get_xid(IntPtr window);
+        
+        [DllImport("libgdk-x11-2.0")]
+        extern static IntPtr gdk_x11_get_default_xdisplay();
         
-        [DllImport("gdk-x11-2.0")]
-        static extern IntPtr gdk_x11_get_default_xdisplay();
+        [DllImport("libgdk-x11-2.0")]
+        extern static void gdk_error_trap_push();
         
-        [DllImport("gdk-x11-2.0")]
-        static extern void gdk_error_trap_push();
+        [DllImport("libgdk-x11-2.0")]
+        extern static int gdk_error_trap_pop();
         
-        [DllImport("gdk-x11-2.0")]
-        static extern int gdk_error_trap_pop();
+        [DllImport("libgdk-x11-2.0")]
+        extern static void gdk_flush();
         
         [Flags]
         private enum XModMask {
/* -*- Mode: csharp; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: t -*- */
/***************************************************************************
 *  MMKeysPlugin.cs
 *
 *  Written by Danilo Reinhardt (danilo reinhardt gmx net)
 ****************************************************************************/

/*  THIS FILE IS LICENSED UNDER THE MIT LICENSE AS OUTLINED IMMEDIATELY BELOW: 
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a
 *  copy of this software and associated documentation files (the "Software"),  
 *  to deal in the Software without restriction, including without limitation  
 *  the rights to use, copy, modify, merge, publish, distribute, sublicense,  
 *  and/or sell copies of the Software, and to permit persons to whom the  
 *  Software is furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in 
 *  all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
 *  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
 *  DEALINGS IN THE SOFTWARE. 
 */

using System;
using System.IO;
using Gtk;
using Gdk;
using Mono.Unix;

using Banshee.Base;


namespace Banshee.Plugins.MMKeysPlugin 
{
	public class MMKeysPlugin : Banshee.Plugins.Plugin
	{
		private Action playAction;
		private Action nextTrackAction;
		private Action prevTrackAction;
		
		private SpecialKeys special_keys;
		
		protected override string ConfigurationName { get { return "MMKeysPlugin"; } }
        public override string DisplayName { get { return "Multimediakeys"; } }
	
		public override string Description {
            get {
                return Catalog.GetString(
                    "Adding support for configured gnome multimedia keys."
                );
            }
        }

        public override string [] Authors {
            get {
                return new string [] {
                    "Danilo Reinhardt"
                };
            }
        }
        
        protected override void PluginInitialize()
        {
        	playAction = Globals.ActionManager["PlayPauseAction"];
            nextTrackAction = Globals.ActionManager["NextAction"];
            prevTrackAction = Globals.ActionManager["PreviousAction"];
            
            try {
                if((bool)Globals.Configuration.Get(GConfKeys.EnableSpecialKeys)) {
                    special_keys = new SpecialKeys();
                    special_keys.Delay = new TimeSpan(350 * TimeSpan.TicksPerMillisecond);
                    
                    special_keys.RegisterHandler(OnSpecialKeysPressed, 
                        SpecialKey.AudioPlay,
                        SpecialKey.AudioPrev,
                        SpecialKey.AudioNext
                    );
                }
            } catch(GConf.NoSuchKeyException) {
            } catch(Exception e) {
                special_keys = null;
                Console.WriteLine (e.Message);
                LogCore.Instance.PushWarning(Catalog.GetString("Could not setup special keys"), e.Message, false);
            }
            Console.WriteLine ("MMKeys: loaded");
        }
        
        private void OnSpecialKeysPressed(object o, SpecialKey key)
        {
            switch(key) {
                case SpecialKey.AudioPlay:
                    playAction.Activate();
                    break;
                case SpecialKey.AudioNext:
                    nextTrackAction.Activate();
                    break;
                case SpecialKey.AudioPrev:
                    prevTrackAction.Activate();
                    break;
            }
        }
        
        protected override void PluginDispose()
        {
            special_keys.UnregisterHandler(OnSpecialKeysPressed, 
                        SpecialKey.AudioPlay,
                        SpecialKey.AudioPrev,
                        SpecialKey.AudioNext
                    );
            special_keys.UngrabKeys();        
            special_keys = null;
        	playAction = null;
        	nextTrackAction = null;
        	prevTrackAction = null;
        	Console.WriteLine ("MMKeys: unloaded");
        }
        
        
	}
}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]