Index: libs/libmyth/AppleRemote.h
===================================================================
--- libs/libmyth/AppleRemote.h	(revision 0)
+++ libs/libmyth/AppleRemote.h	(revision 0)
@@ -0,0 +1,79 @@
+#ifndef APPLEREMOTE
+#define APPLEREMOTE
+
+#include <string>
+#include <vector>
+#include <map>
+
+#include <IOKit/IOKitLib.h>
+#include <IOKit/IOCFPlugIn.h>
+#include <IOKit/hid/IOHIDLib.h>
+#include <IOKit/hid/IOHIDKeys.h>
+#include <CoreFoundation/CoreFoundation.h>
+
+class AppleRemote {
+public:
+  enum Event {
+    VolumePlus = 0,
+    VolumeMinus,
+    Menu,
+    Play,
+    Right,
+    Left,
+    RightHold,
+    LeftHold,
+    MenuHold,
+    PlaySleep,
+    ControlSwitched
+  };
+
+  class Listener {
+  public:
+    virtual ~Listener();
+    virtual void appleRemoteButton(Event button, bool pressedDown) = 0;
+  };
+
+  static AppleRemote& instance();
+  ~AppleRemote();
+
+  bool isRemoteAvailable();
+  bool isListeningToRemote();
+
+  void setListener(Listener* listener);
+  Listener* listener() { return _listener; }
+  void setOpenInExclusiveMode(bool in) { openInExclusiveMode = in; };
+  bool isOpenInExclusiveMode() { return openInExclusiveMode; };
+  void startListening();
+  void stopListening();
+  void runLoop();
+
+protected:
+  AppleRemote(); // will be a singleton class
+
+  static AppleRemote* _instance;
+  static const char* const AppleRemoteDeviceName;
+  static const int REMOTE_SWITCH_COOKIE;
+
+
+private:
+  bool openInExclusiveMode;
+  IOHIDDeviceInterface** hidDeviceInterface;
+  IOHIDQueueInterface** queue;
+  std::vector<int> cookies;
+  std::map< std::string, Event > cookieToButtonMapping;
+  int remoteId;
+  Listener* _listener;
+
+  void _initCookieMap();
+  io_object_t _findAppleRemoteDevice();
+  bool _initCookies();
+  bool _createDeviceInterface(io_object_t hidDevice);
+  bool _openDevice();
+
+  static void QueueCallbackFunction(void* target, IOReturn result, 
+                                    void* refcon, void* sender);
+  void _queueCallbackFunction(IOReturn result, void* refcon, void* sender);
+  void _handleEventWithCookieString(std::string cookieString, SInt32 sumOfValues);
+};
+
+#endif // APPLEREMOTE
Index: libs/libmyth/AppleRemoteListener.cpp
===================================================================
--- libs/libmyth/AppleRemoteListener.cpp	(revision 0)
+++ libs/libmyth/AppleRemoteListener.cpp	(revision 0)
@@ -0,0 +1,77 @@
+#include <qapplication.h>
+#include <qkeysequence.h>
+#include "lircevent.h"
+
+#include "AppleRemoteListener.h"
+
+AppleRemoteListener::AppleRemoteListener(QObject* mainWindow_): mainWindow(mainWindow_) {
+}
+
+void
+AppleRemoteListener::appleRemoteButton(AppleRemote::Event button, bool pressedDown) {
+  char* code = 0;
+  bool separateRelease = false;
+  switch (button) {
+    case AppleRemote::VolumePlus: {
+        code="Up";
+        separateRelease=true;
+        break;
+    }
+    case AppleRemote::VolumeMinus: {
+        code="Down";
+        separateRelease=true;
+        break;
+    }
+    case AppleRemote::Menu: {
+    	code="Esc";
+        break;
+    }
+    case AppleRemote::Play: {
+    	code="Enter";
+        break;
+    }
+    case AppleRemote::Right: {
+    	code="Right";
+        break;
+    }
+    case AppleRemote::Left: {
+    	code="Left";
+        break;
+    }
+    case AppleRemote::RightHold: {
+    	code="End";
+        separateRelease=true;
+        break;
+    }
+    case AppleRemote::LeftHold: {
+    	code="Home";
+        separateRelease=true;
+        break;
+    }
+    case AppleRemote::MenuHold: {
+    	code="M";
+        break;
+    }
+    case AppleRemote::PlaySleep: {
+    	code="P";
+        break;
+    }
+    case AppleRemote::ControlSwitched: {
+    	return;
+    }
+  }
+  QKeySequence a(code);
+  int keycode = 0;
+  for (unsigned int i = 0; i < a.count(); i++)
+           {
+                keycode = a[i];
+
+                QApplication::postEvent(mainWindow, new LircKeycodeEvent(code, 
+                                        keycode, pressedDown));
+                if (!separateRelease) {
+                	QApplication::postEvent(mainWindow, new LircKeycodeEvent(code, 
+                                        keycode, false));
+                }
+            }
+  
+}
Index: libs/libmyth/AppleRemote.cpp
===================================================================
--- libs/libmyth/AppleRemote.cpp	(revision 0)
+++ libs/libmyth/AppleRemote.cpp	(revision 0)
@@ -0,0 +1,297 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <sys/errno.h>
+#include <sysexits.h>
+#include <mach/mach.h>
+#include <mach/mach_error.h>
+#include <IOKit/IOKitLib.h>
+#include <IOKit/IOCFPlugIn.h>
+#include <IOKit/hid/IOHIDLib.h>
+#include <IOKit/hid/IOHIDKeys.h>
+#include <CoreFoundation/CoreFoundation.h>
+
+
+#include <map>
+#include <sstream>
+#include <iostream>
+
+#include "AppleRemote.h"
+
+// static 
+AppleRemote* AppleRemote::_instance = 0;
+// static 
+const char* const AppleRemote::AppleRemoteDeviceName = "AppleIRController";
+// static 
+const int AppleRemote::REMOTE_SWITCH_COOKIE=19;
+
+AppleRemote::Listener::~Listener() {
+}
+
+// public
+AppleRemote&
+AppleRemote::instance() {
+  if (_instance==0) {
+    _instance = new AppleRemote();
+  }
+  return *_instance;
+}
+
+AppleRemote::~AppleRemote() {
+  stopListening();
+}
+
+bool 
+AppleRemote::isRemoteAvailable() {
+  io_object_t hidDevice = _findAppleRemoteDevice();
+  if (hidDevice != 0) {
+    IOObjectRelease(hidDevice);
+    return true;
+  }
+  return false;
+}
+
+bool 
+AppleRemote::isListeningToRemote() {
+  return (hidDeviceInterface != NULL && !cookies.empty() && queue != NULL);
+}
+
+void 
+AppleRemote::setListener(AppleRemote::Listener* listener) {
+  _listener = listener;
+}
+
+void
+AppleRemote::startListening() {
+  if (queue != NULL) {
+  	// already listening
+  	return;
+  }
+  io_object_t hidDevice = _findAppleRemoteDevice();
+  if (hidDevice == 0) goto error;
+  if (!_createDeviceInterface(hidDevice)) goto error;
+  if (!_initCookies()) goto error;
+  if (!_openDevice()) goto error;
+  goto cleanup;
+
+error:
+  stopListening();
+
+cleanup:
+  IOObjectRelease(hidDevice);
+}
+
+void 
+AppleRemote::stopListening() {
+  if (queue != NULL) {
+    (*queue)->stop(queue);
+    (*queue)->dispose(queue);
+    (*queue)->Release(queue);
+    queue = NULL;
+  }
+
+  if (!cookies.empty()) {
+    cookies.clear();
+  }
+
+  if (hidDeviceInterface != NULL) {
+    (*hidDeviceInterface)->close(hidDeviceInterface);
+    (*hidDeviceInterface)->Release(hidDeviceInterface);
+    hidDeviceInterface = NULL;
+  }
+}
+
+void 
+AppleRemote::runLoop() {
+  CFRunLoopRun();
+}
+
+// protected
+AppleRemote::AppleRemote():
+    openInExclusiveMode(true),
+    hidDeviceInterface(0),
+    queue(0),
+    _listener(0) {
+  _initCookieMap();
+}
+
+// private
+void
+AppleRemote::_initCookieMap() {
+  cookieToButtonMapping["14_12_11_6_5_"] = VolumePlus;
+  cookieToButtonMapping["14_13_11_6_5_"] = VolumeMinus;
+  cookieToButtonMapping["14_7_6_5_14_7_6_5_"] = Menu;
+  cookieToButtonMapping["14_8_6_5_14_8_6_5_"] = Play;
+  cookieToButtonMapping["14_9_6_5_14_9_6_5_"] = Right;
+  cookieToButtonMapping["14_10_6_5_14_10_6_5_"] = Left;
+  cookieToButtonMapping["14_6_5_4_2_"] = RightHold;
+  cookieToButtonMapping["14_6_5_3_2_"] = LeftHold;
+  cookieToButtonMapping["14_6_5_14_6_5_"] = MenuHold;
+  cookieToButtonMapping["18_14_6_5_18_14_6_5_"] = PlaySleep;
+  cookieToButtonMapping["19_"] = ControlSwitched;
+}
+
+// private
+io_object_t
+AppleRemote::_findAppleRemoteDevice() {
+  CFMutableDictionaryRef hidMatchDictionary = 0;
+  io_iterator_t hidObjectIterator = 0;
+  io_object_t hidDevice = 0;
+
+  hidMatchDictionary = IOServiceMatching(AppleRemoteDeviceName);
+
+  // check for matching devices
+  IOReturn ioReturnValue = IOServiceGetMatchingServices(kIOMasterPortDefault, 
+                                               hidMatchDictionary, 
+                                               &hidObjectIterator);
+  if ((ioReturnValue == kIOReturnSuccess) 
+                       && (hidObjectIterator != 0)) {
+    hidDevice = IOIteratorNext(hidObjectIterator);
+  }
+
+  // IOServiceGetMatchingServices consumes a reference to the dictionary, so we
+  // don't need to release the dictionary ref.
+  hidMatchDictionary = 0;
+  return hidDevice;
+}
+
+// private
+bool
+AppleRemote::_initCookies() {
+  IOHIDDeviceInterface122** handle = (IOHIDDeviceInterface122**)hidDeviceInterface;
+
+  CFArrayRef elements;
+  IOReturn success =
+  (*handle)->copyMatchingElements(handle,NULL,(CFArrayRef*)&elements);
+
+  if (success == kIOReturnSuccess) {
+    for (CFIndex i = 0; i < CFArrayGetCount(elements); i++) {
+      CFDictionaryRef element = (CFDictionaryRef)CFArrayGetValueAtIndex(elements, i);
+
+      CFTypeRef object = CFDictionaryGetValue(element,
+                                            CFSTR(kIOHIDElementCookieKey));
+      if (object == 0 || CFGetTypeID(object) != CFNumberGetTypeID()) continue;
+      long number;
+      if (!CFNumberGetValue((CFNumberRef)object, kCFNumberLongType, &number)) {
+        continue;
+      }
+      IOHIDElementCookie cookie = (IOHIDElementCookie)number;
+
+      cookies.push_back((int)cookie);
+    }
+    return true;
+  }
+  return false;
+}
+
+// private
+bool
+AppleRemote::_createDeviceInterface(io_object_t hidDevice) {
+  SInt32 score = 0;
+  IOCFPlugInInterface** plugInInterface = NULL;
+
+  IOReturn ioReturnValue = IOCreatePlugInInterfaceForService(hidDevice,
+                                                    kIOHIDDeviceUserClientTypeID,
+                                                    kIOCFPlugInInterfaceID,
+                                                    &plugInInterface,
+                                                    &score);
+  if (ioReturnValue == kIOReturnSuccess) {
+    HRESULT plugInResult = (*plugInInterface)->QueryInterface(plugInInterface,
+                                CFUUIDGetUUIDBytes(kIOHIDDeviceInterfaceID),
+                                (LPVOID*) (&hidDeviceInterface));
+    if (plugInResult != S_OK) {
+      std::cerr << "AppleRemote Error: couldn't create device interface " << std::endl;
+    }
+    // Release
+    if (plugInInterface) (*plugInInterface)->Release(plugInInterface);
+  }
+  return hidDeviceInterface != 0;
+}
+
+// private
+bool
+AppleRemote::_openDevice() {
+  IOHIDOptionsType openMode = kIOHIDOptionsTypeNone;
+  if (openInExclusiveMode) openMode = kIOHIDOptionsTypeSeizeDevice;
+  IOReturn ioReturnValue = (*hidDeviceInterface)->open(hidDeviceInterface, openMode);
+
+  if (ioReturnValue != KERN_SUCCESS) {
+    std::cerr << "AppleRemote Error: when opening device" << std::endl;
+    return false;
+  }
+  queue = (*hidDeviceInterface)->allocQueue(hidDeviceInterface);
+  if (!queue) {
+    std::cerr << "AppleRemote Error allocating queue" << std::endl;
+    return false;
+  }
+
+  HRESULT result = (*queue)->create(queue, 0, 12);
+  if (result != S_OK || !queue) {
+  	std::cerr << "AppleRemote Error creating queue" << std::endl;
+  }
+
+  for (std::vector<int>::iterator iter = cookies.begin(); 
+       iter != cookies.end();
+       iter++) {
+    IOHIDElementCookie cookie = (IOHIDElementCookie)(*iter);
+    (*queue)->addElement(queue, cookie, 0);
+  }
+
+  CFRunLoopSourceRef eventSource;
+  ioReturnValue = (*queue)->createAsyncEventSource(queue, &eventSource);
+  if (ioReturnValue != KERN_SUCCESS) {
+    std::cerr << "AppleRemote Error creating async event source" << std::endl;
+    return false;
+  }
+
+  ioReturnValue = (*queue)->setEventCallout(queue,QueueCallbackFunction, this, NULL);
+  if (ioReturnValue != KERN_SUCCESS) {
+    std::cerr << "AppleRemote Error registering callback" << std::endl;
+    return false;
+  }
+  CFRunLoopAddSource(CFRunLoopGetCurrent(), eventSource, kCFRunLoopDefaultMode);
+  (*queue)->start(queue);
+  return true;
+}
+
+// static 
+void 
+AppleRemote::QueueCallbackFunction(void* target, IOReturn result, 
+                                    void* refcon, void* sender) {
+  AppleRemote* remote = (AppleRemote*)target;
+  remote->_queueCallbackFunction(result,refcon,sender);
+}
+
+void 
+AppleRemote::_queueCallbackFunction(IOReturn result, void* /*refcon*/, void* /*sender*/) {
+  AbsoluteTime zeroTime = {0,0};
+  SInt32 sumOfValues = 0;
+  std::stringstream cookieString;
+
+  while (result == kIOReturnSuccess) {
+    IOHIDEventStruct event;
+    result = (*queue)->getNextEvent(queue, &event, zeroTime, 0);
+    if (result != kIOReturnSuccess) break;
+
+    if (REMOTE_SWITCH_COOKIE == (int)event.elementCookie) {
+      remoteId=event.value;
+      _handleEventWithCookieString("19_",0);
+    } else {
+      sumOfValues+=event.value;
+      cookieString << std::dec << (int)event.elementCookie << "_";
+    }
+  }
+
+  _handleEventWithCookieString(cookieString.str(), sumOfValues);
+}
+
+void 
+AppleRemote::_handleEventWithCookieString(std::string cookieString, 
+                                          SInt32 sumOfValues) {
+  std::map<std::string,AppleRemote::Event>::iterator ii = cookieToButtonMapping.find(cookieString);
+  if (ii  != cookieToButtonMapping.end() && _listener) {
+    AppleRemote::Event buttonid = ii->second;
+    if (_listener) _listener->appleRemoteButton(buttonid, sumOfValues>0);
+  }
+}
Index: libs/libmyth/mythdialogs.cpp
===================================================================
--- libs/libmyth/mythdialogs.cpp	(revision 10355)
+++ libs/libmyth/mythdialogs.cpp	(working copy)
@@ -23,6 +23,11 @@
 using namespace std;
 
 #include <pthread.h>
