Index: xbmc/Application.cpp =================================================================== --- xbmc/Application.cpp (revision 22047) +++ xbmc/Application.cpp (working copy) @@ -5418,6 +5418,8 @@ m_gWindowManager.SendThreadMessage(msg); } #endif + if (g_RemoteControl.IsInUse() && !g_RemoteControl.IsInitialized()) + g_RemoteControl.Initialize(); } // Global Idle Time in Seconds Index: guilib/common/LIRC.h =================================================================== --- guilib/common/LIRC.h (revision 22047) +++ guilib/common/LIRC.h (working copy) @@ -17,9 +17,15 @@ bool IsHolding(); void setDeviceName(const CStdString& value); void setUsed(bool value); + bool IsInUse() const { return m_used; } + bool IsInitialized() const { return m_bInitialized; } private: int m_fd; + int m_inotify_fd; + int m_inotify_wd; + int m_lastInitAttempt; + int m_initRetryPeriod; FILE* m_file; bool m_isHolding; WORD m_button; @@ -27,8 +33,10 @@ bool m_bInitialized; bool m_skipHold; bool m_used; + bool m_bLogConnectFailure; Uint32 m_firstClickTime; CStdString m_deviceName; + bool CheckDevice(); }; extern CRemoteControl g_RemoteControl; Index: guilib/common/LIRC.cpp =================================================================== --- guilib/common/LIRC.cpp (revision 22047) +++ guilib/common/LIRC.cpp (working copy) @@ -2,11 +2,14 @@ #include #include #include +#include +#include #include #include "LIRC.h" #include "ButtonTranslator.h" #include "log.h" #include "Settings.h" +#include "FileSystem/File.h" #define LIRC_DEVICE "/dev/lircd" @@ -18,7 +21,15 @@ m_file = NULL; m_bInitialized = false; m_skipHold = false; + m_button = 0; + m_isHolding = false; m_used = true; + m_deviceName = LIRC_DEVICE; + m_inotify_fd = -1; + m_inotify_wd = -1; + m_bLogConnectFailure = true; + m_lastInitAttempt = 0; + m_initRetryPeriod = 5000; CLog::Log(LOGINFO, "LIRC %s: started ", __FUNCTION__); Reset(); } @@ -47,12 +58,20 @@ if (!m_used) return; - if (m_fd) + if (!(m_fd < 0)) { if (m_bInitialized) { m_bInitialized = false; - closesocket(m_fd); + fclose(m_file); + m_fd = -1; + m_file = NULL; + if (m_inotify_wd >= 0) { + inotify_rm_watch(m_inotify_fd, m_inotify_wd); + m_inotify_wd = -1; + } + if (m_inotify_fd >= 0) + close(m_inotify_fd); } } } @@ -68,14 +87,26 @@ void CRemoteControl::Initialize() { struct sockaddr_un addr; - if (!m_used) + int now = timeGetTime(); + + if (!m_used || now < m_lastInitAttempt + m_initRetryPeriod) return; + m_lastInitAttempt = now; + if (!XFILE::CFile::Exists(m_deviceName)) { + m_initRetryPeriod *= 2; + if (m_initRetryPeriod > 60000) + { + m_used = false; + CLog::Log(LOGDEBUG, "LIRC device %s does not exist. Giving up.", m_deviceName.c_str()); + } + else + CLog::Log(LOGDEBUG, "LIRC device %s does not exist. Retry in %ds.", m_deviceName.c_str(), m_initRetryPeriod/1000); + return; + } + addr.sun_family = AF_UNIX; - if (m_deviceName.length()>0) - strcpy(addr.sun_path, m_deviceName.c_str()); - else - strcpy(addr.sun_path, LIRC_DEVICE); + strcpy(addr.sun_path, m_deviceName.c_str()); // Open the socket from which we will receive the remote commands m_fd = socket(AF_UNIX, SOCK_STREAM,0); @@ -88,9 +119,15 @@ // Connect to the socket if (connect(m_fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) { - CLog::Log(LOGINFO, "LIRC %s: connect failed: %s", __FUNCTION__, strerror(errno)); + if (m_bLogConnectFailure) + { + CLog::Log(LOGINFO, "LIRC %s: connect failed: %s", __FUNCTION__, strerror(errno)); + m_bLogConnectFailure = false; + } return; } + + m_bLogConnectFailure = true; // Set the socket to non-blocking int opts = fcntl(m_fd,F_GETFL); @@ -114,15 +151,47 @@ return; } + // Setup inotify so we can disconnect if lircd is restarted + if ((m_inotify_fd = inotify_init1(IN_NONBLOCK)) >= 0) + { + if ((m_inotify_wd = inotify_add_watch(m_inotify_fd, m_deviceName.c_str(), IN_DELETE_SELF)) < 0) + { + close(m_inotify_fd); + m_inotify_fd = -1; + CLog::Log(LOGDEBUG, "LIRC: Failed to initialize Inotify. LIRC device will not be monitored."); + } + } + CLog::Log(LOGINFO, "LIRC %s: sucessfully started on: %s", __FUNCTION__, addr.sun_path); m_bInitialized = true; } +bool CRemoteControl::CheckDevice() { + if (m_inotify_fd < 0 || m_inotify_wd < 0) + return true; // inotify wasn't setup for some reason, assume all is well + int bufsize = sizeof(struct inotify_event) + PATH_MAX; + char buf[bufsize]; + int ret = read(m_inotify_fd, buf, bufsize); + for (int i = 0; i + (int)sizeof(struct inotify_event) <= ret;) { + struct inotify_event* e = (struct inotify_event*)(buf+i); + if (e->mask & IN_DELETE_SELF) { + CLog::Log(LOGDEBUG, "LIRC device removed, disconnecting..."); + Disconnect(); + return false; + } + i += sizeof(struct inotify_event)+e->len; + } + return true; +} + void CRemoteControl::Update() { if (!m_bInitialized || !m_used ) return; + if (!CheckDevice()) + return; + Uint32 now = SDL_GetTicks(); // Read a line from the socket @@ -154,7 +223,7 @@ if (strcmp(repeatStr, "00") == 0) { - CLog::Log(LOGDEBUG, "%s - NEW at %d:%s (%s)", __FUNCTION__, now, m_buf, buttonName); + CLog::Log(LOGDEBUG, "LIRC: %s - NEW at %d:%s (%s)", __FUNCTION__, now, m_buf, buttonName); m_firstClickTime = now; m_isHolding = false; m_skipHold = true; @@ -170,6 +239,8 @@ m_button = 0; } } + if (feof(m_file) != 0) + Disconnect(); m_skipHold = false; }