Ticket #9090: mythgame-remote-launch.patch
File mythgame-remote-launch.patch, 15.2 KB (added by , 14 years ago) |
---|
-
mythplugins/mythgame/mythgame/gamehandler.cpp
diff --git a/mythplugins/mythgame/mythgame/gamehandler.cpp b/mythplugins/mythgame/mythgame/gamehandler.cpp index 7a93ea8..ac19efc 100644
a b 6 6 #include <QRegExp> 7 7 #include <QDir> 8 8 #include <QList> 9 #include <QMutex> 9 10 10 11 #include <mythcontext.h> 11 12 #include <mythdbcon.h> … … 18 19 #define LOC QString("MythGame:GAMEHANDLER: ") 19 20 20 21 static QList<GameHandler*> *handlers = NULL; 22 static QMutex *game_launch_mutex = NULL; 21 23 22 24 bool existsHandler(const QString name) 23 25 { … … GameHandler* GameHandler::GetHandlerByName(QString systemname) 823 825 824 826 void GameHandler::Launchgame(RomInfo *romdata, QString systemname) 825 827 { 826 GameHandler *handler; 828 GameHandler *handler; 827 829 828 830 if (!systemname.isEmpty() && !systemname.isNull()) 829 831 { … … void GameHandler::Launchgame(RomInfo *romdata, QString systemname) 889 891 } 890 892 } 891 893 892 QString savedir = QDir::current().path(); 893 QDir d; 894 if (!handler->SystemWorkingPath().isEmpty()) 895 { 896 if (!d.cd(handler->SystemWorkingPath())) 897 { 898 VERBOSE(VB_GENERAL, LOC_ERR + QString("Failed to change to specified Working Directory: %1") 899 .arg(handler->SystemWorkingPath())); 900 } 901 } 902 VERBOSE(VB_GENERAL, LOC + QString("Launching Game : %1 : %2") 903 .arg(handler->SystemName()) 904 .arg(exec)); 905 906 GetMythUI()->AddCurrentLocation(QString("MythGame %1 ( %2 )").arg(handler->SystemName()).arg(exec)); 894 if (!game_launch_mutex) 895 game_launch_mutex = new QMutex(); 907 896 908 QStringList cmdlist = exec.split(";"); 909 if (cmdlist.count() > 0) 910 { 911 for (QStringList::Iterator cmd = cmdlist.begin(); cmd != cmdlist.end(); 912 ++cmd ) 913 { 914 VERBOSE(VB_GENERAL, LOC + QString("Executing : %1").arg(*cmd)); 915 myth_system(*cmd, kMSProcessEvents); 916 } 917 } 918 else 897 if (game_launch_mutex->tryLock()) 919 898 { 920 VERBOSE(VB_GENERAL, LOC + QString("Executing : %1").arg(exec)); 921 myth_system(exec, kMSProcessEvents); 899 QString savedir = QDir::current().path(); 900 QDir d; 901 if (!handler->SystemWorkingPath().isEmpty()) 902 { 903 if (!d.cd(handler->SystemWorkingPath())) 904 { 905 VERBOSE(VB_GENERAL, LOC_ERR + QString("Failed to change to specified Working Directory: %1") 906 .arg(handler->SystemWorkingPath())); 907 } 908 } 909 VERBOSE(VB_GENERAL, LOC + QString("Launching Game : %1 : %2") 910 .arg(handler->SystemName()) 911 .arg(exec)); 912 913 GetMythUI()->AddCurrentLocation(QString("game %1 %2").arg(romdata->Gamename()).arg(handler->SystemName())); 914 915 QStringList cmdlist = exec.split(";"); 916 if (cmdlist.count() > 0) 917 { 918 for (QStringList::Iterator cmd = cmdlist.begin(); cmd != cmdlist.end(); 919 ++cmd ) 920 { 921 VERBOSE(VB_GENERAL, LOC + QString("Executing : %1").arg(*cmd)); 922 myth_system(*cmd, kMSProcessEvents | kMSAbortOnJump); 923 } 924 } 925 else 926 { 927 VERBOSE(VB_GENERAL, LOC + QString("Executing : %1").arg(exec)); 928 myth_system(exec, kMSProcessEvents | kMSAbortOnJump); 929 } 930 931 GetMythUI()->RemoveCurrentLocation(); 932 933 (void)d.cd(savedir); 934 935 game_launch_mutex->unlock(); 922 936 } 923 924 GetMythUI()->RemoveCurrentLocation();925 926 (void)d.cd(savedir);927 937 } 928 938 929 939 RomInfo *GameHandler::CreateRomInfo(RomInfo *parent) -
new file mythplugins/mythgame/mythgame/gamelauncher.cpp
diff --git a/mythplugins/mythgame/mythgame/gamelauncher.cpp b/mythplugins/mythgame/mythgame/gamelauncher.cpp new file mode 100644 index 0000000..16cfd26
- + 1 #include "gamelauncher.h" 2 #include "rominfo.h" 3 #include "gamehandler.h" 4 5 #include <QObject> 6 #include <QRegExp> 7 8 #include <mythcontext.h> 9 #include <mythdbcon.h> 10 #include <mythdialogs.h> 11 #include <util.h> 12 #include <mythdb.h> 13 #include <mythuihelper.h> 14 15 #define LOC_ERR QString("MythGame:GAMELAUNCHER Error: ") 16 #define LOC QString("MythGame:GAMELAUNCHER: ") 17 18 MythGameLauncher::MythGameLauncher() 19 { 20 gCoreContext->addListener(this); 21 } 22 23 void MythGameLauncher::customEvent(QEvent *e) 24 { 25 if( e->type() != MythEvent::MythEventMessage) 26 return; 27 28 MythEvent *me = dynamic_cast<MythEvent *>(e); 29 QString message = me->Message(); 30 QStringList tokens = message.split(" ", QString::SkipEmptyParts); 31 32 if (message.left(15) == "NETWORK_CONTROL") 33 { 34 QRegExp qr = QRegExp("NETWORK_CONTROL GAME LAUNCH (\\S+)( (.+))?"); 35 if(message.contains(qr)) 36 { 37 this->LaunchGame(qr.capturedTexts()[1], qr.capturedTexts()[3]); 38 return; 39 } 40 } 41 } 42 43 void MythGameLauncher::LaunchGame(QString name, QString system="") 44 { 45 RomInfo info = RomInfo(); 46 info.setGamename(name); 47 info.fillData(); 48 49 VERBOSE(VB_GENERAL, LOC + QString("Rom Info %1 for game system %2").arg(info.Romname()).arg(info.Gamename())); 50 GameHandler::count(); 51 GameHandler::Launchgame(&info,system); 52 } -
new file mythplugins/mythgame/mythgame/gamelauncher.h
diff --git a/mythplugins/mythgame/mythgame/gamelauncher.h b/mythplugins/mythgame/mythgame/gamelauncher.h new file mode 100644 index 0000000..6fbc088
- + 1 // -*- Mode: c++ -*- 2 #ifndef GAMELAUNCHER_H_ 3 #define GAMELAUNCHER_H_ 4 5 #include <QObject> 6 7 class MythGameLauncher : public QObject 8 { 9 Q_OBJECT 10 11 public: 12 MythGameLauncher(); 13 14 void LaunchGame(QString name, QString type); 15 16 void customEvent(QEvent *event); 17 }; 18 19 #endif /* GAMELAUNCHER_H_ */ -
mythplugins/mythgame/mythgame/main.cpp
diff --git a/mythplugins/mythgame/mythgame/main.cpp b/mythplugins/mythgame/mythgame/main.cpp index 9345a8c..bbb5f05 100644
a b using namespace std; 11 11 #include "rominfo.h" 12 12 #include "gamesettings.h" 13 13 #include "dbcheck.h" 14 #include "gamelauncher.h" 14 15 15 16 #include <mythcontext.h> 16 17 #include <mythdbcon.h> … … using namespace std; 24 25 #define LOC_ERR QString("MythGame:MAIN Error: ") 25 26 #define LOC QString("MythGame:MAIN: ") 26 27 28 MythGameLauncher *launcher; 29 27 30 struct GameData 28 31 { 29 32 }; … … int mythplugin_init(const char *libversion) 146 149 // settings.Load(); 147 150 // settings.Save(); 148 151 152 launcher = new MythGameLauncher(); 153 149 154 setupKeys(); 150 155 151 156 return 0; 152 157 } 153 158 159 void mythplugin_destroy(void) 160 { 161 delete launcher; 162 } 163 154 164 int mythplugin_run(void) 155 165 { 156 166 return RunGames(); -
mythplugins/mythgame/mythgame/mythgame.pro
diff --git a/mythplugins/mythgame/mythgame/mythgame.pro b/mythplugins/mythgame/mythgame/mythgame.pro index 2b934a6..a99dc3f 100644
a b INSTALLS += target installscripts installgiantbomb installgiantbombxsl 20 20 21 21 # Input 22 22 HEADERS += gamehandler.h rominfo.h unzip.h gamesettings.h gameui.h 23 HEADERS += rom_metadata.h romedit.h gamedetails.h 23 HEADERS += rom_metadata.h romedit.h gamedetails.h gamelauncher.h 24 24 25 25 SOURCES += main.cpp gamehandler.cpp rominfo.cpp gameui.cpp unzip.c 26 26 SOURCES += gamesettings.cpp dbcheck.cpp rom_metadata.cpp romedit.cpp 27 SOURCES += gamedetails.cpp 27 SOURCES += gamedetails.cpp gamelauncher.cpp 28 28 29 29 use_hidesyms { 30 30 QMAKE_CXXFLAGS += -fvisibility=hidden -
mythtv/libs/libmythdb/mythsystem.cpp
diff --git a/mythtv/libs/libmythdb/mythsystem.cpp b/mythtv/libs/libmythdb/mythsystem.cpp index 176901c..935a454 100644
a b typedef struct { 48 48 uint result; 49 49 time_t timeout; 50 50 bool background; 51 bool abortOnJump; 51 52 } PidData_t; 52 53 53 54 typedef QMap<pid_t, PidData_t *> PidMap_t; 54 55 55 56 class MythSystemReaper : public QThread 56 57 { 57 public: 58 void run(void); 59 uint waitPid( pid_t pid, time_t timeout, bool background = false, 60 bool processEvents = true ); 61 uint abortPid( pid_t pid ); 62 private: 63 PidMap_t m_pidMap; 64 QMutex m_mapLock; 58 public: 59 void run(void); 60 uint waitPid( pid_t pid, time_t timeout, bool background = false, 61 bool processEvents = true, bool abortOnJump = false ); 62 uint abortPid( pid_t pid ); 63 uint abortOnJump(void); 64 65 private: 66 PidMap_t m_pidMap; 67 QMutex m_mapLock; 65 68 }; 66 69 67 70 static class MythSystemReaper *reaper = NULL; … … void MythSystemReaper::run(void) 103 106 pidData->result = GENERIC_EXIT_TIMEOUT; 104 107 VERBOSE(VB_GENERAL, QString("Child PID %1 timed out, killing") 105 108 .arg(pid)); 106 kill( pid, SIGTERM);109 kill(-pid, SIGTERM); 107 110 usleep(500); 108 kill( pid, SIGKILL);111 kill(-pid, SIGKILL); 109 112 pidData->mutex.unlock(); 110 113 } 111 114 count = m_pidMap.size(); … … void MythSystemReaper::run(void) 167 170 } 168 171 169 172 uint MythSystemReaper::waitPid( pid_t pid, time_t timeout, bool background, 170 bool processEvents )173 bool processEvents, bool abortOnJump ) 171 174 { 172 175 PidData_t *pidData = new PidData_t; 173 176 uint result; … … uint MythSystemReaper::waitPid( pid_t pid, time_t timeout, bool background, 178 181 pidData->timeout = 0; 179 182 180 183 pidData->background = background; 184 pidData->abortOnJump = abortOnJump; 181 185 182 186 pidData->mutex.lock(); 183 187 m_mapLock.lock(); … … uint MythSystemReaper::abortPid( pid_t pid ) 222 226 delete pidData; 223 227 224 228 VERBOSE(VB_GENERAL, QString("Child PID %1 aborted, killing") .arg(pid)); 225 kill( pid, SIGTERM);229 kill(-pid, SIGTERM); 226 230 usleep(500); 227 kill( pid, SIGKILL);231 kill(-pid, SIGKILL); 228 232 result = GENERIC_EXIT_ABORTED; 229 233 return( result ); 230 234 } 235 236 uint MythSystemReaper::abortOnJump( void ) 237 { 238 PidMap_t::iterator i,next; 239 QList<pid_t>::iterator j; 240 uint result = GENERIC_EXIT_ABORTED; 241 242 QList<pid_t> pids = QList<pid_t>(); 243 244 m_mapLock.lock(); 245 for( i = m_pidMap.begin(); i != m_pidMap.end(); ++i ) 246 { 247 if( (i.value()->abortOnJump) ) 248 { 249 pids << i.key(); 250 VERBOSE(VB_GENERAL, QString("pid : %1 ( %2 ; %3 ; %4 )").arg(i.key()).arg(i.value()->result).arg(i.value()->timeout).arg(i.value()->background?"background":"foreground")); 251 } 252 } 253 m_mapLock.unlock(); 254 255 for( j = pids.begin(); j != pids.end(); ++j ) 256 { 257 VERBOSE(VB_GENERAL, QString("SIGTERM process %1").arg(*j)); 258 kill(-(*j), SIGTERM); 259 } 260 261 usleep(500); 262 263 for( j = pids.begin(); j != pids.end(); ++j ) 264 { 265 VERBOSE(VB_GENERAL, QString("SIGKILL process %1").arg(*j)); 266 kill(-(*j), SIGKILL); 267 } 268 269 return result; 270 } 231 271 #endif 232 272 233 273 … … uint myth_system(const QString &command, uint flags, uint timeout) 257 297 258 298 if( result == GENERIC_EXIT_RUNNING ) 259 299 result = myth_system_wait( pid, timeout, (flags & kMSRunBackground), 260 (flags & kMSProcessEvents) ); 300 (flags & kMSProcessEvents), 301 (flags & kMSAbortOnJump)); 261 302 #else 262 303 STARTUPINFO si; 263 304 PROCESS_INFORMATION pi; … … pid_t myth_system_fork(const QString &command, uint &result) 380 421 * execl calls in the child. It causes occasional locking issues that 381 422 * cause deadlocked child processes. */ 382 423 424 /* Set the process group id to be the same as the pid of this child process 425 * This ensures that any subprocesses launched by this process can be killed 426 * along with the process itself. */ 427 setpgid(0,0); 428 383 429 /* Close all open file descriptors except stdout/stderr */ 384 430 for (int i = sysconf(_SC_OPEN_MAX) - 1; i > 2; i--) 385 431 close(i); … … pid_t myth_system_fork(const QString &command, uint &result) 427 473 } 428 474 429 475 uint myth_system_wait(pid_t pid, uint timeout, bool background, 430 bool processEvents )476 bool processEvents, bool abortOnJump) 431 477 { 432 478 if( reaper == NULL ) 433 479 { … … uint myth_system_wait(pid_t pid, uint timeout, bool background, 436 482 } 437 483 VERBOSE(VB_GENERAL, QString("PID %1: launched%2") .arg(pid) 438 484 .arg(background ? " in the background, not waiting" : "")); 439 return reaper->waitPid(pid, timeout, background, processEvents );485 return reaper->waitPid(pid, timeout, background, processEvents, abortOnJump); 440 486 } 441 487 442 488 uint myth_system_abort(pid_t pid) … … uint myth_system_abort(pid_t pid) 449 495 VERBOSE(VB_GENERAL, QString("PID %1: aborted") .arg(pid)); 450 496 return reaper->abortPid(pid); 451 497 } 498 499 uint myth_system_abort_on_jump( void ) 500 { 501 if( reaper == NULL ) 502 { 503 reaper = new MythSystemReaper; 504 reaper->start(); 505 } 506 VERBOSE(VB_GENERAL, QString("Aborting system blocking processes")); 507 return reaper->abortOnJump(); 508 } 452 509 #endif 453 510 454 511 -
mythtv/libs/libmythdb/mythsystem.h
diff --git a/mythtv/libs/libmythdb/mythsystem.h b/mythtv/libs/libmythdb/mythsystem.h index 54c9ffa..702c42c 100644
a b typedef enum MythSystemMask { 13 13 kMSRunBackground = 0x00000004, //< run child in the background 14 14 kMSProcessEvents = 0x00000008, //< process events while waiting 15 15 kMSInUi = 0x00000010, //< the parent is in the UI 16 kMSAbortOnJump = 0x00000020, //< abort this process when a jump-point is activated 16 17 } MythSystemFlag; 17 18 18 19 MPUBLIC unsigned int myth_system(const QString &command, … … MPUBLIC void myth_system_post_flags(uint &flags); 24 25 #ifndef USING_MINGW 25 26 MPUBLIC pid_t myth_system_fork(const QString &command, uint &result); 26 27 MPUBLIC uint myth_system_wait(pid_t pid, uint timeout, bool background = false, 27 bool processEvents = true );28 bool processEvents = true, bool abortOnJump = false); 28 29 MPUBLIC uint myth_system_abort(pid_t pid); 30 MPUBLIC uint myth_system_abort_on_jump( void ); 29 31 #endif 30 32 31 33 #endif -
mythtv/libs/libmythui/mythmainwindow.cpp
diff --git a/mythtv/libs/libmythui/mythmainwindow.cpp b/mythtv/libs/libmythui/mythmainwindow.cpp index 08c5851..560b0a4 100644
a b using namespace std; 44 44 #include "compat.h" 45 45 #include "mythsignalingtimer.h" 46 46 #include "mythcorecontext.h" 47 #include "mythsystem.h" 47 48 48 49 // Libmythui headers 49 50 #include "myththemebase.h" … … void MythMainWindow::JumpTo(const QString& destination, bool pop) 1657 1658 screenShot(); 1658 1659 else if (d->destinationMap.count(destination) > 0 && d->exitmenucallback == NULL) 1659 1660 { 1661 #ifndef USING_MINGW 1662 myth_system_abort_on_jump(); 1663 #endif /* USING_MINGW */ 1664 1660 1665 d->exitingtomain = true; 1661 1666 d->popwindows = pop; 1662 1667 d->exitmenucallback = d->destinationMap[destination].callback; -
mythtv/programs/mythfrontend/networkcontrol.cpp
diff --git a/mythtv/programs/mythfrontend/networkcontrol.cpp b/mythtv/programs/mythfrontend/networkcontrol.cpp index c091433..21cc70d 100644
a b QString NetworkControl::processPlay(NetworkCommand *nc, int clientID) 651 651 "%1, cannot play requested file.") 652 652 .arg(GetMythUI()->GetCurrentLocation()); 653 653 } 654 } else if ((nc->getArgCount() >= 3) && 655 (is_abbrev("game", nc->getArg(1)))) 656 { 657 message = QString("NETWORK_CONTROL GAME LAUNCH %1 %2").arg(nc->getArg(2)).arg(nc->getFrom(3)); 658 result = QString("OK"); 654 659 } 655 660 // Everything below here requires us to be in playback mode so check to 656 661 // see if we are