+#ifdef Q_WS_MACX
+#include "lircevent.h"
+#include "AppleRemote.h"
+#include "AppleRemoteListener.h"
+#endif
 #ifdef USE_LIRC
 #include "lirc.h"
 #include "lircevent.h"
@@ -56,6 +61,22 @@
 }
 #endif
 
+#ifdef Q_WS_MACX
+static void* SpawnAppleRemote(void* param)
+{
+	MythMainWindow *main_window = (MythMainWindow *)param;
+	AppleRemoteListener *arl = new AppleRemoteListener(main_window);
+	AppleRemote& remote(AppleRemote::instance());
+	remote.setListener(arl);
+	remote.startListening();
+	if (!remote.isListeningToRemote()) {
+		return NULL;
+	}
+	remote.runLoop();
+	return NULL;
+}
+#endif
+
 #ifdef USE_JOYSTICK_MENU
 static void *SpawnJoystickMenu(void *param)
 {
@@ -194,6 +215,15 @@
     pthread_create(&lirc_tid, &attr, SpawnLirc, this);
 #endif
 
+#ifdef Q_WS_MACX
+    pthread_t appleremote_tid;
+    pthread_attr_t arattr;
+    pthread_attr_init(&arattr);
+    pthread_attr_setdetachstate(&arattr, PTHREAD_CREATE_DETACHED);
+
+    pthread_create(&appleremote_tid, &arattr, SpawnAppleRemote, this);
+#endif
+
 #ifdef USE_JOYSTICK_MENU
     d->ignore_joystick_keys = false;
     pthread_t js_tid;
@@ -247,6 +277,21 @@
     qApp->quit();
 }
 
