[banshee] [OsxBackend] Added OsxIntegration APIs



commit b5e8ba7e576487085d2ec69fb9672edaa9cb4072
Author: Aaron Bockover <abockover novell com>
Date:   Wed Feb 24 15:45:30 2010 -0500

    [OsxBackend] Added OsxIntegration APIs
    
    Many thanks to Michael Hutchinson for his work here. OsxIntegration.Framework
    is lifted from MonoDevelop. There's a thin IgeMacIntegratiokn binding to
    handle the GTK menu proxying. No longer do we depend on
    ige-mac-integration-sharp, and soon enough we won't need ige-mac-integration.

 .../OsxIntegration.Framework/AppleEvent.cs         |   41 ++
 .../OsxIntegration.Framework/ApplicationEvents.cs  |  219 ++++++
 .../Banshee.Osx/OsxIntegration.Framework/Carbon.cs |  692 +++++++++++++++++++
 .../OsxIntegration.Framework/CoreFoundation.cs     |   95 +++
 .../OsxIntegration.Framework/HIToolbox.cs          |  713 ++++++++++++++++++++
 .../OsxIntegration.Framework/NavDialog.cs          |  513 ++++++++++++++
 .../Banshee.Osx/OsxIntegration.Ige/IgeMacMenu.cs   |   74 ++
 .../OsxIntegration.Ige/IgeMacMenuGroup.cs          |   54 ++
 8 files changed, 2401 insertions(+), 0 deletions(-)