+#ifdef Q_WS_MACX
+bool MythMainWindow::event(QEvent* e) {
+	switch (e->type()) {
+		case QEvent::WindowActivate: {
+			AppleRemote::instance().startListening();
+		}break;
+		case QEvent::WindowDeactivate: {
+			// relinquish the remote
+			AppleRemote::instance().stopListening();
+		}break;
+	}
+	return	QWidget::event(e);
+}
+#endif
+
 void MythMainWindow::Init(void)
 {
     gContext->GetScreenSettings(d->xbase, d->screenwidth, d->wmult,
@@ -810,8 +855,12 @@
             }
         }
     }
+#if defined(USE_LIRC) || defined(Q_WS_MACX)
+    else if (ce->type() == kLircKeycodeEventType
 #ifdef USE_LIRC
-    else if (ce->type() == kLircKeycodeEventType && !d->ignore_lirc_keys) 
+    && !d->ignore_lirc_keys
+#endif
+        )
     {
         LircKeycodeEvent *lke = (LircKeycodeEvent *)ce;
         int keycode = lke->getKeycode();
@@ -851,6 +900,8 @@
                                            " your key mappings.\n";
         }
     }
+#endif
+#ifdef USE_LIRC
     else if (ce->type() == kLircMuteEventType)
     {
         LircMuteEvent *lme = (LircMuteEvent *)ce;
Index: libs/libmyth/libmyth.pro
===================================================================
--- libs/libmyth/libmyth.pro	(revision 10355)
+++ libs/libmyth/libmyth.pro	(working copy)
@@ -75,8 +75,8 @@
 macx {
     HEADERS += audiooutputca.h   screensaver-osx.h   DisplayResOSX.h
     SOURCES += audiooutputca.cpp screensaver-osx.cpp DisplayResOSX.cpp
-    HEADERS += util-osx.h
-    SOURCES += util-osx.cpp
+    HEADERS += util-osx.h AppleRemote.h AppleRemoteListener.h lircevent.h
+    SOURCES += util-osx.cpp AppleRemote.cpp AppleRemoteListener.cpp lircevent.cpp
 
     # Mac OS X Frameworks
     FWKS = ApplicationServices AudioUnit Carbon CoreAudio IOKit
Index: libs/libmyth/mythdialogs.h
===================================================================
--- libs/libmyth/mythdialogs.h	(revision 10355)
+++ libs/libmyth/mythdialogs.h	(working copy)
@@ -123,6 +123,9 @@
     void keyPressEvent(QKeyEvent *e);
     void customEvent(QCustomEvent *ce);
     void closeEvent(QCloseEvent *e);
+#ifdef Q_WS_MACX
+    bool event(QEvent* e);
+#endif
     
     void ExitToMainMenu();
 
Index: libs/libmyth/AppleRemoteListener.h
===================================================================
--- libs/libmyth/AppleRemoteListener.h	(revision 0)
+++ libs/libmyth/AppleRemoteListener.h	(revision 0)
@@ -0,0 +1,17 @@
+#ifndef APPLEREMOTELISTENER
+#define APPLEREMOTELISTENER
+
+#include "AppleRemote.h"
+
+#include <iostream>
+
+class AppleRemoteListener: public AppleRemote::Listener {
+public:
+	AppleRemoteListener(QObject* mainWindow_);
+    // virtual 
+    void appleRemoteButton(AppleRemote::Event button, bool pressedDown);
+private:
+	QObject *mainWindow;
+};
+
+#endif // APPLEREMOTELISTENER
\ No newline at end of file
Index: libs/libmythui/mythmainwindow.cpp
===================================================================
--- libs/libmythui/mythmainwindow.cpp	(revision 10355)
+++ libs/libmythui/mythmainwindow.cpp	(working copy)
@@ -10,7 +10,11 @@
 #include <qwindowsystem_qws.h>
 #endif
 #ifdef Q_WS_MACX
-#import <HIToolbox/Menus.h>   // For GetMBarHeight()
+#include <HIToolbox/Menus.h>   // For GetMBarHeight()
+#include <pthread.h>
+#include "lircevent.h"
+#include "AppleRemote.h"
+#include "AppleRemoteListener.h"
 #endif
 
 #ifdef USE_LIRC
@@ -46,6 +50,22 @@
 }
 #endif
 
+#ifdef Q_WS_MACX
+static void* SpawnAppleRemote(void* param)
+{
+	MythMainWindow *main_window = (MythMainWindow *)param;
+	AppleRemoteListener *arl = new AppleRemoteListener(main_window);
+	AppleRemote& remote(AppleRemote::instance());
+	remote.setListener(arl);
+	remote.startListening();
+	if (!remote.isListeningToRemote()) {
+		return NULL;
+	}
+	remote.runLoop();
+	return NULL;
+}
+#endif
+
 class KeyContext
 {
   public:
@@ -214,6 +234,15 @@
     pthread_create(&lirc_tid, &attr, SpawnLirc, this);
 #endif
 
+#ifdef Q_WS_MACX
+    pthread_t appleremote_tid;
+    pthread_attr_t arattr;
+    pthread_attr_init(&arattr);
+    pthread_attr_setdetachstate(&arattr, PTHREAD_CREATE_DETACHED);
+
+    pthread_create(&appleremote_tid, &arattr, SpawnAppleRemote, this);
+#endif
+
     d->keyContexts.setAutoDelete(true);
 
     RegisterKey("Global", "UP", "Up Arrow", "Up");
@@ -357,6 +386,21 @@
     d->repaintRegion = d->repaintRegion.unite(pe->region());
 }
 
+#ifdef Q_WS_MACX
+bool MythMainWindow::event(QEvent* e) {
+	switch (e->type()) {
+		case QEvent::WindowActivate: {
+			AppleRemote::instance().startListening();
+		}break;
+		case QEvent::WindowDeactivate: {
+			// relinquish the remote
+			AppleRemote::instance().stopListening();
+		}break;
+	}
+	return	QWidget::event(e);
+}
+#endif
+
 void MythMainWindow::Init(void)
 {
     gContext->GetScreenSettings(d->xbase, d->screenwidth, d->wmult,
@@ -901,7 +945,7 @@
             }
         }
     }
-#ifdef USE_LIRC
+#if defined(USE_LIRC) || defined(Q_WS_MACX)
     else if (ce->type() == kLircKeycodeEventType && !d->ignore_lirc_keys) 
     {
         LircKeycodeEvent *lke = (LircKeycodeEvent *)ce;
Index: libs/libmythui/mythmainwindow.h
===================================================================
--- libs/libmythui/mythmainwindow.h	(revision 10355)
+++ libs/libmythui/mythmainwindow.h	(working copy)
@@ -94,6 +94,9 @@
     void customEvent(QCustomEvent *ce);
     void closeEvent(QCloseEvent *e);
     void paintEvent(QPaintEvent *e);
+#ifdef Q_WS_MACX
+    bool event(QEvent* e);
+#endif
     
     void ExitToMainMenu();
 