---
diff --git a/src/Backends/Banshee.Osx/OsxIntegration.Framework/AppleEvent.cs b/src/Backends/Banshee.Osx/OsxIntegration.Framework/AppleEvent.cs
new file mode 100644
index 0000000..4541889
--- /dev/null
+++ b/src/Backends/Banshee.Osx/OsxIntegration.Framework/AppleEvent.cs
@@ -0,0 +1,41 @@
+// 
+// AppleEvent.cs
+//  
+// Author:
+//       Michael Hutchinson <mhutchinson novell com>
+// 
+// Copyright (c) 2010 Novell, Inc.
+// 
+// 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.Runtime.InteropServices;
+
+#pragma warning disable 0169
+
+namespace OsxIntegration.Framework
+{
+	public static class AppleEvent
+	{
+		const string AELib = Carbon.CarbonLib;
+		
+		//[DllImport (AELib)]
+		//OSErr AECreateDesc (DescType typeCode, IntPtr dataPtr, Size dataSize, out AEDesc result);
+	}
+}
+
diff --git a/src/Backends/Banshee.Osx/OsxIntegration.Framework/ApplicationEvents.cs b/src/Backends/Banshee.Osx/OsxIntegration.Framework/ApplicationEvents.cs
new file mode 100644
index 0000000..d7cabf6
--- /dev/null
+++ b/src/Backends/Banshee.Osx/OsxIntegration.Framework/ApplicationEvents.cs
@@ -0,0 +1,219 @@
+// 
+// ApplicationEvents.cs
+//  
+// Author:
+//       Michael Hutchinson <mhutchinson novell com>
+// 
+// Copyright (c) 2010 Novell, Inc. (http://www.novell.com)
+// 
+// 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.Collections.Generic;
+
+#pragma warning disable 0169
+
+namespace OsxIntegration.Framework
+{
+	public static class ApplicationEvents
+	{
+		static object lockObj = new object ();
+		
+		#region Quit
+		
+		static EventHandler<ApplicationEventArgs> quit;
+		static IntPtr quitHandlerRef = IntPtr.Zero;
+		
+		public static event EventHandler<ApplicationEventArgs> Quit {
+			add {
+				lock (lockObj) {
+					quit += value;
+					if (quitHandlerRef == IntPtr.Zero)
+						quitHandlerRef = Carbon.InstallApplicationEventHandler (HandleQuit, CarbonEventApple.QuitApplication);
+				}
+			}
+			remove {
+				lock (lockObj) {
+					quit -= value;
+					if (quit == null && quitHandlerRef != IntPtr.Zero) {
+						Carbon.RemoveEventHandler (quitHandlerRef);
+						quitHandlerRef = IntPtr.Zero;
+					}
+				}
+			}
+		}
+		
+		static CarbonEventHandlerStatus HandleQuit (IntPtr callRef, IntPtr eventRef, IntPtr user_data)
+		{
+			var args = new ApplicationEventArgs ();
+			quit (null, args);
+			return args.HandledStatus;
+		}
+		
+		#endregion
+		
+		#region Reopen
+		
+		static EventHandler<ApplicationEventArgs> reopen;
+		static IntPtr reopenHandlerRef = IntPtr.Zero;
+		
+		public static event EventHandler<ApplicationEventArgs> Reopen {
+			add {
+				lock (lockObj) {
+					reopen += value;
+					if (reopenHandlerRef == IntPtr.Zero)
+						reopenHandlerRef = Carbon.InstallApplicationEventHandler (HandleReopen, CarbonEventApple.ReopenApplication);
+				}
+			}
+			remove {
+				lock (lockObj) {
+					reopen -= value;
+					if (reopen == null && reopenHandlerRef != IntPtr.Zero) {
+						Carbon.RemoveEventHandler (reopenHandlerRef);
+						reopenHandlerRef = IntPtr.Zero;
+					}
+				}
+			}
+		}
+		
+		static CarbonEventHandlerStatus HandleReopen (IntPtr callRef, IntPtr eventRef, IntPtr user_data)
+		{
+			var args = new ApplicationEventArgs ();
+			reopen (null, args);
+			return args.HandledStatus;
+		}
+		
+		#endregion
+		
+		#region OpenDocuments
+		
+		static EventHandler<ApplicationDocumentEventArgs> openDocuments;
+		static IntPtr openDocumentsHandlerRef = IntPtr.Zero;
+		
+		public static event EventHandler<ApplicationDocumentEventArgs> OpenDocuments {
+			add {
+				lock (lockObj) {
+					openDocuments += value;
+					if (openDocumentsHandlerRef == IntPtr.Zero)
+						openDocumentsHandlerRef = Carbon.InstallApplicationEventHandler (HandleOpenDocuments, CarbonEventApple.OpenDocuments);
+				}
+			}
+			remove {
+				lock (lockObj) {
+					openDocuments -= value;
+					if (openDocuments == null && openDocumentsHandlerRef != IntPtr.Zero) {
+						Carbon.RemoveEventHandler (openDocumentsHandlerRef);
+						openDocumentsHandlerRef = IntPtr.Zero;
+					}
+				}
+			}
+		}
+		
+		static CarbonEventHandlerStatus HandleOpenDocuments (IntPtr callRef, IntPtr eventRef, IntPtr user_data)
+		{
+			try {
+				var docs = Carbon.GetFileListFromEventRef (eventRef);
+				var args = new ApplicationDocumentEventArgs (docs);
+				openDocuments (null, args);
+				return args.HandledStatus;
+			} catch (Exception ex) {
+				System.Console.WriteLine (ex);
+				return CarbonEventHandlerStatus.NotHandled;
+			}
+		}
+		
+		#endregion
+		
+		#region OpenUrls
+		
+		static EventHandler<ApplicationUrlEventArgs> openUrls;
+		static IntPtr openUrlsHandlerRef = IntPtr.Zero;
+		
+		public static event EventHandler<ApplicationUrlEventArgs> OpenUrls {
+			add {
+				lock (lockObj) {
+					openUrls += value;
+					if (openUrlsHandlerRef == IntPtr.Zero)
+						openUrlsHandlerRef = Carbon.InstallApplicationEventHandler (HandleOpenUrls,
+							new CarbonEventTypeSpec[] {
+								//For some reason GetUrl doesn't take CarbonEventClass.AppleEvent
+								//need to use GURL, GURL
+								new CarbonEventTypeSpec (CarbonEventClass.Internet, (int)CarbonEventApple.GetUrl)
+							}
+						);
+				}
+			}
+			remove {
+				lock (lockObj) {
+					openUrls -= value;
+					if (openUrls == null && openUrlsHandlerRef != IntPtr.Zero) {
+						Carbon.RemoveEventHandler (openUrlsHandlerRef);
+						openUrlsHandlerRef = IntPtr.Zero;
+					}
+				}
+			}
+		}
+		
+		static CarbonEventHandlerStatus HandleOpenUrls (IntPtr callRef, IntPtr eventRef, IntPtr user_data)
+		{
+			try {
+				var urls = Carbon.GetUrlListFromEventRef (eventRef);
+				var args = new ApplicationUrlEventArgs (urls);
+				openUrls (null, args);
+				return args.HandledStatus;
+			} catch (Exception ex) {
+				System.Console.WriteLine (ex);
+				return CarbonEventHandlerStatus.NotHandled;
+			}
+		}
+		
+		#endregion
+	}
+	
+	public class ApplicationEventArgs : EventArgs
+	{
+		public bool Handled { get; set; }
+		
+		internal CarbonEventHandlerStatus HandledStatus {
+			get {
+				return Handled? CarbonEventHandlerStatus.Handled : CarbonEventHandlerStatus.NotHandled;
+			}
+		}
+	}
+	
+	public class ApplicationDocumentEventArgs : ApplicationEventArgs
+	{
+		public ApplicationDocumentEventArgs (IList<string> documents)
+		{
+			this.Documents = documents;
+		}		
+		
+		public IList<string> Documents { get; private set; }
+	}
+	
+	public class ApplicationUrlEventArgs : ApplicationEventArgs
+	{
+		public ApplicationUrlEventArgs (IList<string> urls)
+		{
+			this.Urls = urls;
+		}		
+		
+		public IList<string> Urls { get; private set; }
+	}
+}
+
diff --git a/src/Backends/Banshee.Osx/OsxIntegration.Framework/Carbon.cs b/src/Backends/Banshee.Osx/OsxIntegration.Framework/Carbon.cs
new file mode 100644
index 0000000..67065c4
--- /dev/null
+++ b/src/Backends/Banshee.Osx/OsxIntegration.Framework/Carbon.cs
@@ -0,0 +1,692 @@
+// 
+// Carbon.cs
+//  
+// Author:
+//       Michael Hutchinson <mhutchinson novell com>
+//       Geoff Norton  <gnorton novell com>
+// 
+// Copyright (c) 2009 Novell, Inc. (http://www.novell.com)
+// 
+// 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.Runtime.InteropServices;
+using System.Collections.Generic;
+
+#pragma warning disable 0169
+
+namespace OsxIntegration.Framework
+{
+	internal delegate CarbonEventHandlerStatus EventDelegate (IntPtr callRef, IntPtr eventRef, IntPtr userData);
+	internal delegate CarbonEventHandlerStatus AEHandlerDelegate (IntPtr inEvnt, IntPtr outEvt, uint refConst);
+	
+	internal static class Carbon
+	{
+		public const string CarbonLib = "/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon";
+		
+		[DllImport (CarbonLib)]
+		public static extern IntPtr GetApplicationEventTarget ();
+		
+		[DllImport (CarbonLib)]
+		public static extern IntPtr GetControlEventTarget (IntPtr control);
+		
+		[DllImport (CarbonLib)]
+		public static extern IntPtr GetWindowEventTarget (IntPtr window);
+		
+		[DllImport (CarbonLib)]
+		public static extern IntPtr GetMenuEventTarget (IntPtr menu);
+
+		[DllImport (CarbonLib)]
+		public static extern CarbonEventClass GetEventClass (IntPtr eventref);
+		
+		[DllImport (CarbonLib)]
+		public static extern uint GetEventKind (IntPtr eventref);
+		
+		#region Event handler installation
+		
+		[DllImport (CarbonLib)]
+		static extern EventStatus InstallEventHandler (IntPtr target, EventDelegate handler, uint count,
+		                                               CarbonEventTypeSpec [] types, IntPtr user_data, out IntPtr handlerRef);
+		
+		[DllImport (CarbonLib)]
+		public static extern EventStatus RemoveEventHandler (IntPtr handlerRef);
+		
+		public static IntPtr InstallEventHandler (IntPtr target, EventDelegate handler, CarbonEventTypeSpec [] types)
+		{
+			IntPtr handlerRef;
+			CheckReturn (InstallEventHandler (target, handler, (uint)types.Length, types, IntPtr.Zero, out handlerRef));
+			return handlerRef;
+		}
+		
+		public static IntPtr InstallEventHandler (IntPtr target, EventDelegate handler, CarbonEventTypeSpec type)
+		{
+			return InstallEventHandler (target, handler, new CarbonEventTypeSpec[] { type });
+		}
+		
+		public static IntPtr InstallApplicationEventHandler (EventDelegate handler, CarbonEventTypeSpec [] types)
+		{
+			return InstallEventHandler (GetApplicationEventTarget (), handler, types);
+		}
+		
+		public static IntPtr InstallApplicationEventHandler (EventDelegate handler, CarbonEventTypeSpec type)
+		{
+			return InstallEventHandler (GetApplicationEventTarget (), handler, new CarbonEventTypeSpec[] { type });
+		}
+		
+		#endregion
+		
+		#region Event parameter extraction
+		
+		[DllImport (CarbonLib)]
+		public static extern EventStatus GetEventParameter (IntPtr eventRef, CarbonEventParameterName name, CarbonEventParameterType desiredType,
+		                                                    out CarbonEventParameterType actualType, uint size, ref uint outSize, ref IntPtr outPtr);
+		
+		public static IntPtr GetEventParameter (IntPtr eventRef, CarbonEventParameterName name, CarbonEventParameterType desiredType)
+		{
+			CarbonEventParameterType actualType;
+			uint outSize = 0;
+			IntPtr val = IntPtr.Zero;
+			CheckReturn (GetEventParameter (eventRef, name, desiredType, out actualType, (uint)IntPtr.Size, ref outSize, ref val));
+			return val;
+		} 
+		
+		[DllImport (CarbonLib)]
+		static extern EventStatus GetEventParameter (IntPtr eventRef, CarbonEventParameterName name, CarbonEventParameterType desiredType,	
+		                                             out CarbonEventParameterType actualType, uint size, ref uint outSize, IntPtr dataBuffer);
+		  
+		[DllImport (CarbonLib)]
+		static extern EventStatus GetEventParameter (IntPtr eventRef, CarbonEventParameterName name, CarbonEventParameterType desiredType,	
+		                                             uint zero, uint size, uint zero2, IntPtr dataBuffer);
+		
+		public static T GetEventParameter<T> (IntPtr eventRef, CarbonEventParameterName name, CarbonEventParameterType desiredType) where T : struct
+		{
+			int len = Marshal.SizeOf (typeof (T));
+			IntPtr bufferPtr = Marshal.AllocHGlobal (len);
+			CheckReturn (GetEventParameter (eventRef, name, desiredType, 0, (uint)len, 0, bufferPtr));
+			T val = (T)Marshal.PtrToStructure (bufferPtr, typeof (T));
+			Marshal.FreeHGlobal (bufferPtr);
+			return val;
+		}
+		
+		#endregion
+		
+		#region Sending events
+		
+		[DllImport (CarbonLib)]
+		static extern EventStatus SendEventToEventTarget (IntPtr eventRef, IntPtr eventTarget);
+		
+		[DllImport (CarbonLib)]
+		static extern EventStatus CreateEvent (IntPtr allocator, CarbonEventClass classID, uint kind, double eventTime,
+		                                       CarbonEventAttributes flags, out IntPtr eventHandle);
+		
+		[DllImport (CarbonLib)]
+		static extern void ReleaseEvent (IntPtr eventHandle);
+		
+		static EventStatus SendApplicationEvent (CarbonEventClass classID, uint kind, CarbonEventAttributes flags)
+		{
+			IntPtr eventHandle;
+			EventStatus s = CreateEvent (IntPtr.Zero, classID, kind, 0, flags, out eventHandle);
+			if (s != EventStatus.Ok)
+				return s;
+			s = SendEventToEventTarget (eventHandle, GetApplicationEventTarget ());
+			ReleaseEvent (eventHandle);
+			return s;
+		}
+		
+		[DllImport (CarbonLib)]
+		public static extern CarbonEventHandlerStatus ProcessHICommand (ref CarbonHICommand command);
+		
+		#endregion
+		
+		#region AEList manipulation
+		
+		[DllImport (CarbonLib)]
+		static extern int AECountItems (ref AEDesc descList, out int count); //return an OSErr
+		
+		public static int AECountItems (ref AEDesc descList)
+		{
+			int count;
+			CheckReturn (AECountItems (ref descList, out count));
+			return count;
+		}
+		
+		[DllImport (CarbonLib)]
+		static extern AEDescStatus AEGetNthPtr (ref AEDesc descList, int index, CarbonEventParameterType desiredType, uint keyword,
+		                                        out CarbonEventParameterType actualType, IntPtr buffer, int bufferSize, out int actualSize);
+		
+		[DllImport (CarbonLib)]
+		static extern AEDescStatus AEGetNthPtr (ref AEDesc descList, int index, CarbonEventParameterType desiredType, uint keyword,
+		                                        uint zero, IntPtr buffer, int bufferSize, int zero2);
+		
+		public static T AEGetNthPtr<T> (ref AEDesc descList, int index, CarbonEventParameterType desiredType) where T : struct
+		{
+			int len = Marshal.SizeOf (typeof (T));
+			IntPtr bufferPtr = Marshal.AllocHGlobal (len);
+			try {
+				CheckReturn ((int)AEGetNthPtr (ref descList, index, desiredType, 0, 0, bufferPtr, len, 0));
+				T val = (T)Marshal.PtrToStructure (bufferPtr, typeof (T));
+				return val;
+			} finally{ 
+				Marshal.FreeHGlobal (bufferPtr);
+			}
+		}
+		
+		[DllImport (CarbonLib)]
+		static extern AEDescStatus AEGetNthPtr (ref AEDesc descList, int index, CarbonEventParameterType desiredType, uint keyword,
+		                                        uint zero, out IntPtr outPtr, int bufferSize, int zero2);
+		
+		public static IntPtr AEGetNthPtr (ref AEDesc descList, int index, CarbonEventParameterType desiredType)
+		{
+			IntPtr ret;
+			CheckReturn ((int)AEGetNthPtr (ref descList, index, desiredType, 0, 0, out ret, 4, 0));
+			return ret;
+		}
+		
+		[DllImport (CarbonLib)]
+		public static extern int AEDisposeDesc (ref AEDesc desc);
+		
+		[DllImport (CarbonLib)]
+		public static extern AEDescStatus AESizeOfNthItem  (ref AEDesc descList, int index, ref CarbonEventParameterType type, out int size);
+		
+		//FIXME: this might not work in some encodings. need to test more.
+		static string GetStringFromAEPtr (ref AEDesc descList, int index)
+		{
+			int size;
+			CarbonEventParameterType type = CarbonEventParameterType.UnicodeText;
+			if (AESizeOfNthItem (ref descList, index, ref type, out size) == AEDescStatus.Ok) {
+				IntPtr buffer = Marshal.AllocHGlobal (size);
+				try {
+					if (AEGetNthPtr (ref descList, index, type, 0, 0, buffer, size, 0) == AEDescStatus.Ok)
+						return Marshal.PtrToStringAuto (buffer, size);
+				} finally {
+					Marshal.FreeHGlobal (buffer);
+				}
+			}
+			return null;
+		}
+		
+		#endregion
+		
+		[DllImport (CarbonLib)]
+		static extern int FSRefMakePath (ref FSRef fsRef, IntPtr buffer, uint bufferSize);
+		
+		public static string FSRefToPath (ref FSRef fsRef)
+		{
+			//FIXME: is this big enough?
+			const int MAX_LENGTH = 4096;
+			IntPtr buf = IntPtr.Zero;
+			string ret;
+			try {
+				buf = Marshal.AllocHGlobal (MAX_LENGTH);
+				CheckReturn (FSRefMakePath (ref fsRef, buf, (uint)MAX_LENGTH));
+				//FIXME: on Mono, auto is UTF-8, which is correct but I'd prefer to be more explicit
+				ret = Marshal.PtrToStringAuto (buf, MAX_LENGTH);
+			} finally {
+				if (buf != IntPtr.Zero)
+					Marshal.FreeHGlobal (buf);
+			}
+			return ret;
+		}
+		
+		#region Error checking
+		
+		public static void CheckReturn (EventStatus status)
+		{
+			int intStatus = (int) status;
+			if (intStatus < 0)
+				throw new EventStatusException (status);
+		}
+		
+		public static void CheckReturn (int osErr)
+		{
+			if (osErr != 0) {
+				string s = GetMacOSStatusCommentString (osErr);
+				throw new SystemException ("Unexpected OS error code " + osErr + ": " + s);
+			}
+		}
+		
+		[DllImport (CarbonLib)]
+		static extern string GetMacOSStatusCommentString (int osErr);
+		
+		#endregion
+		
+		#region Char code conversion
+		
+		internal static int ConvertCharCode (string code)
+		{
+			return (code[3]) | (code[2] << 8) | (code[1] << 16) | (code[0] << 24);
+		}
+		
+		internal static string UnConvertCharCode (int i)
+		{
+			return new string (new char[] {
+				(char)(i >> 24),
+				(char)(0xFF & (i >> 16)),
+				(char)(0xFF & (i >> 8)),
+				(char)(0xFF & i),
+			});
+		}
+		
+		#endregion
+		
+		#region Navigation services
+		
+		[DllImport (CarbonLib)]
+		static extern NavStatus NavDialogSetFilterTypeIdentifiers (IntPtr getFileDialogRef, IntPtr typeIdentifiersCFArray);
+		
+		
+		[DllImport (CarbonLib)]
+		static extern NavEventUPP NewNavEventUPP (NavEventProc userRoutine);
+		
+		[DllImport (CarbonLib)]
+		static extern NavObjectFilterUPP NewNavObjectFilterUPP (NavObjectFilterProc userRoutine);
+		
+		[DllImport (CarbonLib)]
+		static extern NavPreviewUPP NewNavPreviewUPP (NavPreviewProc userRoutine);
+		
+		delegate void NavEventProc (NavEventCallbackMessage callBackSelector, ref NavCBRec callBackParms, IntPtr callBackUD);
+		
+		delegate bool NavObjectFilterProc (ref AEDesc theItem, IntPtr info, IntPtr callBackUD, NavFilterModes filterMode);
+		
+		delegate bool NavPreviewProc (ref NavCBRec callBackParms, IntPtr callBackUD);
+		
+		[DllImport (CarbonLib)]
+		static extern void DisposeNavEventUPP (NavEventUPP userUPP);
+		
+		[DllImport (CarbonLib)]
+		static extern void DisposeNavObjectFilterUPP (NavObjectFilterUPP userUPP);
+		
+		[DllImport (CarbonLib)]
+		static extern void DisposeNavPreviewUPP (NavPreviewUPP userUPP);
+		
+		#endregion
+		
+		#region Internal Mac API for setting process name
+		
+		[DllImport (CarbonLib)]
+		static extern int GetCurrentProcess (out ProcessSerialNumber psn);
+		
+		[DllImport (CarbonLib)]
+		static extern int CPSSetProcessName (ref ProcessSerialNumber psn, string name);
+		
+		public static void SetProcessName (string name)
+		{
+			try {
+				ProcessSerialNumber psn;
+				if (GetCurrentProcess (out psn) == 0)
+					CPSSetProcessName (ref psn, name);
+			} catch {} //EntryPointNotFoundException?
+		}
+		
+		struct ProcessSerialNumber {
+			ulong highLongOfPSN;
+			ulong lowLongOfPSN;
+		}
+		
+		#endregion
+		
+		public static List<string> GetFileListFromEventRef (IntPtr eventRef)
+		{
+			AEDesc list = GetEventParameter<AEDesc> (eventRef, CarbonEventParameterName.DirectObject, CarbonEventParameterType.AEList);
+			long count = AECountItems (ref list);
+			var files = new List<string> ();
+			for (int i = 1; i <= count; i++) {
+				FSRef fsRef = AEGetNthPtr<FSRef> (ref list, i, CarbonEventParameterType.FSRef);
+				string file = FSRefToPath (ref fsRef);
+				if (!string.IsNullOrEmpty (file))
+					files.Add (file);
+			}
+			CheckReturn (AEDisposeDesc (ref list));
+			return files;
+		}
+		
+		public static List<string> GetUrlListFromEventRef (IntPtr eventRef)
+		{
+			AEDesc list = GetEventParameter<AEDesc> (eventRef, CarbonEventParameterName.DirectObject, CarbonEventParameterType.AEList);
+			long count = AECountItems (ref list);
+			var files = new List<string> ();
+			for (int i = 1; i <= count; i++) {
+				string url = GetStringFromAEPtr (ref list, i); 
+				if (!string.IsNullOrEmpty (url))
+					files.Add (url);
+			}
+			Carbon.CheckReturn (Carbon.AEDisposeDesc (ref list));
+			return files;
+		}
+	}
+	
+	
+	[StructLayout(LayoutKind.Sequential, Pack = 2)]
+	struct AEDesc
+	{
+		uint descriptorType;
+		IntPtr dataHandle;
+	}
+	
+	[StructLayout(LayoutKind.Sequential, Pack = 2, Size = 80)]
+	struct FSRef
+	{
+		//this is an 80-char opaque byte array
+		private byte hidden;
+	}
+	
+	internal enum CarbonEventHandlerStatus //this is an OSStatus
+	{
+		Handled = 0,
+		NotHandled = -9874,
+	}
+	
+	internal enum CarbonEventParameterName : uint
+	{
+		DirectObject = 757935405, // '----'
+	}
+	
+	internal enum CarbonEventParameterType : uint
+	{
+		HICommand = 1751346532, // 'hcmd'
+		MenuRef = 1835363957, // 'menu'
+		WindowRef = 2003398244, // 'wind'
+		Char = 1413830740, // 'TEXT'
+		UInt32 = 1835100014, // 'magn'
+		UnicodeText = 1970567284, // 'utxt'
+		AEList = 1818850164, // 'list'
+		WildCard = 707406378, // '****'
+		FSRef = 1718841958, // 'fsrf' 
+	}
+	
+	internal enum CarbonEventClass : uint
+	{
+		Mouse = 1836021107, // 'mous'
+		Keyboard = 1801812322, // 'keyb'
+		TextInput = 1952807028, // 'text'
+		Application = 1634758764, // 'appl'
+		RemoteAppleEvent = 1701867619,  //'eppc' //remote apple event?
+		Menu = 1835363957, // 'menu'
+		Window = 2003398244, // 'wind'
+		Control = 1668183148, // 'cntl'
+		Command = 1668113523, // 'cmds'
+		Tablet = 1952607348, // 'tblt'
+		Volume = 1987013664, // 'vol '
+		Appearance = 1634758765, // 'appm'
+		Service = 1936028278, // 'serv'
+		Toolbar = 1952604530, // 'tbar'
+		ToolbarItem = 1952606580, // 'tbit'
+		Accessibility = 1633903461, // 'acce'
+		HIObject = 1751740258, // 'hiob'
+		AppleEvent = 1634039412, // 'aevt'
+		Internet = 1196773964, // 'GURL'
+	}
+	
+	public enum CarbonCommandID : uint
+	{
+		OK = 1869291552, // 'ok  '
+		Cancel = 1852797985, // 'not!'
+		Quit = 1903520116, // 'quit'
+		Undo = 1970168943, // 'undo'
+		Redo = 1919247471, // 'redo'
+		Cut = 1668641824, // 'cut '
+		Copy = 1668247673, // 'copy'
+		Paste = 1885434740, // 'past'
+		Clear = 1668048225, // 'clea',
+		SelectAll = 1935764588, // 'sall',
+		Preferences = 1886545254, //'pref'
+		About = 1633841013, // 'abou'
+		New = 1852143392, // 'new ',
+		Open = 1869636974, // 'open'
+		Close = 1668050803, // 'clos'
+		Save = 1935767141, // 'save',
+		SaveAs = 1937138035, // 'svas'
+		Revert = 1920365172, // 'rvrt'
+		Print = 1886547572, // 'prnt'
+		PageSetup = 1885431653, // 'page',
+		AppHelp = 1634233456, //'ahlp'
+		
+		//menu manager handles these automatically
+		
+		Hide = 1751737445, // 'hide'
+		HideOthers = 1751737455, // 'hido'
+		ShowAll = 1936220524, // 'shal'
+		ZoomWindow = 2054123373, // 'zoom'
+		MinimizeWindow = 1835626089, // 'mini'
+		MinimizeAll = 1835626081, // 'mina'
+		MaximizeAll = 1835104353, // 'maxa'
+		ArrangeInFront = 1718775412, // 'frnt'
+		BringAllToFront = 1650881140, // 'bfrt'
+		SelectWindow = 1937205614, // 'swin'
+		RotateWindowsForward = 1919906935, // 'rotw'
+		RotateWindowsBackward = 1919906914, // 'rotb'
+		RotateFloatingWindowsForward = 1920231031, // 'rtfw'
+		RotateFloatingWindowsBackward = 1920231010, // 'rtfb'
+		
+		//created automatically -- used for inserting before/after the default window list
+		WindowListSeparator = 2003592310, // 'wldv'
+		WindowListTerminator = 2003596148, // 'wlst'
+	}
+	
+	internal enum CarbonEventCommand : uint
+	{
+		Process = 1,
+		UpdateStatus = 2,
+	}
+	
+	internal enum CarbonEventMenu : uint
+	{
+		BeginTracking = 1,
+		EndTracking = 2,
+		ChangeTrackingMode = 3,
+		Opening = 4,
+		Closed = 5,
+		TargetItem = 6,
+		MatchKey = 7,
+	}
+	
+	internal enum CarbonEventAttributes : uint
+	{
+		None = 0,
+		UserEvent = (1 << 0),
+		Monitored= 1 << 3,
+	}
+	
+	internal enum CarbonEventApple
+	{
+		OpenApplication = 1868656752, // 'oapp'
+		ReopenApplication = 1918988400, //'rapp'
+		OpenDocuments = 1868853091, // 'odoc'
+		PrintDocuments = 188563030, // 'pdoc'
+		OpenContents = 1868787566, // 'ocon'
+		QuitApplication =  1903520116, // 'quit'
+		ShowPreferences = 1886545254, // 'pref'
+		ApplicationDied = 1868720500, // 'obit'
+		GetUrl = 1196773964, // 'GURL'
+	}
+	
+	[StructLayout(LayoutKind.Sequential, Pack = 2)]
+	struct CarbonEventTypeSpec
+	{
+		public CarbonEventClass EventClass;
+		public uint EventKind;
+
+		public CarbonEventTypeSpec (CarbonEventClass eventClass, UInt32 eventKind)
+		{
+			this.EventClass = eventClass;
+			this.EventKind = eventKind;
+		}
+		
+		public CarbonEventTypeSpec (CarbonEventMenu kind) : this (CarbonEventClass.Menu, (uint) kind)
+		{
+		}
+		
+		public CarbonEventTypeSpec (CarbonEventCommand kind) : this (CarbonEventClass.Command, (uint) kind)
+		{
+		}
+		
+		
+		public CarbonEventTypeSpec (CarbonEventApple kind) : this (CarbonEventClass.AppleEvent, (uint) kind)
+		{
+		}
+		
+		public static implicit operator CarbonEventTypeSpec (CarbonEventMenu kind)
+		{
+			return new CarbonEventTypeSpec (kind);
+		}
+		
+		public static implicit operator CarbonEventTypeSpec (CarbonEventCommand kind)
+		{
+			return new CarbonEventTypeSpec (kind);
+		}
+		
+		public static implicit operator CarbonEventTypeSpec (CarbonEventApple kind)
+		{
+			return new CarbonEventTypeSpec (kind);
+		}
+	}
+	
+	class EventStatusException : SystemException
+	{
+		public EventStatusException (EventStatus status)
+		{
+			StatusCode = status;
+		}
+		
+		public EventStatus StatusCode {
+			get; private set;
+		}
+	}
+	
+	enum EventStatus // this is an OSStatus
+	{
+		Ok = 0,
+		
+		//event manager
+		EventAlreadyPostedErr = -9860,
+		EventTargetBusyErr = -9861,
+		EventClassInvalidErr = -9862,
+		EventClassIncorrectErr = -9864,
+		EventHandlerAlreadyInstalledErr = -9866,
+		EventInternalErr = -9868,
+		EventKindIncorrectErr = -9869,
+		EventParameterNotFoundErr = -9870,
+		EventNotHandledErr = -9874,
+		EventLoopTimedOutErr = -9875,
+		EventLoopQuitErr = -9876,
+		EventNotInQueueErr = -9877,
+		EventHotKeyExistsErr = -9878,
+		EventHotKeyInvalidErr = -9879,
+	}
+	
+	enum AEDescStatus
+	{
+		Ok = 0,
+		MemoryFull = -108,
+		CoercionFail = -1700,
+		DescRecordNotFound = -1701,
+		WrongDataType = -1703,
+		NotAEDesc = -1704,
+		ReplyNotArrived = -1718,
+	}
+	
+	[StructLayout(LayoutKind.Explicit)]
+	struct CarbonHICommand //technically HICommandExtended, but they're compatible
+	{
+		[FieldOffset(0)]
+		CarbonHICommandAttributes attributes;
+		
+		[FieldOffset(4)]
+		uint commandID;
+		
+		[FieldOffset(8)]
+		IntPtr controlRef;
+		
+		[FieldOffset(8)]
+		IntPtr windowRef;
+		
+		[FieldOffset(8)]
+		HIMenuItem menuItem;
+		
+		public CarbonHICommand (uint commandID, HIMenuItem item)
+		{
+			windowRef = controlRef = IntPtr.Zero;
+			this.commandID = commandID;
+			this.menuItem = item;
+			this.attributes = CarbonHICommandAttributes.FromMenu;
+		}
+		
+		public CarbonHICommandAttributes Attributes { get { return attributes; } }
+		public uint CommandID { get { return commandID; } }
+		public IntPtr ControlRef { get { return controlRef; } }
+		public IntPtr WindowRef { get { return windowRef; } }
+		public HIMenuItem MenuItem { get { return menuItem; } }
+		
+		public bool IsFromMenu {
+			get { return attributes == CarbonHICommandAttributes.FromMenu; }
+		}
+		
+		public bool IsFromControl {
+			get { return attributes == CarbonHICommandAttributes.FromControl; }
+		}
+		
+		public bool IsFromWindow {
+			get { return attributes == CarbonHICommandAttributes.FromWindow; }
+		}
+	}
+	
+	[StructLayout(LayoutKind.Sequential, Pack = 2)]
+	struct HIMenuItem
+	{
+		IntPtr menuRef;
+		ushort index;
+		
+		public HIMenuItem (IntPtr menuRef, ushort index)
+		{
+			this.index = index;
+			this.menuRef = menuRef;
+		}
+		
+		public IntPtr MenuRef { get { return menuRef; } }
+		public ushort Index { get { return index; } }
+	}
+	
+	//*NOT* flags
+	enum CarbonHICommandAttributes : uint
+	{
+		FromMenu = 1,
+		FromControl = 1 << 1,
+		FromWindow  = 1 << 2,
+	}
+
+	[StructLayout(LayoutKind.Sequential, Pack = 2)]
+	struct FileTranslationSpec
+	{
+		uint componentSignature; // OSType
+		IntPtr translationSystemInfo; // void*
+		FileTypeSpec src;
+		FileTypeSpec dst;
+	}
+	
+	[StructLayout(LayoutKind.Sequential, Pack = 2)]
+	struct FileTypeSpec
+	{/*
+		uint format; // FileType
+		long hint;
+		TranslationAttributes flags;
+		uint catInfoType; // OSType
+		uint catInfoCreator; // OSType
+		*/
+	}
+}
diff --git a/src/Backends/Banshee.Osx/OsxIntegration.Framework/CoreFoundation.cs b/src/Backends/Banshee.Osx/OsxIntegration.Framework/CoreFoundation.cs
new file mode 100644
index 0000000..a53ddbd
--- /dev/null
+++ b/src/Backends/Banshee.Osx/OsxIntegration.Framework/CoreFoundation.cs
@@ -0,0 +1,95 @@
+// 
+// CoreFoundation.cs
+//  
+// Author:
+//       Michael Hutchinson <mhutchinson novell com>
+//       Miguel de Icaza
+// 
+// Copyright (c) 2009 Novell, Inc. (http://www.novell.com)
+// 
+// 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.Runtime.InteropServices;
+
+#pragma warning disable 0169
+
+namespace OsxIntegration.Framework
+{
+	internal static class CoreFoundation
+	{
+		const string CFLib = "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation";
+		
+		[DllImport (CFLib)]
+		static extern IntPtr CFStringCreateWithCString (IntPtr alloc, string str, int encoding);
+		
+		public static IntPtr CreateString (string s)
+		{
+			// The magic value is "kCFStringENcodingUTF8"
+			return CFStringCreateWithCString (IntPtr.Zero, s, 0x08000100);
+		}
+		
+		[DllImport (CFLib, EntryPoint="CFRelease")]
+		public static extern void Release (IntPtr cfRef);
+		
+				struct CFRange {
+			public int Location, Length;
+			public CFRange (int l, int len)
+			{
+				Location = l;
+				Length = len;
+			}
+		}
+		
+		[DllImport (CFLib, CharSet=CharSet.Unicode)]
+		extern static int CFStringGetLength (IntPtr handle);
+
+		[DllImport (CFLib, CharSet=CharSet.Unicode)]
+		extern static IntPtr CFStringGetCharactersPtr (IntPtr handle);
+		
+		[DllImport (CFLib, CharSet=CharSet.Unicode)]
+		extern static IntPtr CFStringGetCharacters (IntPtr handle, CFRange range, IntPtr buffer);
+		
+		public static string FetchString (IntPtr handle)
+		{
+			if (handle == IntPtr.Zero)
+				return null;
+			
+			string str;
+			
+			int l = CFStringGetLength (handle);
+			IntPtr u = CFStringGetCharactersPtr (handle);
+			IntPtr buffer = IntPtr.Zero;
+			if (u == IntPtr.Zero){
+				CFRange r = new CFRange (0, l);
+				buffer = Marshal.AllocCoTaskMem (l * 2);
+				CFStringGetCharacters (handle, r, buffer);
+				u = buffer;
+			}
+			unsafe {
+				str = new string ((char *) u, 0, l);
+			}
+			
+			if (buffer != IntPtr.Zero)
+				Marshal.FreeCoTaskMem (buffer);
+			
+			return str;
+		}
+	}
+}
diff --git a/src/Backends/Banshee.Osx/OsxIntegration.Framework/HIToolbox.cs b/src/Backends/Banshee.Osx/OsxIntegration.Framework/HIToolbox.cs
new file mode 100644
index 0000000..2a3d4e3
--- /dev/null
+++ b/src/Backends/Banshee.Osx/OsxIntegration.Framework/HIToolbox.cs
@@ -0,0 +1,713 @@
+// 
+// HIToolbox.cs
+//  
+// Author:
+//       Michael Hutchinson <mhutchinson novell com>
+//       Miguel de Icaza
+// 
+// Copyright (c) 2009 Novell, Inc. (http://www.novell.com)
+// 
+// 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.Runtime.InteropServices;
+
+#pragma warning disable 0169
+
+namespace OsxIntegration.Framework
+{
+	internal static class HIToolbox
+	{
+		const string hiToolboxLib = "/System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/HIToolbox";
+		
+		[DllImport (hiToolboxLib)]
+		static extern CarbonMenuStatus CreateNewMenu (ushort menuId, MenuAttributes attributes, out IntPtr menuRef);
+		
+		public static IntPtr CreateMenu (ushort id, string title, MenuAttributes attributes)
+		{
+			IntPtr menuRef;
+			CheckResult (CreateNewMenu (id, attributes, out menuRef));
+			SetMenuTitle (menuRef, title);
+			return menuRef;
+		}
+
+		[DllImport (hiToolboxLib)]
+		internal static extern CarbonMenuStatus SetRootMenu (IntPtr menuRef);
+
+		[DllImport (hiToolboxLib)]
+		internal static extern void DeleteMenu (IntPtr menuRef);
+
+		[DllImport (hiToolboxLib)]
+		internal static extern void ClearMenuBar ();
+		
+		[DllImport (hiToolboxLib)]
+		internal static extern ushort CountMenuItems (IntPtr menuRef);
+		
+		[DllImport (hiToolboxLib)]
+		internal static extern void DeleteMenuItem (IntPtr menuRef, ushort index);
+		
+		[DllImport (hiToolboxLib)]
+		internal static extern void InsertMenu (IntPtr menuRef, ushort before_id);
+		
+		[DllImport (hiToolboxLib)]
+		static extern CarbonMenuStatus AppendMenuItemTextWithCFString (IntPtr menuRef, IntPtr cfString, MenuItemAttributes attributes, uint commandId, out ushort index);
+		
+		public static ushort AppendMenuItem (IntPtr parentRef, string title, MenuItemAttributes attributes, uint commandId)
+		{
+			ushort index;
+			IntPtr str = CoreFoundation.CreateString (title);
+			CarbonMenuStatus result = AppendMenuItemTextWithCFString (parentRef, str, attributes, commandId, out index);
+			CoreFoundation.Release (str);
+			CheckResult (result);
+			return index;
+		}
+		
+		public static ushort AppendMenuSeparator (IntPtr parentRef)
+		{
+			ushort index;
+			CarbonMenuStatus result = AppendMenuItemTextWithCFString (parentRef, IntPtr.Zero, MenuItemAttributes.Separator, 0, out index);
+			CheckResult (result);
+			return index;
+		}
+		
+		[DllImport (hiToolboxLib)]
+		static extern CarbonMenuStatus InsertMenuItemTextWithCFString (IntPtr menuRef, IntPtr cfString, ushort afterItemIndex,
+		                                                         MenuItemAttributes attributes, uint commandID, out ushort index);
+		
+		public static ushort InsertMenuItem (IntPtr parentRef, string title, ushort afterItemIndex, MenuItemAttributes attributes, uint commandId)
+		{
+			ushort index;
+			IntPtr str = CoreFoundation.CreateString (title);
+			CarbonMenuStatus result = InsertMenuItemTextWithCFString (parentRef, str, afterItemIndex, attributes, commandId, out index);
+			CoreFoundation.Release (str);
+			CheckResult (result);
+			return index;
+		}
+		
+		public static ushort InsertMenuSeparator (IntPtr parentRef, ushort afterItemIndex)
+		{
+			ushort index;
+			CarbonMenuStatus result = InsertMenuItemTextWithCFString (parentRef, IntPtr.Zero, afterItemIndex, MenuItemAttributes.Separator, 0, out index);
+			CheckResult (result);
+			return index;
+		}
+
+		
+		[DllImport (hiToolboxLib)]
+		static extern CarbonMenuStatus EnableMenuItem (IntPtr menuRef, ushort index);
+		
+		public static void EnableMenuItem (HIMenuItem item)
+		{
+			CheckResult (EnableMenuItem (item.MenuRef, item.Index));
+		}
+		
+		[DllImport (hiToolboxLib)]
+		static extern CarbonMenuStatus DisableMenuItem (IntPtr menuRef, ushort index);
+		
+		public static void DisableMenuItem (HIMenuItem item)
+		{
+			CheckResult (DisableMenuItem (item.MenuRef, item.Index));
+		}
+		
+		[DllImport (hiToolboxLib)]
+		static extern CarbonMenuStatus ChangeMenuItemAttributes (IntPtr menu, ushort item, MenuItemAttributes setTheseAttributes, 
+		                                                         MenuItemAttributes clearTheseAttributes);
+		
+		public static void ChangeMenuItemAttributes (HIMenuItem item, MenuItemAttributes toSet, MenuItemAttributes toClear)
+		{
+			CheckResult (ChangeMenuItemAttributes (item.MenuRef, item.Index, toSet, toClear));
+		}
+		
+		[DllImport (hiToolboxLib)]
+		internal static extern CarbonMenuStatus SetMenuItemHierarchicalMenu (IntPtr parentMenu, ushort parent_index, IntPtr submenu);
+
+		[DllImport (hiToolboxLib)]
+		static extern CarbonMenuStatus SetMenuTitleWithCFString (IntPtr menuRef, IntPtr cfstring);
+		
+		public static void SetMenuTitle (IntPtr menuRef, string title)
+		{
+			IntPtr str = CoreFoundation.CreateString (title);
+			CarbonMenuStatus result = SetMenuTitleWithCFString (menuRef, str);
+			CoreFoundation.Release (str);
+			CheckResult (result);
+		}
+
+		[DllImport (hiToolboxLib)]
+		static extern CarbonMenuStatus SetMenuItemTextWithCFString (IntPtr menuRef, ushort index, IntPtr cfstring);
+		
+		public static void SetMenuItemText (IntPtr menuRef, ushort index, string title)
+		{
+			IntPtr str = CoreFoundation.CreateString (title);
+			CarbonMenuStatus result = SetMenuItemTextWithCFString (menuRef, index, str);
+			CoreFoundation.Release (str);
+			CheckResult (result);
+		}
+
+		[DllImport (hiToolboxLib)]
+		internal static extern CarbonMenuStatus SetMenuItemKeyGlyph (IntPtr menuRef, ushort index, short glyph);
+
+		[DllImport (hiToolboxLib)]
+		internal static extern CarbonMenuStatus SetMenuItemCommandKey (IntPtr menuRef, ushort index, bool isVirtualKey, ushort key);
+
+		[DllImport (hiToolboxLib)]
+		internal static extern CarbonMenuStatus SetMenuItemModifiers (IntPtr menuRef, ushort index, MenuAccelModifier modifiers);
+		
+		[DllImport (hiToolboxLib)]
+		static extern CarbonMenuStatus GetMenuItemCommandID (IntPtr menuRef, ushort index, out uint commandId);
+		
+		public static uint GetMenuItemCommandID (HIMenuItem item)
+		{
+			uint id;
+			CheckResult (GetMenuItemCommandID (item.MenuRef, item.Index, out id));
+			return id;
+		}
+		
+		[DllImport (hiToolboxLib)]
+		static extern CarbonMenuStatus GetIndMenuItemWithCommandID (IntPtr startAtMenuRef, uint commandID, uint commandItemIndex, 
+		                                                      out IntPtr itemMenuRef, out ushort itemIndex);
+		
+		public static HIMenuItem GetMenuItem (uint commandId)
+		{
+			IntPtr itemMenuRef;
+			ushort itemIndex;
+			CheckResult (GetIndMenuItemWithCommandID (IntPtr.Zero, commandId, 1, out itemMenuRef, out itemIndex));
+			return new HIMenuItem (itemMenuRef, itemIndex);
+		}
+		
+		[DllImport (hiToolboxLib)]
+		public static extern CarbonMenuStatus CancelMenuTracking (IntPtr rootMenu, bool inImmediate, MenuDismissalReason reason);
+		
+		[DllImport (hiToolboxLib)]
+		public static extern CarbonMenuStatus SetMenuItemData (IntPtr menu, uint indexOrCommandID, bool isCommandID, ref MenuItemData data);
+		
+		[DllImport (hiToolboxLib)]
+		static extern CarbonMenuStatus SetMenuItemRefCon (IntPtr menuRef, ushort index, uint inRefCon);
+		
+		public static void SetMenuItemReferenceConstant (HIMenuItem item, uint value)
+		{
+			CheckResult (SetMenuItemRefCon (item.MenuRef, item.Index, value));
+		}
+		
+		[DllImport (hiToolboxLib)]
+		static extern CarbonMenuStatus GetMenuItemRefCon (IntPtr menuRef, ushort index, out uint inRefCon);
+		
+		public static uint GetMenuItemReferenceConstant (HIMenuItem item)
+		{
+			uint val;
+			CheckResult (GetMenuItemRefCon (item.MenuRef, item.Index, out val));
+			return val;
+		}
+		
+		internal static void CheckResult (CarbonMenuStatus result)
+		{
+			if (result != CarbonMenuStatus.Ok)
+				throw new CarbonMenuException (result);
+		}
+	}
+	
+	class CarbonMenuException : Exception
+	{
+		public CarbonMenuException (CarbonMenuStatus result)
+		{
+			this.Result = result;
+		}
+		
+		public CarbonMenuStatus Result { get; private set; }
+		
+		public override string ToString ()
+		{
+			return string.Format("CarbonMenuException: Result={0}\n{1}", Result, StackTrace);
+		}
+	}
+	
+	internal enum CarbonMenuStatus // this is an OSStatus
+	{ 
+		Ok = 0,
+		PropertyInvalid = -5603,
+		PropertyNotFound = -5604,
+		NotFound  = -5620,
+		UsesSystemDef = -5621,
+		ItemNotFound = -5622,
+		Invalid = -5623
+	}
+
+	[Flags]
+	internal enum MenuAttributes {
+		ExcludesMarkColumn = 1,
+		AutoDisable = 1 << 2,
+		UsePencilGlyph = 1 << 3,
+		Hidden = 1 << 4,
+		CondenseSeparators = 1 << 5,
+		DoNotCacheImage = 1 << 6,
+		DoNotUseUserCommandKeys = 1 << 7
+	}
+
+	internal enum MenuAccelModifier : byte
+	{
+		CommandModifier = 0,
+		ShiftModifier = 1 << 0,
+		OptionModifier = 1 << 1,
+		ControlModifier = 1 << 2,
+		None = 1 << 3
+	}
+	
+	[Flags]
+	internal enum MenuItemAttributes : uint
+	{
+		Disabled = 1 << 0,
+		IconDisabled = 1 << 1,
+		SubmenuParentChoosable = 1 << 2,
+		Dynamic = 1 << 3,
+		NotPreviousAlternate = 1 << 4,
+		Hidden = 1 << 5,
+		Separator = 1 << 6,
+		SectionHeader = 1 << 7,
+		IgnoreMeta = 1 << 8,
+		AutoRepeat = 1 << 9,
+		UseVirtualKey = 1 << 10,
+		CustomDraw = 1 << 11,
+		IncludeInCmdKeyMatching = 1 << 12,
+		AutoDisable = 1 << 13,
+		UpdateSingleItem = 1 << 14
+	}
+	
+	internal enum MenuDismissalReason : uint
+	{
+		DismissedBySelection   = 1,
+		DismissedByUserCancel  = 2,
+		DismissedByMouseDown   = 3,
+		DismissedByMouseUp     = 4,
+		DismissedByKeyEvent    = 5,
+		DismissedByAppSwitch   = 6,
+		DismissedByTimeout     = 7,
+		DismissedByCancelMenuTracking = 8,
+		DismissedByActivationChange = 9,
+		DismissedByFocusChange = 10,
+	}
+	
+	
+	[StructLayout(LayoutKind.Sequential, Pack = 2)]
+	internal struct MenuItemData
+	{
+		MenuItemDataFlags whichData; //8
+		IntPtr text; //Str255 //12
+		[MarshalAs (UnmanagedType.U2)] //14
+		char mark;
+		[MarshalAs (UnmanagedType.U2)] //16
+		char cmdKey;
+		uint cmdKeyGlyph; //20
+		uint cmdKeyModifiers; //24
+		byte style; //25
+		[MarshalAs (UnmanagedType.U1)] //26
+		bool enabled;
+		[MarshalAs (UnmanagedType.U1)] //27
+		bool iconEnabled;
+		byte filler1; //28
+		int iconID; //32
+		uint iconType; //36
+		IntPtr iconHandle; //40
+		uint cmdID; //44
+		CarbonTextEncoding encoding; //48
+		ushort submenuID; //50
+		IntPtr submenuHandle; //54
+		int fontID; //58
+		uint refcon; //62
+		// LAMESPEC: this field is documented as OptionBits
+		MenuItemAttributes attr; //66
+		IntPtr cfText; //70
+		// Collection 
+		IntPtr properties; //74
+		uint indent; //78
+		ushort cmdVirtualKey; //80
+		
+		//these aren't documented
+		IntPtr attributedText; //84
+		IntPtr font; //88
+		
+		#region Properties
+		
+		public IntPtr Text {
+			get { return text; }
+			set {
+				whichData |= MenuItemDataFlags.Text;
+				text = value;
+			}
+		}
+		
+		public char Mark {
+			get { return mark; }
+			set {
+				whichData |= MenuItemDataFlags.Mark;
+				mark = value;
+			}
+		}
+		
+		public char CommandKey {
+			get { return cmdKey; }
+			set {
+				whichData |= MenuItemDataFlags.CmdKey;
+				cmdKey = value;
+			}
+		}
+		
+		public uint CommandKeyGlyph {
+			get { return cmdKeyGlyph; }
+			set {
+				whichData |= MenuItemDataFlags.CmdKeyGlyph;
+				cmdKeyGlyph = value;
+			}
+		}
+		
+		public MenuAccelModifier CommandKeyModifiers {
+			get { return (MenuAccelModifier) cmdKeyModifiers; }
+			set {
+				whichData |= MenuItemDataFlags.CmdKeyModifiers;
+				cmdKeyModifiers = (uint) value;
+			}
+		}
+		
+		public byte Style {
+			get { return style; }
+			set {
+				whichData |= MenuItemDataFlags.Style;
+				style = value;
+			}
+		}
+		
+		public bool Enabled {
+			get { return enabled; }
+			set {
+				whichData |= MenuItemDataFlags.Enabled;
+				enabled = value;
+			}
+		}
+		
+		public bool IconEnabled {
+			get { return iconEnabled; }
+			set {
+				whichData |= MenuItemDataFlags.IconEnabled;
+				iconEnabled = value;
+			}
+		}
+		
+		public int IconID {
+			get { return iconID; }
+			set {
+				whichData |= MenuItemDataFlags.IconID;
+				iconID = value;
+			}
+		}
+		
+		public HIIconHandle IconHandle {
+			get { return new HIIconHandle (iconHandle, iconType); }
+			set {
+				whichData |= MenuItemDataFlags.IconHandle;
+				iconHandle = value.Ref;
+				iconType = value.Type;
+			}
+		}
+		
+		public uint CommandID {
+			get { return cmdID; }
+			set {
+				whichData |= MenuItemDataFlags.CommandID;
+				cmdID = value;
+			}
+		}
+		
+		public CarbonTextEncoding Encoding {
+			get { return encoding; }
+			set {
+				whichData |= MenuItemDataFlags.TextEncoding;
+				encoding = value;
+			}
+		}
+		
+		public ushort SubmenuID {
+			get { return submenuID; }
+			set {
+				whichData |= MenuItemDataFlags.SubmenuID;
+				submenuID = value;
+			}
+		}
+		
+		public IntPtr SubmenuHandle {
+			get { return submenuHandle; }
+			set {
+				whichData |= MenuItemDataFlags.SubmenuHandle;
+				submenuHandle = value;
+			}
+		}
+		
+		public int FontID {
+			get { return fontID; }
+			set {
+				whichData |= MenuItemDataFlags.FontID;
+				fontID = value;
+			}
+		}
+		
+		public uint ReferenceConstant {
+			get { return refcon; }
+			set {
+				whichData |= MenuItemDataFlags.Refcon;
+				refcon = value;
+			}
+		}
+		
+		public MenuItemAttributes Attributes {
+			get { return attr; }
+			set {
+				whichData |= MenuItemDataFlags.Attributes;
+				attr = value;
+			}
+		}
+		
+		public IntPtr CFText {
+			get { return cfText; }
+			set {
+				whichData |= MenuItemDataFlags.CFString;
+				cfText = value;
+			}
+		}
+		
+		public IntPtr Properties {
+			get { return properties; }
+			set {
+				whichData |= MenuItemDataFlags.Properties;
+				properties = value;
+			}
+		}
+		
+		public uint Indent {
+			get { return indent; }
+			set {
+				whichData |= MenuItemDataFlags.Indent;
+				indent = value;
+			}
+		}
+		
+		public ushort CommandVirtualKey {
+			get { return cmdVirtualKey; }
+			set {
+				whichData |= MenuItemDataFlags.CmdVirtualKey;
+				cmdVirtualKey = value;
+			}
+		}
+		
+		#endregion
+		
+		#region 'Has' properties
+		
+		public bool HasText {
+			get { return (whichData & MenuItemDataFlags.Text) != 0; }
+		}
+		
+		public bool HasMark {
+			get { return (whichData & MenuItemDataFlags.Mark) != 0; }
+		}
+		
+		public bool HasCommandKey {
+			get { return (whichData & MenuItemDataFlags.CmdKey) != 0; }
+		}
+		
+		public bool HasCommandKeyGlyph {
+			get { return (whichData & MenuItemDataFlags.CmdKeyGlyph) != 0; }
+		}
+		
+		public bool HasCommandKeyModifiers {
+			get { return (whichData & MenuItemDataFlags.CmdKeyModifiers) != 0; }
+		}
+		
+		public bool HasStyle {
+			get { return (whichData & MenuItemDataFlags.Style) != 0; }
+		}
+		
+		public bool HasEnabled {
+			get { return (whichData & MenuItemDataFlags.Enabled) != 0; }
+		}
+		
+		public bool HasIconEnabled {
+			get { return (whichData & MenuItemDataFlags.IconEnabled) != 0; }
+		}
+		
+		public bool HasIconID {
+			get { return (whichData & MenuItemDataFlags.IconID) != 0; }
+		}
+		
+		public bool HasIconHandle {
+			get { return (whichData & MenuItemDataFlags.IconHandle) != 0; }
+		}
+		
+		public bool HasCommandID {
+			get { return (whichData & MenuItemDataFlags.CommandID) != 0; }
+		}
+		
+		public bool HasEncoding {
+			get { return (whichData & MenuItemDataFlags.TextEncoding) != 0; }
+		}
+		
+		public bool HasSubmenuID {
+			get { return (whichData & MenuItemDataFlags.SubmenuID) != 0; }
+		}
+		
+		public bool HasSubmenuHandle {
+			get { return (whichData & MenuItemDataFlags.SubmenuHandle) != 0; }
+		}
+		
+		public bool HasFontID {
+			get { return (whichData & MenuItemDataFlags.FontID) != 0; }
+		}
+		
+		public bool HasRefcon {
+			get { return (whichData & MenuItemDataFlags.Refcon) != 0; }
+		}
+		
+		public bool HasAttributes {
+			get { return (whichData & MenuItemDataFlags.Attributes) != 0; }
+		}
+		
+		public bool HasCFText {
+			get { return (whichData & MenuItemDataFlags.CFString) != 0; }
+		}
+		
+		public bool HasProperties {
+			get { return (whichData & MenuItemDataFlags.Properties) != 0; }
+		}
+		
+		public bool HasIndent {
+			get { return (whichData & MenuItemDataFlags.Indent) != 0; }
+		}
+		
+		public bool HasCommandVirtualKey {
+			get { return (whichData & MenuItemDataFlags.CmdVirtualKey) != 0; }
+		}
+		
+		#endregion
+	}
+	
+	struct HIIconHandle
+	{
+		IntPtr _ref;
+		uint type;
+		
+		public HIIconHandle (IntPtr @ref, uint type)
+		{
+			this._ref = @ref;
+			this.type = type;
+		}
+		
+		public IntPtr Ref { get { return _ref; } }
+		public uint Type { get { return type; } }
+	}
+	
+	enum CarbonTextEncoding : uint
+	{
+	}
+	
+	enum MenuItemDataFlags : ulong
+	{
+		Text = (1 << 0),
+		Mark = (1 << 1),
+		CmdKey = (1 << 2),
+		CmdKeyGlyph = (1 << 3),
+		CmdKeyModifiers = (1 << 4),
+		Style = (1 << 5),
+		Enabled = (1 << 6),
+		IconEnabled = (1 << 7),
+		IconID = (1 << 8),
+		IconHandle = (1 << 9),
+		CommandID = (1 << 10),
+		TextEncoding = (1 << 11),
+		SubmenuID = (1 << 12),
+		SubmenuHandle = (1 << 13),
+		FontID = (1 << 14),
+		Refcon = (1 << 15),
+		Attributes = (1 << 16),
+		CFString = (1 << 17),
+		Properties = (1 << 18),
+		Indent = (1 << 19),
+		CmdVirtualKey = (1 << 20),
+		AllDataVersionOne = 0x000FFFFF,
+		AllDataVersionTwo = AllDataVersionOne | CmdVirtualKey,
+	}
+	
+	enum MenuGlyphs : byte //char
+	{
+		None = 0x00,
+		TabRight = 0x02,
+		TabLeft = 0x03,
+		Enter = 0x04,
+		Shift = 0x05,
+		Control = 0x06,
+		Option = 0x07,
+		Space = 0x09,
+		DeleteRight = 0x0A,
+		Return = 0x0B,
+		ReturnR2L = 0x0C,
+		NonmarkingReturn = 0x0D,
+		Pencil = 0x0F,
+		DownwardArrowDashed = 0x10,
+		Command = 0x11,
+		Checkmark = 0x12,
+		Diamond = 0x13,
+		AppleLogoFilled = 0x14,
+		ParagraphKorean = 0x15,
+		DeleteLeft = 0x17,
+		LeftArrowDashed = 0x18,
+		UpArrowDashed = 0x19,
+		RightArrowDashed = 0x1A,
+		Escape = 0x1B,
+		Clear = 0x1C,
+		LeftDoubleQuotesJapanese = 0x1D,
+		RightDoubleQuotesJapanese = 0x1E,
+		TrademarkJapanese = 0x1F,
+		Blank = 0x61,
+		PageUp = 0x62,
+		CapsLock = 0x63,
+		LeftArrow = 0x64,
+		RightArrow = 0x65,
+		NorthwestArrow = 0x66,
+		Help = 0x67,
+		UpArrow = 0x68,
+		SoutheastArrow = 0x69,
+		DownArrow = 0x6A,
+		PageDown = 0x6B,
+		AppleLogoOutline = 0x6C,
+		ContextualMenu = 0x6D,
+		Power = 0x6E,
+		F1 = 0x6F,
+		F2 = 0x70,
+		F3 = 0x71,
+		F4 = 0x72,
+		F5 = 0x73,
+		F6 = 0x74,
+		F7 = 0x75,
+		F8 = 0x76,
+		F9 = 0x77,
+		F10 = 0x78,
+		F11 = 0x79,
+		F12 = 0x7A,
+		F13 = 0x87,
+		F14 = 0x88,
+		F15 = 0x89,
+		ControlISO = 0x8A,
+		Eject = 0x8C
+	};
+}
diff --git a/src/Backends/Banshee.Osx/OsxIntegration.Framework/NavDialog.cs b/src/Backends/Banshee.Osx/OsxIntegration.Framework/NavDialog.cs
new file mode 100644
index 0000000..0cc2499
--- /dev/null
+++ b/src/Backends/Banshee.Osx/OsxIntegration.Framework/NavDialog.cs
@@ -0,0 +1,513 @@
+// 
+// Carbon.cs
+//  
+// Author:
+//       Michael Hutchinson <mhutchinson novell com>
+// 
+// Copyright (c) 2010 Novell, Inc. (http://www.novell.com)
+// 
+// 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.Runtime.InteropServices;
+using System.Collections.Generic;
+
+#pragma warning disable 0169
+
+namespace OsxIntegration.Framework
+{
+	class NavDialog : IDisposable
+	{
+		IntPtr ptr;
+		
+		public static NavDialog CreateChooseFileDialog (NavDialogCreationOptions options)	
+		{
+			NavDialog dialog = new NavDialog ();
+			CheckReturn (NavCreateChooseFileDialog (ref options.data, IntPtr.Zero, new NavEventUPP (), new NavPreviewUPP (),
+			                                                    new NavObjectFilterUPP (), IntPtr.Zero, out dialog.ptr));
+			return dialog;
+		}
+		
+		public static NavDialog CreateChooseFolderDialog (NavDialogCreationOptions options)	
+		{
+			NavDialog dialog = new NavDialog ();
+			CheckReturn (NavCreateChooseFolderDialog (ref options.data, new NavEventUPP (),
+			                                                    new NavObjectFilterUPP (), IntPtr.Zero, out dialog.ptr));
+			return dialog;
+		}
+		
+		public static NavDialog CreatePutFileDialog (NavDialogCreationOptions options)	
+		{
+			NavDialog dialog = new NavDialog ();
+			CheckReturn (NavCreatePutFileDialog (ref options.data, new OSType (), new OSType (),
+			                                                 new NavEventUPP (), IntPtr.Zero, out dialog.ptr));
+			return dialog;
+		}
+		
+		public static NavDialog CreateNewFolderDialog (NavDialogCreationOptions options)	
+		{
+			NavDialog dialog = new NavDialog ();
+			CheckReturn (NavCreateNewFolderDialog (ref options.data, new NavEventUPP (),
+			                                                   IntPtr.Zero, out dialog.ptr));
+			return dialog;
+		}
+		
+		public NavUserAction Run ()
+		{
+			CheckDispose ();
+			CheckReturn (NavDialogRun (ptr));
+			return NavDialogGetUserAction (ptr);
+		}
+		
+		public NavReplyRecordRef GetReply ()
+		{
+			CheckDispose ();
+			var record = new NavReplyRecordRef ();
+			CheckReturn (NavDialogGetReply (ptr, out record.value));
+			return record;
+		}
+		
+		public void SetLocation (string location)
+		{
+			CheckDispose ();
+			throw new NotImplementedException ();
+		//	AEDesc desc = new AEDesc ();
+		//	CheckReturn (NavCustomControl (ptr, NavCustomControlMessage.SetLocation, ref desc)); 
+		}
+		
+		void CheckDispose ()
+		{
+			if (ptr == IntPtr.Zero)
+				throw new ObjectDisposedException ("NavDialog");
+		}
+		
+		public void Dispose ()
+		{
+			if (ptr != IntPtr.Zero) {
+				NavDialogDispose (ptr);
+				ptr = IntPtr.Zero;
+				GC.SuppressFinalize (this);
+			}
+		}
+		
+		~NavDialog ()
+		{
+			Console.WriteLine ("WARNING: NavDialog not disposed");
+		}
+		
+		[DllImport (Carbon.CarbonLib)]
+		static extern NavStatus NavCreateChooseFileDialog (ref NavDialogCreationOptionsData options, IntPtr inTypeList, 
+		                                                   NavEventUPP inEventProc, NavPreviewUPP inPreviewProc, 
+		                                                   NavObjectFilterUPP inFilterProc, IntPtr inClientData, out IntPtr navDialogRef);
+		//intTypeList is a NavTypeListHandle, which apparently is a pointer to  NavTypeListPtr, which is a pointer to a NavTypeList
+		
+		[DllImport (Carbon.CarbonLib)]
+		static extern NavStatus NavCreateChooseFolderDialog (ref NavDialogCreationOptionsData options, 
+		                                                     NavEventUPP inEventProc, NavObjectFilterUPP inFilterProc,
+		                                                     IntPtr inClientData, out IntPtr navDialogRef);
+		
+		[DllImport (Carbon.CarbonLib)]
+		static extern NavStatus NavCreatePutFileDialog (ref NavDialogCreationOptionsData options, OSType inFileType,
+		                                                OSType inFileCreator, NavEventUPP inEventProc,
+		                                                IntPtr inClientData, out IntPtr navDialogRef);
+
+		[DllImport (Carbon.CarbonLib)]
+		static extern NavStatus NavCreateNewFolderDialog (ref NavDialogCreationOptionsData options, 
+		                                                  NavEventUPP inEventProc, IntPtr inClientData, 
+		                                                  out IntPtr navDialogRef);
+		
+		[DllImport (Carbon.CarbonLib)]
+		public static extern NavStatus NavDialogRun (IntPtr navDialogRef);
+		
+		[DllImport (Carbon.CarbonLib)]
+		static extern NavStatus NavDialogGetReply (IntPtr navDialogRef, out NavReplyRecord outReply);
+		
+		[DllImport (Carbon.CarbonLib)]
+		static extern NavUserAction NavDialogGetUserAction (IntPtr navDialogRef);
+		
+		[DllImport (Carbon.CarbonLib)]
+		static extern void NavDialogDispose (IntPtr navDialogRef);
+		
+		[DllImport (Carbon.CarbonLib)]
+		static extern NavStatus NavCustomControl (IntPtr dialog, NavCustomControlMessage selector, IntPtr parms);
+		
+		[DllImport (Carbon.CarbonLib)]
+		static extern NavStatus NavCustomControl (IntPtr dialog, NavCustomControlMessage selector, ref AEDesc parm);
+		
+		public static void CheckReturn (NavStatus status)
+		{
+			CheckReturn (status);
+		}
+	}
+	
+	struct NavEventUPP { IntPtr ptr; }
+	struct NavObjectFilterUPP { IntPtr ptr; }
+	struct NavPreviewUPP { IntPtr ptr; }
+	struct OSType { int value; }
+	
+	class NavDialogCreationOptions : IDisposable
+	{
+		internal NavDialogCreationOptionsData data;
+		
+		public static NavDialogCreationOptions NewFromDefaults ()
+		{
+			var options = new NavDialogCreationOptions ();
+			NavDialog.CheckReturn (NavGetDefaultDialogCreationOptions (out options.data));
+			return options;
+		}
+		
+		[DllImport (Carbon.CarbonLib)]
+		static extern NavStatus NavGetDefaultDialogCreationOptions (out NavDialogCreationOptionsData options);
+		
+		public NavDialogOptionFlags OptionFlags {
+			get { return data.optionFlags; }
+			set { data.optionFlags = value; }
+		}
+		
+		public Point Location {
+			get { return data.location; }
+			set { data.location = value; }
+		}
+		
+		public string ClientName {
+			get { return CoreFoundation.FetchString (data.clientName); }
+			set { data.clientName = AddCFString (value); }
+		}
+		
+		public string WindowTitle {
+			get { return CoreFoundation.FetchString (data.windowTitle); }
+			set { data.windowTitle = AddCFString (value); }
+		}
+		
+		public string ActionButtonLabel {
+			get { return CoreFoundation.FetchString (data.actionButtonLabel); }
+			set { data.actionButtonLabel = AddCFString (value); }
+		}
+		
+		public string CancelButtonLabel {
+			get { return CoreFoundation.FetchString (data.cancelButtonLabel); }
+			set { data.cancelButtonLabel = AddCFString (value); }
+		}
+		
+		public string SaveFileName {
+			get { return CoreFoundation.FetchString (data.saveFileName); }
+			set { data.saveFileName = AddCFString (value); }
+		}
+		
+		public string Message {
+			get { return CoreFoundation.FetchString (data.message); }
+			set { data.message = AddCFString (value); }
+		}
+		
+		public uint PreferenceKey {
+			get { return data.preferenceKey; }
+			set { data.preferenceKey = value; }
+		}
+		
+		public IntPtr PopupExtension {
+			get { return data.popupExtension; }
+			set { data.popupExtension = value; }
+		}
+		
+		public WindowModality Modality {
+			get { return data.modality; }
+			set { data.modality = value; }
+		}
+		
+		public IntPtr ParentWindow {
+			get { return data.parentWindow; }
+			set { data.parentWindow = value; }
+		}
+		
+		List<IntPtr> toDispose;
+		IntPtr AddCFString (string value)
+		{
+			var ptr = CoreFoundation.CreateString (value);
+			if (toDispose == null)
+				toDispose = new List<IntPtr> ();
+			toDispose.Add (ptr);
+			return ptr;
+		}
+		
+		public void Dispose ()
+		{
+			if (toDispose != null) {
+				foreach (IntPtr ptr in toDispose)
+					CoreFoundation.Release (ptr);
+				toDispose = null;
+				GC.SuppressFinalize (this);
+			}
+		}
+		
+		~NavDialogCreationOptions ()
+		{
+			Console.WriteLine ("WARNING: Did not dispose NavDialogCreationOptions");
+		}
+	}
+	
+	[StructLayout(LayoutKind.Sequential, Pack = 2, Size = 66)]
+	struct NavDialogCreationOptionsData
+	{
+		public ushort version;
+		public NavDialogOptionFlags optionFlags;
+		public Point location;
+		public IntPtr clientName; //CFStringRef
+		public IntPtr windowTitle; //CFStringRef
+		public IntPtr actionButtonLabel; // CFStringRef
+		public IntPtr cancelButtonLabel; // CFStringRef
+		public IntPtr saveFileName; // CFStringRef
+		public IntPtr message; // CFStringRef
+		public uint preferenceKey;
+		public IntPtr popupExtension; //CFArrayRef
+		public WindowModality modality;
+		public IntPtr parentWindow; //WindowRef
+		public char reserved; //char[16]
+	}
+	
+	[Flags]
+	enum NavDialogOptionFlags : uint
+	{
+		Default = DontAddTranslateItems & AllowStationery & AllowPreviews & AllowMultipleFiles,
+		NoTypePopup = 1,
+		DontAutoTranslate = 1 << 1,
+		DontAddTranslateItems = 1 << 2,
+		AllFilesInPopup = 1 << 4,
+		AllowStationery = 1 << 5,
+		AllowPreviews = 1 << 6,
+		AllowMultipleFiles = 1 << 7,
+		AllowInvisibleFiles = 1 << 8,
+		DontResolveAliases = 1 << 9,
+ 		SelectDefaultLocation = 1 << 10,
+		SelectAllReadableItem = 1 << 11,
+		SupportPackages = 1 << 12,
+		AllowOpenPackages = 1 << 13,
+		DontAddRecents = 1 << 14,
+		DontUseCustomFrame = 1 << 15,
+		DontConfirmReplacement = 1 << 16,
+		PreserveSaveFileExtension = 1 << 17
+	}
+	
+	[StructLayout(LayoutKind.Sequential, Pack = 2)]
+	struct Point
+	{
+		short v;
+		short h;
+		
+		public Point (short v, short h)
+		{
+			this.v = v;
+			this.h = h;
+		}
+		
+		public short V { get { return v; } }
+		public short H { get { return h; } }
+	}
+	
+	[StructLayout(LayoutKind.Sequential, Pack = 2)]
+	struct Rect
+	{
+		short top;
+		short left;
+		short bottom;
+		short right;
+		
+		public short Top { get { return top; } }
+		public short Left { get { return left; } }
+		public short Bottom { get { return bottom; } }
+		public short Right { get { return right; } }
+	}
+	
+	enum WindowModality : uint
+	{
+		None = 0,
+		SystemModal = 1,
+		AppModal = 2,
+		WindowModal = 3,
+	}
+	
+	enum WindowPositionMethod : uint
+	{
+		CenterOnMainScreen = 1,
+		CenterOnParentWindow = 2,
+		CenterOnParentWindowScreen = 3,
+		CascadeOnMainScreen = 4,
+		CascadeOnParentWindow = 5,
+		CascadeOnParentWindowScreen = 6,
+		CascadeStartAtParentWindowScreen = 10,
+		AlertPositionOnMainScreen = 7,
+		AlertPositionOnParentWindow = 8,
+		AlertPositionOnParentWindowScreen = 9,
+	}
+	
+	enum NavStatus : int
+	{
+		Ok = 0,
+		WrongDialogStateErr = -5694,
+		WrongDialogClassErr = -5695,
+		InvalidSystemConfigErr = -5696,
+		CustomControlMessageFailedErr = -5697,
+		InvalidCustomControlMessageErr = -5698,
+		MissingKindStringErr = -5699,
+	}
+	
+	enum NavEventCallbackMessage : int
+	{
+		Event = 0,
+		Customize = 1,
+		Start = 2,
+		Terminate = 3,
+		AdjustRect = 4,
+		NewLocation = 5,
+		ShowDesktop = 6,
+		SelectEntry = 7,
+		PopupMenuSelect = 8,
+		Accept = 9,
+		Cancel = 10,
+		AdjustPreview = 11,
+		UserAction = 12,
+		OpenSelection = -2147483648, // unchecked 0x80000000
+	}
+	
+	[StructLayout(LayoutKind.Sequential, Pack = 2, Size=254)]
+	struct NavCBRec
+	{
+		ushort version;
+		IntPtr context; // NavDialogRef
+		IntPtr window; // WindowRef
+		Rect customRect;
+		Rect previewRect;
+		NavEventData eventData;
+		NavUserAction userAction;
+		char reserved; //[218];
+	}
+	
+	[StructLayout(LayoutKind.Sequential, Pack = 2)]
+	struct NavEventData
+	{
+		IntPtr eventDataParms; // NavEventDataInfo union, usually a pointer to either a EventRecord or an AEDescList
+		short itemHit;
+	}
+	
+	enum NavUserAction : uint
+	{
+		None = 0,
+		Cancel = 1,
+		Open = 2,
+		SaveAs = 3,
+		Choose = 4,
+		NewFolder = 5,
+		SaveChanges = 6,
+		DontSaveChanges = 7,
+		DiscardChanges = 8,
+		ReviewDocuments = 9,
+		DiscardDocuments = 10
+	}
+	
+	enum NavFilterModes : short
+	{
+		BrowserList = 0,
+		Favorites = 1,
+		Recents = 2,
+		ShortCutVolumes = 3,
+		LocationPopup = 4
+	}
+	
+	[StructLayout(LayoutKind.Sequential, Pack = 2, Size=255)]
+	struct NavReplyRecord
+	{
+		ushort version;
+		[MarshalAs(UnmanagedType.U1)]
+		bool validRecord;
+		[MarshalAs(UnmanagedType.U1)]
+		bool replacing;
+		[MarshalAs(UnmanagedType.U1)]
+		bool isStationery;
+		[MarshalAs(UnmanagedType.U1)]
+		bool translationNeeded;
+		AEDesc selection; //actually an AEDescList
+		short keyScript;
+		//fileTranslation is a FileTranslationSpecArrayHandle, which apparently is a pointer to a FileTranslationSpecArrayPtr,
+		//which is a pointer to a FileTranslationSpec
+		IntPtr fileTranslation;
+		uint reserved1;
+		IntPtr saveFileName; //CFStringRef
+		[MarshalAs(UnmanagedType.U1)]
+		bool saveFileExtensionHidden;
+		byte reserved2;
+		char reserved; //size [225];
+	}
+	
+	class NavReplyRecordRef : IDisposable
+	{
+		bool disposed;
+		internal NavReplyRecord value;
+		
+		public void Dispose ()
+		{
+			if (!disposed) {
+				disposed = true;
+				NavDisposeReply (ref value);
+				GC.SuppressFinalize (this);
+			}
+		}
+		
+		~NavReplyRecordRef ()
+		{
+			Console.WriteLine ("WARNING: NavReplyRecordRef not disposed");
+		}
+		
+		[DllImport (Carbon.CarbonLib)]
+		static extern NavStatus NavDisposeReply (ref NavReplyRecord record);
+	}
+	
+	enum NavCustomControlMessage : int
+	{
+		ShowDesktop = 0,
+		SortBy = 1,
+		SortOrder = 2,
+		ScrollHome = 3,
+		ScrollEnd = 4,
+		PageUp = 5,
+		PageDown = 6,
+		GetLocation = 7,
+		SetLocation = 8,
+		GetSelection = 9,
+		SetSelection = 10,
+		ShowSelection = 11,
+		OpenSelection = 12,
+		EjectVolume = 13,
+		NewFolder = 14,
+		Cancel = 15,
+		Accept = 16,
+		IsPreviewShowing = 17,
+		AddControl = 18,
+		AddControlList = 19,
+		GetFirstControlID = 20,
+		SelectCustomType = 21,
+		SelectAllType = 22,
+		GetEditFileName = 23,
+		SetEditFileName = 24,
+		SelectEditFileName = 25,
+		BrowserSelectAll = 26,
+		GotoParent = 27,
+		SetActionState = 28,
+		BrowserRedraw = 29,
+		Terminate = 30
+	}
+}
diff --git a/src/Backends/Banshee.Osx/OsxIntegration.Ige/IgeMacMenu.cs b/src/Backends/Banshee.Osx/OsxIntegration.Ige/IgeMacMenu.cs
new file mode 100644
index 0000000..f34d4fc
--- /dev/null
+++ b/src/Backends/Banshee.Osx/OsxIntegration.Ige/IgeMacMenu.cs
@@ -0,0 +1,74 @@
+//
+// IgeMacMenu.cs
+// 
+// Author:
+//   Aaron Bockover <abockover novell com>
+// 
+// Copyright 2010 Novell, Inc.
+// 
+// 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.Runtime.InteropServices;
+
+namespace OsxIntegration.Ige
+{
+    public static class IgeMacMenu
+    {
+        [DllImport ("libigemacintegration.dylib")]
+        private static extern void ige_mac_menu_connect_window_key_handler (IntPtr window);
+
+        public static void ConnectWindowKeyHandler (Gtk.Window window)
+        {
+            ige_mac_menu_connect_window_key_handler (window.Handle);
+        }
+
+        [DllImport ("libigemacintegration.dylib")]
+        private static extern void ige_mac_menu_set_global_key_handler_enabled (bool enabled);
+
+        public static bool GlobalKeyHandlerEnabled {
+            set { ige_mac_menu_set_global_key_handler_enabled (value); }
+        }
+
+        [DllImport ("libigemacintegration.dylib")]
+        static extern void ige_mac_menu_set_menu_bar (IntPtr menu_shell);
+
+        public static Gtk.MenuShell MenuBar {
+            set { ige_mac_menu_set_menu_bar (value == null ? IntPtr.Zero : value.Handle); }
+        }
+
+        [DllImport ("libigemacintegration.dylib")]
+        private static extern void ige_mac_menu_set_quit_menu_item (IntPtr quit_item);
+
+        public static Gtk.MenuItem QuitMenuItem {
+            set { ige_mac_menu_set_quit_menu_item (value == null ? IntPtr.Zero : value.Handle); }
+        }
+
+        [DllImport ("libigemacintegration.dylib")]
+        private static extern IntPtr ige_mac_menu_add_app_menu_group ();
+
+        public static IgeMacMenuGroup AddAppMenuGroup ()
+        {
+            var native = ige_mac_menu_add_app_menu_group ();
+            return native == IntPtr.Zero
+                ? null
+                : (IgeMacMenuGroup)GLib.Opaque.GetOpaque (native, typeof (IgeMacMenuGroup), false);
+        }
+    }
+}
diff --git a/src/Backends/Banshee.Osx/OsxIntegration.Ige/IgeMacMenuGroup.cs b/src/Backends/Banshee.Osx/OsxIntegration.Ige/IgeMacMenuGroup.cs
new file mode 100644
index 0000000..57ed82a
--- /dev/null
+++ b/src/Backends/Banshee.Osx/OsxIntegration.Ige/IgeMacMenuGroup.cs
@@ -0,0 +1,54 @@
+// 
+// IgeMacMenuGroup.cs
+// 
+// Author:
+//   Aaron Bockover <abockover novell com>
+// 
+// Copyright 2010 Novell, Inc.
+// 
+// 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.Runtime.InteropServices;
+
+namespace OsxIntegration.Ige
+{
+    public class IgeMacMenuGroup : GLib.Opaque
+    {
+        public IgeMacMenuGroup (IntPtr raw) : base (raw)
+        {
+        }
+
+        [DllImport ("libigemacintegration.dylib")]
+        private static extern void ige_mac_menu_add_app_menu_item (IntPtr raw,
+            IntPtr menu_item, IntPtr label);
+
+        public void AddMenuItem (Gtk.MenuItem menu_item, string label)
+        {
+            var native_label = GLib.Marshaller.StringToPtrGStrdup (label);
+            try {
+                ige_mac_menu_add_app_menu_item (Handle,
+                    menu_item == null ? IntPtr.Zero : menu_item.Handle,
+                    native_label);
+            } finally {
+                GLib.Marshaller.Free (native_label);
+            }
+        }
+    }
+}



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