diff --git a/checkin_notes b/checkin_notes
index bf00e5a8ff..d421b11066 100644
--- a/checkin_notes
+++ b/checkin_notes
@@ -9606,3 +9606,11 @@ David 26 Dec 2011
sched/
sched_customize.cpp
+
+Rom 27 Dec 2011
+ - SCR: Remove last linger pieces of v5 backward graphics compatibility
+ from the screensaver.
+
+ clientscr/
+ screensaver.cpp
+ screensaver_win.h
diff --git a/clientscr/screensaver.cpp b/clientscr/screensaver.cpp
index 25b039daf5..d33c8ac282 100644
--- a/clientscr/screensaver.cpp
+++ b/clientscr/screensaver.cpp
@@ -1,882 +1,873 @@
-// This file is part of BOINC.
-// http://boinc.berkeley.edu
-// Copyright (C) 2008 University of California
-//
-// BOINC is free software; you can redistribute it and/or modify it
-// under the terms of the GNU Lesser General Public License
-// as published by the Free Software Foundation,
-// either version 3 of the License, or (at your option) any later version.
-//
-// BOINC is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-// See the GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with BOINC. If not, see .
-
-// Screensaver coordinator.
-// Alternates between a "default screensaver"
-// and application graphics for running jobs.
-// Periods are configurable via config file "ss_config.xml".
-// See http://boinc.berkeley.edu/trac/wiki/ScreensaverEnhancements
-
-#ifdef _WIN32
-#include "boinc_win.h"
-#endif
-
-#ifdef __APPLE__
-#include
-#include
-#endif
-
-// Common application includes
-//
-#include "diagnostics.h"
-#include "common_defs.h"
-#include "util.h"
-#include "common_defs.h"
-#include "filesys.h"
-#include "error_numbers.h"
-#include "gui_rpc_client.h"
-#include "str_util.h"
-#include "str_replace.h"
-#include "screensaver.h"
-
-// Platform specific application includes
-//
-#if defined(_WIN32)
-#include "screensaver_win.h"
-#elif defined(__APPLE__)
-#include "Mac_Saver_Module.h"
-#endif
-
-
-#ifdef _WIN32
-// Allow for Unicode wide characters
-#define PATH_SEPARATOR (_T("\\"))
-#define THE_DEFAULT_SS_EXECUTABLE (_T(DEFAULT_SS_EXECUTABLE))
-#define THE_SS_CONFIG_FILE (_T(SS_CONFIG_FILE))
-#define DEFAULT_GFX_CANT_CONNECT ERR_CONNECT
-#else
-// Using (_T()) here causes compiler errors on Mac
-#define PATH_SEPARATOR "/"
-#define THE_DEFAULT_SS_EXECUTABLE DEFAULT_SS_EXECUTABLE
-#define THE_SS_CONFIG_FILE SS_CONFIG_FILE
-#define DEFAULT_GFX_CANT_CONNECT (ERR_CONNECT & 0xff)
-#endif
-
-
-// Flags for testing & debugging
-#define SIMULATE_NO_GRAPHICS 0
-
-
-bool CScreensaver::is_same_task(RESULT* taska, RESULT* taskb) {
- if ((taska == NULL) || (taskb == NULL)) return false;
- if (strcmp(taska->name, taskb->name)) return false;
- if (strcmp(taska->project_url, taskb->project_url)) return false;
- return true;
-}
-
-int CScreensaver::count_active_graphic_apps(RESULTS& results, RESULT* exclude) {
- unsigned int i = 0;
- unsigned int graphics_app_count = 0;
- m_bV5_GFX_app_is_running = false;
-
- // Count the number of active graphics-capable apps excluding the specified result.
- // If exclude is NULL, don't exclude any results.
- for (i = 0; i < results.results.size(); i++) {
- BOINCTRACE(_T("get_random_graphics_app -- active task detected\n"));
- BOINCTRACE(
- _T("get_random_graphics_app -- name = '%s', path = '%s'\n"),
- results.results[i]->name, results.results[i]->graphics_exec_path
- );
- if (results.results[i]->supports_graphics) m_bV5_GFX_app_is_running = true;
- if (!strlen(results.results[i]->graphics_exec_path)
- && (state.executing_as_daemon || !(results.results[i]->supports_graphics))
- ) {
- continue;
- }
- BOINCTRACE(_T("get_random_graphics_app -- active task detected w/graphics\n"));
-
- if (is_same_task(results.results[i], exclude)) continue;
- graphics_app_count++;
- }
- return graphics_app_count;
-}
-
-
-// Choose a random graphics application out of the vector.
-// Exclude the specified result unless it is the only candidate.
-// If exclude is NULL or an empty string, don't exclude any results.
-//
-RESULT* CScreensaver::get_random_graphics_app(RESULTS& results, RESULT* exclude) {
- RESULT* rp = NULL;
- unsigned int i = 0;
- unsigned int graphics_app_count = 0;
- unsigned int random_selection = 0;
- unsigned int current_counter = 0;
- RESULT *avoid = exclude;
-
- BOINCTRACE(_T("get_random_graphics_app -- Function Start\n"));
-
- graphics_app_count = count_active_graphic_apps(results, avoid);
- BOINCTRACE(_T("get_random_graphics_app -- graphics_app_count = '%d'\n"), graphics_app_count);
-
- // If no graphics app found other than the one excluded, count again without excluding any
- if ((0 == graphics_app_count) && (avoid != NULL)) {
- avoid = NULL;
- graphics_app_count = count_active_graphic_apps(results, avoid);
- }
-
- // If no graphics app was found, return NULL
- if (0 == graphics_app_count) {
- goto CLEANUP;
- }
-
- // Choose which application to display.
- random_selection = (rand() % graphics_app_count) + 1;
- BOINCTRACE(_T("get_random_graphics_app -- random_selection = '%d'\n"), random_selection);
-
- // Lets find the chosen graphics application.
- for (i = 0; i < results.results.size(); i++) {
- if (!strlen(results.results[i]->graphics_exec_path)
- && (state.executing_as_daemon || !(results.results[i]->supports_graphics))
- ){
- continue;
- }
- if (is_same_task(results.results[i], avoid)) continue;
-
- current_counter++;
- if (current_counter == random_selection) {
- rp = results.results[i];
- break;
- }
- }
-
-CLEANUP:
- BOINCTRACE(_T("get_random_graphics_app -- Function End\n"));
-
- return rp;
-}
-
-
-// Launch a project (science) graphics application
-//
-#ifdef _WIN32
-int CScreensaver::launch_screensaver(RESULT* rp, HANDLE& graphics_application)
-#else
-int CScreensaver::launch_screensaver(RESULT* rp, int& graphics_application)
-#endif
-{
- int retval = 0;
- if (strlen(rp->graphics_exec_path)) {
- // V6 Graphics
-#ifdef __APPLE__
- // For sandbox security, use gfx_switcher to launch gfx app
- // as user boinc_project and group boinc_project.
- //
- // For unknown reasons, the graphics application exits with
- // "RegisterProcess failed (error = -50)" unless we pass its
- // full path twice in the argument list to execv.
- char* argv[5];
- argv[0] = "gfx_Switcher";
- argv[1] = "-launch_gfx";
- argv[2] = strrchr(rp->slot_path, '/');
- if (*argv[2]) argv[2]++; // Point to the slot number in ascii
-
- argv[3] = "--fullscreen";
- argv[4] = 0;
-
- retval = run_program(
- rp->slot_path,
- m_gfx_Switcher_Path,
- 4,
- argv,
- 0,
- graphics_application
- );
-#else
- char* argv[3];
- argv[0] = "app_graphics"; // not used
- argv[1] = "--fullscreen";
- argv[2] = 0;
- retval = run_program(
- rp->slot_path,
- rp->graphics_exec_path,
- 2,
- argv,
- 0,
- graphics_application
- );
-#endif
- }
- return retval;
-}
-
-
-// Terminate any screensaver graphics application
-//
-#ifdef _WIN32
-int CScreensaver::terminate_v6_screensaver(HANDLE& graphics_application)
-#else
-int CScreensaver::terminate_v6_screensaver(int& graphics_application)
-#endif
-{
- int retval = 0;
-
-#ifdef __APPLE__
- // Under sandbox security, use gfx_switcher to kill default gfx app
- // as user boinc_master and group boinc_master. The man page for
- // kill() says the user ID of the process sending the signal must
- // match that of the target process, though in practice that seems
- // not to be true on the Mac.
-
- char current_dir[PATH_MAX];
- char gfx_pid[16];
- pid_t thePID;
- int i;
-
- sprintf(gfx_pid, "%d", graphics_application);
- getcwd( current_dir, sizeof(current_dir));
-
- char* argv[4];
- argv[0] = "gfx_switcher";
- argv[1] = "-kill_gfx";
- argv[2] = gfx_pid;
- argv[3] = 0;
-
- retval = run_program(
- current_dir,
- m_gfx_Switcher_Path,
- 3,
- argv,
- 0,
- thePID
- );
-
- for (i=0; i<200; i++) {
- boinc_sleep(0.01); // Wait 2 seconds max
- // Prevent gfx_switcher from becoming a zombie
- if (waitpid(thePID, 0, WNOHANG) == thePID) {
- break;
- }
- }
-#endif
-
-#ifdef _WIN32
+// This file is part of BOINC.
+// http://boinc.berkeley.edu
+// Copyright (C) 2008 University of California
+//
+// BOINC is free software; you can redistribute it and/or modify it
+// under the terms of the GNU Lesser General Public License
+// as published by the Free Software Foundation,
+// either version 3 of the License, or (at your option) any later version.
+//
+// BOINC is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with BOINC. If not, see .
+
+// Screensaver coordinator.
+// Alternates between a "default screensaver"
+// and application graphics for running jobs.
+// Periods are configurable via config file "ss_config.xml".
+// See http://boinc.berkeley.edu/trac/wiki/ScreensaverEnhancements
+
+#ifdef _WIN32
+#include "boinc_win.h"
+#endif
+
+#ifdef __APPLE__
+#include
+#include
+#endif
+
+// Common application includes
+//
+#include "diagnostics.h"
+#include "common_defs.h"
+#include "util.h"
+#include "common_defs.h"
+#include "filesys.h"
+#include "error_numbers.h"
+#include "gui_rpc_client.h"
+#include "str_util.h"
+#include "str_replace.h"
+#include "screensaver.h"
+
+// Platform specific application includes
+//
+#if defined(_WIN32)
+#include "screensaver_win.h"
+#elif defined(__APPLE__)
+#include "Mac_Saver_Module.h"
+#endif
+
+
+#ifdef _WIN32
+// Allow for Unicode wide characters
+#define PATH_SEPARATOR (_T("\\"))
+#define THE_DEFAULT_SS_EXECUTABLE (_T(DEFAULT_SS_EXECUTABLE))
+#define THE_SS_CONFIG_FILE (_T(SS_CONFIG_FILE))
+#define DEFAULT_GFX_CANT_CONNECT ERR_CONNECT
+#else
+// Using (_T()) here causes compiler errors on Mac
+#define PATH_SEPARATOR "/"
+#define THE_DEFAULT_SS_EXECUTABLE DEFAULT_SS_EXECUTABLE
+#define THE_SS_CONFIG_FILE SS_CONFIG_FILE
+#define DEFAULT_GFX_CANT_CONNECT (ERR_CONNECT & 0xff)
+#endif
+
+
+// Flags for testing & debugging
+#define SIMULATE_NO_GRAPHICS 0
+
+
+bool CScreensaver::is_same_task(RESULT* taska, RESULT* taskb) {
+ if ((taska == NULL) || (taskb == NULL)) return false;
+ if (strcmp(taska->name, taskb->name)) return false;
+ if (strcmp(taska->project_url, taskb->project_url)) return false;
+ return true;
+}
+
+int CScreensaver::count_active_graphic_apps(RESULTS& results, RESULT* exclude) {
+ unsigned int i = 0;
+ unsigned int graphics_app_count = 0;
+
+ // Count the number of active graphics-capable apps excluding the specified result.
+ // If exclude is NULL, don't exclude any results.
+ for (i = 0; i < results.results.size(); i++) {
+ BOINCTRACE(_T("get_random_graphics_app -- active task detected\n"));
+ BOINCTRACE(
+ _T("get_random_graphics_app -- name = '%s', path = '%s'\n"),
+ results.results[i]->name, results.results[i]->graphics_exec_path
+ );
+
+ if (!strlen(results.results[i]->graphics_exec_path)) continue;
+ if (is_same_task(results.results[i], exclude)) continue;
+ BOINCTRACE(_T("get_random_graphics_app -- active task detected w/graphics\n"));
+
+ graphics_app_count++;
+ }
+ return graphics_app_count;
+}
+
+
+// Choose a random graphics application out of the vector.
+// Exclude the specified result unless it is the only candidate.
+// If exclude is NULL or an empty string, don't exclude any results.
+//
+RESULT* CScreensaver::get_random_graphics_app(RESULTS& results, RESULT* exclude) {
+ RESULT* rp = NULL;
+ unsigned int i = 0;
+ unsigned int graphics_app_count = 0;
+ unsigned int random_selection = 0;
+ unsigned int current_counter = 0;
+ RESULT *avoid = exclude;
+
+ BOINCTRACE(_T("get_random_graphics_app -- Function Start\n"));
+
+ graphics_app_count = count_active_graphic_apps(results, avoid);
+ BOINCTRACE(_T("get_random_graphics_app -- graphics_app_count = '%d'\n"), graphics_app_count);
+
+ // If no graphics app found other than the one excluded, count again without excluding any
+ if ((0 == graphics_app_count) && (avoid != NULL)) {
+ avoid = NULL;
+ graphics_app_count = count_active_graphic_apps(results, avoid);
+ }
+
+ // If no graphics app was found, return NULL
+ if (0 == graphics_app_count) {
+ goto CLEANUP;
+ }
+
+ // Choose which application to display.
+ random_selection = (rand() % graphics_app_count) + 1;
+ BOINCTRACE(_T("get_random_graphics_app -- random_selection = '%d'\n"), random_selection);
+
+ // Lets find the chosen graphics application.
+ for (i = 0; i < results.results.size(); i++) {
+ if (!strlen(results.results[i]->graphics_exec_path)) continue;
+ if (is_same_task(results.results[i], avoid)) continue;
+
+ current_counter++;
+ if (current_counter == random_selection) {
+ rp = results.results[i];
+ break;
+ }
+ }
+
+CLEANUP:
+ BOINCTRACE(_T("get_random_graphics_app -- Function End\n"));
+
+ return rp;
+}
+
+
+// Launch a project (science) graphics application
+//
+#ifdef _WIN32
+int CScreensaver::launch_screensaver(RESULT* rp, HANDLE& graphics_application)
+#else
+int CScreensaver::launch_screensaver(RESULT* rp, int& graphics_application)
+#endif
+{
+ int retval = 0;
+ if (strlen(rp->graphics_exec_path)) {
+ // V6 Graphics
+#ifdef __APPLE__
+ // For sandbox security, use gfx_switcher to launch gfx app
+ // as user boinc_project and group boinc_project.
+ //
+ // For unknown reasons, the graphics application exits with
+ // "RegisterProcess failed (error = -50)" unless we pass its
+ // full path twice in the argument list to execv.
+ char* argv[5];
+ argv[0] = "gfx_Switcher";
+ argv[1] = "-launch_gfx";
+ argv[2] = strrchr(rp->slot_path, '/');
+ if (*argv[2]) argv[2]++; // Point to the slot number in ascii
+
+ argv[3] = "--fullscreen";
+ argv[4] = 0;
+
+ retval = run_program(
+ rp->slot_path,
+ m_gfx_Switcher_Path,
+ 4,
+ argv,
+ 0,
+ graphics_application
+ );
+#else
+ char* argv[3];
+ argv[0] = "app_graphics"; // not used
+ argv[1] = "--fullscreen";
+ argv[2] = 0;
+ retval = run_program(
+ rp->slot_path,
+ rp->graphics_exec_path,
+ 2,
+ argv,
+ 0,
+ graphics_application
+ );
+#endif
+ }
+ return retval;
+}
+
+
+// Terminate any screensaver graphics application
+//
+#ifdef _WIN32
+int CScreensaver::terminate_v6_screensaver(HANDLE& graphics_application)
+#else
+int CScreensaver::terminate_v6_screensaver(int& graphics_application)
+#endif
+{
+ int retval = 0;
+
+#ifdef __APPLE__
+ // Under sandbox security, use gfx_switcher to kill default gfx app
+ // as user boinc_master and group boinc_master. The man page for
+ // kill() says the user ID of the process sending the signal must
+ // match that of the target process, though in practice that seems
+ // not to be true on the Mac.
+
+ char current_dir[PATH_MAX];
+ char gfx_pid[16];
+ pid_t thePID;
+ int i;
+
+ sprintf(gfx_pid, "%d", graphics_application);
+ getcwd( current_dir, sizeof(current_dir));
+
+ char* argv[4];
+ argv[0] = "gfx_switcher";
+ argv[1] = "-kill_gfx";
+ argv[2] = gfx_pid;
+ argv[3] = 0;
+
+ retval = run_program(
+ current_dir,
+ m_gfx_Switcher_Path,
+ 3,
+ argv,
+ 0,
+ thePID
+ );
+
+ for (i=0; i<200; i++) {
+ boinc_sleep(0.01); // Wait 2 seconds max
+ // Prevent gfx_switcher from becoming a zombie
+ if (waitpid(thePID, 0, WNOHANG) == thePID) {
+ break;
+ }
+ }
+#endif
+
+#ifdef _WIN32
HWND hBOINCGraphicsWindow = FindWindow(BOINC_WINDOW_CLASS_NAME, NULL);
if (hBOINCGraphicsWindow) {
CloseWindow(hBOINCGraphicsWindow);
Sleep(1000);
hBOINCGraphicsWindow = FindWindow(BOINC_WINDOW_CLASS_NAME, NULL);
if (hBOINCGraphicsWindow) {
- kill_program(graphics_application);
+ kill_program(graphics_application);
}
- }
-#endif
-
- // For safety, call kill_program even under Apple sandbox security
- kill_program(graphics_application);
- return retval;
-}
-
-
-// Terminate the project (science) graphics application
-//
-#ifdef _WIN32
-int CScreensaver::terminate_screensaver(HANDLE& graphics_application, RESULT *worker_app)
-#else
-int CScreensaver::terminate_screensaver(int& graphics_application, RESULT *worker_app)
-#endif
-{
- int retval = 0;
-
- if (graphics_application) {
- // V6 Graphics
- if (m_bScience_gfx_running) {
- terminate_v6_screensaver(graphics_application);
- }
- }
- return retval;
-}
-
-
-// Launch the default graphics application
-//
-#ifdef _WIN32
-int CScreensaver::launch_default_screensaver(char *dir_path, HANDLE& graphics_application)
-#else
-int CScreensaver::launch_default_screensaver(char *dir_path, int& graphics_application)
-#endif
-{
- int retval = 0;
- int num_args;
-
-#ifdef __APPLE__
- // For sandbox security, use gfx_switcher to launch default
- // gfx app as user boinc_master and group boinc_master.
- char* argv[6];
-
- argv[0] = "gfx_switcher";
- argv[1] = "-default_gfx";
- argv[2] = THE_DEFAULT_SS_EXECUTABLE; // Will be changed by gfx_switcher
- argv[3] = "--fullscreen";
- argv[4] = 0;
- argv[5] = 0;
- if (!m_bConnected) {
- BOINCTRACE(_T("launch_default_screensaver using --retry_connect argument\n"));
- argv[4] = "--retry_connect";
- num_args = 5;
- } else {
- num_args = 4;
- }
-
- retval = run_program(
- dir_path,
- m_gfx_Switcher_Path,
- num_args,
- argv,
- 0,
- graphics_application
- );
-
- BOINCTRACE(_T("launch_default_screensaver returned %d\n"), retval);
-
-#else
- // For unknown reasons, the graphics application exits with
- // "RegisterProcess failed (error = -50)" unless we pass its
- // full path twice in the argument list to execv on Macs.
-
- char* argv[4];
- char full_path[1024];
-
- strlcpy(full_path, dir_path, sizeof(full_path));
- strlcat(full_path, PATH_SEPARATOR, sizeof(full_path));
- strlcat(full_path, THE_DEFAULT_SS_EXECUTABLE, sizeof(full_path));
-
- argv[0] = full_path; // not used
- argv[1] = "--fullscreen";
- argv[2] = 0;
- argv[3] = 0;
- if (!m_bConnected) {
- BOINCTRACE(_T("launch_default_screensaver using --retry_connect argument\n"));
- argv[2] = "--retry_connect";
- num_args = 3;
- } else {
- num_args = 2;
- }
-
- retval = run_program(
- dir_path,
- full_path,
- num_args,
- argv,
- 0,
- graphics_application
- );
-
- BOINCTRACE(_T("launch_default_screensaver %s returned %d\n"), full_path, retval);
-
-#endif
- return retval;
-}
-
-
-// Terminate the default graphics application
-//
-#ifdef _WIN32
-int CScreensaver::terminate_default_screensaver(HANDLE& graphics_application)
-#else
-int CScreensaver::terminate_default_screensaver(int& graphics_application)
-#endif
-{
- int retval = 0;
-
- if (! graphics_application) return 0;
- retval = terminate_v6_screensaver(graphics_application);
- return retval;
-}
-
-
-// If we cannot connect to the core client:
-// - we retry connecting every 10 seconds
-// - we launch the default graphics application with the argument --retry_connect, so
-// it will continue running and will also retry connecting every 10 seconds.
-//
-// If we successfully connected to the core client, launch the default graphics application
-// without the argument --retry_connect. If it can't connect, it will return immediately
-// with the exit code ERR_CONNECT. In that case, we assume it was blocked by a firewall
-// and so we run only project (science) graphics.
-
-#ifdef _WIN32
-DWORD WINAPI CScreensaver::DataManagementProc()
-#else
-void *CScreensaver::DataManagementProc()
-#endif
-{
- int retval = 0;
- int suspend_reason = 0;
- RESULT* theResult = NULL;
- RESULT* graphics_app_result_ptr = NULL;
- RESULT previous_result;
- // previous_result_ptr = &previous_result when previous_result is valid, else NULL
- RESULT* previous_result_ptr = NULL;
- int iResultCount = 0;
- int iIndex = 0;
- double default_phase_start_time = 0.0;
- double science_phase_start_time = 0.0;
- double last_change_time = 0.0;
- // If we run default screensaver during science phase because no science graphics
- // are available, then shorten next default graphics phase by that much time.
- double default_saver_start_time_in_science_phase = 0.0;
- double default_saver_duration_in_science_phase = 0.0;
-
- SS_PHASE ss_phase = DEFAULT_SS_PHASE;
- bool switch_to_default_gfx = false;
- bool killing_default_gfx = false;
- int exit_status = 0;
-
- char* default_ss_dir_path = NULL;
- char full_path[1024];
-
- BOINCTRACE(_T("CScreensaver::DataManagementProc - Display screen saver loading message\n"));
- SetError(TRUE, SCRAPPERR_BOINCSCREENSAVERLOADING); // No GFX App is running: show moving BOINC logo
-#ifdef _WIN32
- m_tThreadCreateTime = time(0);
-
- // Set the starting point for iterating through the results
- m_iLastResultShown = 0;
- m_tLastResultChangeTime = 0;
-#endif
-
- m_bDefault_ss_exists = false;
- m_bScience_gfx_running = false;
- m_bDefault_gfx_running = false;
- m_bShow_default_ss_first = false;
-
-#ifdef __APPLE__
- default_ss_dir_path = "/Library/Application Support/BOINC Data";
-#else
- default_ss_dir_path = (char*)m_strBOINCInstallDirectory.c_str();
-#endif
-
- strlcpy(full_path, default_ss_dir_path, sizeof(full_path));
- strlcat(full_path, PATH_SEPARATOR, sizeof(full_path));
- strlcat(full_path, THE_DEFAULT_SS_EXECUTABLE, sizeof(full_path));
-
- if (boinc_file_exists(full_path)) {
- m_bDefault_ss_exists = true;
- } else {
- SetError(TRUE, SCRAPPERR_CANTLAUNCHDEFAULTGFXAPP); // No GFX App is running: show moving BOINC logo
- }
-
- if (m_bDefault_ss_exists && m_bShow_default_ss_first) {
- ss_phase = DEFAULT_SS_PHASE;
- default_phase_start_time = dtime();
- science_phase_start_time = 0;
- switch_to_default_gfx = true;
- } else {
- ss_phase = SCIENCE_SS_PHASE;
- default_phase_start_time = 0;
- science_phase_start_time = dtime();
- }
-
- while (true) {
-
- for (int i = 0; i < 4; i++) {
- // ***
- // *** Things that should be run frequently.
- // *** 4 times per second.
- // ***
-
- // Are we supposed to exit the screensaver?
- if (m_bQuitDataManagementProc) { // If main thread has requested we exit
- BOINCTRACE(_T("CScreensaver::DataManagementProc - Thread told to stop\n"));
- if (m_hGraphicsApplication || graphics_app_result_ptr) {
- if (m_bDefault_gfx_running) {
- BOINCTRACE(_T("CScreensaver::DataManagementProc - Terminating default screensaver\n"));
- terminate_default_screensaver(m_hGraphicsApplication);
- } else {
- BOINCTRACE(_T("CScreensaver::DataManagementProc - Terminating screensaver\n"));
- terminate_screensaver(m_hGraphicsApplication, graphics_app_result_ptr);
- }
- graphics_app_result_ptr = NULL;
- previous_result_ptr = NULL;
- m_hGraphicsApplication = 0;
- }
- BOINCTRACE(_T("CScreensaver::DataManagementProc - Stopping...\n"));
- m_bDataManagementProcStopped = true; // Tell main thread that we exited
- return 0; // Exit the thread
- }
- boinc_sleep(0.25);
- }
-
- // ***
- // *** Things that should be run less frequently.
- // *** 1 time per second.
- // ***
-
- // Blank screen saver?
- if ((m_dwBlankScreen) && (time(0) > m_dwBlankTime) && (m_dwBlankTime > 0)) {
- BOINCTRACE(_T("CScreensaver::DataManagementProc - Time to blank\n"));
- SetError(FALSE, SCRAPPERR_SCREENSAVERBLANKED); // Blanked - hide moving BOINC logo
- m_bQuitDataManagementProc = true;
- continue; // Code above will exit the thread
- }
-
- BOINCTRACE(_T("CScreensaver::DataManagementProc - ErrorMode = '%d', ErrorCode = '%x'\n"), m_bErrorMode, m_hrError);
-
- if (!m_bConnected) {
- HandleRPCError();
- }
-
- if (m_bConnected) {
- // Do we need to get the core client state?
- if (m_bResetCoreState) {
- // Try and get the current state of the CC
- retval = rpc->get_state(state);
- if (retval) {
- // CC may not yet be running
- HandleRPCError();
- continue;
- } else {
- m_bResetCoreState = false;
- }
- }
-
- // Update our task list
- retval = rpc->get_screensaver_tasks(suspend_reason, results);
- if (retval) {
- // rpc call returned error
- HandleRPCError();
- m_bResetCoreState = true;
- continue;
- }
- } else {
- results.clear();
- }
-
- // Time to switch to default graphics phase?
- if (m_bDefault_ss_exists && (ss_phase == SCIENCE_SS_PHASE) && (m_fGFXDefaultPeriod > 0)) {
- if (science_phase_start_time && ((dtime() - science_phase_start_time) > m_fGFXSciencePeriod)) {
- if (!m_bDefault_gfx_running) {
- switch_to_default_gfx = true;
- }
- ss_phase = DEFAULT_SS_PHASE;
- default_phase_start_time = dtime();
- science_phase_start_time = 0;
- if (m_bDefault_gfx_running && default_saver_start_time_in_science_phase) {
- // Remember how long default graphics ran during science phase
- default_saver_duration_in_science_phase += (dtime() - default_saver_start_time_in_science_phase);
- }
- default_saver_start_time_in_science_phase = 0;
- }
- }
-
- // Time to switch to science graphics phase?
- if ((ss_phase == DEFAULT_SS_PHASE) && m_bConnected && (m_fGFXSciencePeriod > 0)) {
- if (default_phase_start_time &&
- ((dtime() - default_phase_start_time + default_saver_duration_in_science_phase)
- > m_fGFXDefaultPeriod)) {
- // BOINCTRACE(_T("CScreensaver::Ending Default phase: now=%f, default_phase_start_time=%f, default_saver_duration_in_science_phase=%f\n"),
- // dtime(), default_phase_start_time, default_saver_duration_in_science_phase);
- ss_phase = SCIENCE_SS_PHASE;
- default_phase_start_time = 0;
- default_saver_duration_in_science_phase = 0;
- science_phase_start_time = dtime();
- if (m_bDefault_gfx_running) {
- default_saver_start_time_in_science_phase = science_phase_start_time;
- }
- switch_to_default_gfx = false;
- }
- }
-
- // Core client suspended?
- if (suspend_reason && !(suspend_reason & (SUSPEND_REASON_CPU_THROTTLE | SUSPEND_REASON_CPU_USAGE))) {
- if (!m_bDefault_gfx_running) {
- SetError(TRUE, m_hrError); // No GFX App is running: show moving BOINC logo
- if (m_bDefault_ss_exists) {
- switch_to_default_gfx = true;
- }
- }
- }
-
- if (switch_to_default_gfx) {
- if (m_bScience_gfx_running) {
- if (m_hGraphicsApplication || previous_result_ptr) {
- // use previous_result_ptr because graphics_app_result_ptr may no longer be valid
- terminate_screensaver(m_hGraphicsApplication, previous_result_ptr);
- if (m_hGraphicsApplication == 0) {
- graphics_app_result_ptr = NULL;
- m_bScience_gfx_running = false;
- } else {
- // HasProcessExited() test will clear m_hGraphicsApplication and graphics_app_result_ptr
- }
- previous_result_ptr = NULL;
- }
- } else {
- if (!m_bDefault_gfx_running) {
- switch_to_default_gfx = false;
- retval = launch_default_screensaver(default_ss_dir_path, m_hGraphicsApplication);
- if (retval) {
- m_hGraphicsApplication = 0;
- previous_result_ptr = NULL;
- graphics_app_result_ptr = NULL;
- m_bDefault_gfx_running = false;
- SetError(TRUE, SCRAPPERR_CANTLAUNCHDEFAULTGFXAPP); // No GFX App is running: show moving BOINC logo
- } else {
- m_bDefault_gfx_running = true;
- if (ss_phase == SCIENCE_SS_PHASE) {
- default_saver_start_time_in_science_phase = dtime();
- }
- SetError(FALSE, SCRAPPERR_BOINCSCREENSAVERLOADING); // A GFX App is running: hide moving BOINC logo
- }
- }
- }
- }
-
- if ((ss_phase == SCIENCE_SS_PHASE) && !switch_to_default_gfx) {
-
-#if SIMULATE_NO_GRAPHICS /* FOR TESTING */
-
- if (!m_bDefault_gfx_running) {
- SetError(TRUE, m_hrError); // No GFX App is running: show moving BOINC logo
- if (m_bDefault_ss_exists) {
- switch_to_default_gfx = true;
- }
- }
-
-#else /* NORMAL OPERATION */
-
- if (m_bScience_gfx_running) {
- // Is the current graphics app's associated task still running?
-
- if ((m_hGraphicsApplication) || (graphics_app_result_ptr)) {
- iResultCount = (int)results.results.size();
- graphics_app_result_ptr = NULL;
-
- // Find the current task in the new results vector (if it still exists)
- for (iIndex = 0; iIndex < iResultCount; iIndex++) {
- theResult = results.results.at(iIndex);
-
- if (is_same_task(theResult, previous_result_ptr)) {
- graphics_app_result_ptr = theResult;
- previous_result = *theResult;
- previous_result_ptr = &previous_result;
- break;
- }
- }
-
- // V6 graphics only: if worker application has stopped running, terminate_screensaver
- if ((graphics_app_result_ptr == NULL) && (m_hGraphicsApplication != 0)) {
- if (previous_result_ptr) {
- BOINCTRACE(_T("CScreensaver::DataManagementProc - %s finished\n"),
- previous_result.graphics_exec_path
- );
- }
- terminate_screensaver(m_hGraphicsApplication, previous_result_ptr);
- previous_result_ptr = NULL;
- if (m_hGraphicsApplication == 0) {
- graphics_app_result_ptr = NULL;
- m_bScience_gfx_running = false;
- // Save previous_result and previous_result_ptr for get_random_graphics_app() call
- } else {
- // HasProcessExited() test will clear m_hGraphicsApplication and graphics_app_result_ptr
- }
- }
-
- if (last_change_time && (m_fGFXChangePeriod > 0) && ((dtime() - last_change_time) > m_fGFXChangePeriod) ) {
- if (count_active_graphic_apps(results, previous_result_ptr) > 0) {
- if (previous_result_ptr) {
- BOINCTRACE(_T("CScreensaver::DataManagementProc - time to change: %s / %s\n"),
- previous_result.name, previous_result.graphics_exec_path
- );
- }
- terminate_screensaver(m_hGraphicsApplication, graphics_app_result_ptr);
- if (m_hGraphicsApplication == 0) {
- graphics_app_result_ptr = NULL;
- m_bScience_gfx_running = false;
- // Save previous_result and previous_result_ptr for get_random_graphics_app() call
- } else {
- // HasProcessExited() test will clear m_hGraphicsApplication and graphics_app_result_ptr
- }
- }
- last_change_time = dtime();
- }
- }
- } // End if (m_bScience_gfx_running)
-
- // If no current graphics app, pick an active task at random and launch its graphics app
- if ((m_bDefault_gfx_running || (m_hGraphicsApplication == 0)) && (graphics_app_result_ptr == NULL)) {
- graphics_app_result_ptr = get_random_graphics_app(results, previous_result_ptr);
- previous_result_ptr = NULL;
-
- if (graphics_app_result_ptr) {
- if (m_bDefault_gfx_running) {
- terminate_default_screensaver(m_hGraphicsApplication);
- killing_default_gfx = true;
- // Remember how long default graphics ran during science phase
- if (default_saver_start_time_in_science_phase) {
- default_saver_duration_in_science_phase += (dtime() - default_saver_start_time_in_science_phase);
- //BOINCTRACE(_T("CScreensaver::During Science phase: now=%f, default_saver_start_time=%f, default_saver_duration=%f\n"),
- // dtime(), default_saver_start_time_in_science_phase, default_saver_duration_in_science_phase);
- }
- default_saver_start_time_in_science_phase = 0;
- // HasProcessExited() test will clear m_hGraphicsApplication and graphics_app_result_ptr
- } else {
- retval = launch_screensaver(graphics_app_result_ptr, m_hGraphicsApplication);
- if (retval) {
- m_hGraphicsApplication = 0;
- previous_result_ptr = NULL;
- graphics_app_result_ptr = NULL;
- m_bScience_gfx_running = false;
- } else {
- SetError(FALSE, SCRAPPERR_BOINCSCREENSAVERLOADING); // A GFX App is running: hide moving BOINC logo
- last_change_time = dtime();
- m_bScience_gfx_running = true;
- // Make a local copy of current result, since original pointer
- // may have been freed by the time we perform later tests
- previous_result = *graphics_app_result_ptr;
- previous_result_ptr = &previous_result;
- if (previous_result_ptr) {
- BOINCTRACE(_T("CScreensaver::DataManagementProc - launching %s\n"),
- previous_result.graphics_exec_path
- );
- }
- }
- }
- } else {
- if (!m_bDefault_gfx_running) {
- // We can't run a science graphics app, so run the default graphics if available
- SetError(TRUE, m_hrError);
- if (m_bDefault_ss_exists) {
- switch_to_default_gfx = true;
- }
- }
-
- } // End if no science graphics available
- } // End if no current science graphics app is running
-
-#endif // ! SIMULATE_NO_GRAPHICS
-
- if (switch_to_default_gfx) {
- switch_to_default_gfx = false;
- if (!m_bDefault_gfx_running) {
- retval = launch_default_screensaver(default_ss_dir_path, m_hGraphicsApplication);
- if (retval) {
- m_hGraphicsApplication = 0;
- previous_result_ptr = NULL;
- graphics_app_result_ptr = NULL;
- m_bDefault_gfx_running = false;
- SetError(TRUE, SCRAPPERR_CANTLAUNCHDEFAULTGFXAPP); // No GFX App is running: show BOINC logo
- } else {
- m_bDefault_gfx_running = true;
- default_saver_start_time_in_science_phase = dtime();
- SetError(FALSE, SCRAPPERR_BOINCSCREENSAVERLOADING); // Default GFX App is running: hide moving BOINC logo
- }
- }
- }
- } // End if ((ss_phase == SCIENCE_SS_PHASE) && !switch_to_default_gfx)
-
-
-
- // Is the graphics app still running?
- if (m_hGraphicsApplication) {
- if (HasProcessExited(m_hGraphicsApplication, exit_status)) {
- // Something has happened to the previously selected screensaver
- // application. Start a different one.
- BOINCTRACE(_T("CScreensaver::DataManagementProc - Graphics application isn't running, start a new one.\n"));
- if (m_bDefault_gfx_running) {
- // If we were able to connect to core client but gfx app can't, don't use it.
- BOINCTRACE(_T("CScreensaver::DataManagementProc - Default graphics application exited with code %d.\n"), exit_status);
- if (!killing_default_gfx) { // If this is an unexpected exit
- if (exit_status == DEFAULT_GFX_CANT_CONNECT) {
- SetError(TRUE, SCRAPPERR_DEFAULTGFXAPPCANTCONNECT); // No GFX App is running: show moving BOINC logo
- } else {
- SetError(TRUE, SCRAPPERR_DEFAULTGFXAPPCRASHED); // No GFX App is running: show moving BOINC logo
- }
- m_bDefault_ss_exists = false;
- ss_phase = SCIENCE_SS_PHASE;
- }
- killing_default_gfx = false;
- }
- SetError(TRUE, SCRAPPERR_BOINCNOGRAPHICSAPPSEXECUTING); // No GFX App is running: show moving BOINC logo
- m_hGraphicsApplication = 0;
- graphics_app_result_ptr = NULL;
- m_bDefault_gfx_running = false;
- m_bScience_gfx_running = false;
- continue;
- }
- }
- } // end while(true)
-}
-
-
-#ifdef _WIN32
-BOOL CScreensaver::HasProcessExited(HANDLE pid_handle, int &exitCode) {
- unsigned long status = 1;
- if (GetExitCodeProcess(pid_handle, &status)) {
- if (status == STILL_ACTIVE) {
- exitCode = 0;
- return false;
- }
- }
- exitCode = (int)status;
- return true;
-}
-#else
-bool CScreensaver::HasProcessExited(pid_t pid, int &exitCode) {
- int status;
- pid_t p;
-
- p = waitpid(pid, &status, WNOHANG);
- exitCode = WEXITSTATUS(status);
- if (p == pid) return true; // process has exited
- if (p == -1) return true; // PID doesn't exist
- exitCode = 0;
- return false;
-}
-#endif
-
-
-void CScreensaver::GetDefaultDisplayPeriods(struct ss_periods &periods)
-{
- char* default_data_dir_path = NULL;
- char buf[1024];
- FILE* f;
- MIOFILE mf;
-
- periods.GFXDefaultPeriod = GFX_DEFAULT_PERIOD;
- periods.GFXSciencePeriod = GFX_SCIENCE_PERIOD;
- periods.GFXChangePeriod = GFX_CHANGE_PERIOD;
- periods.Show_default_ss_first = false;
-
-#ifdef __APPLE__
- default_data_dir_path = "/Library/Application Support/BOINC Data";
-#else
- default_data_dir_path = (char*)m_strBOINCDataDirectory.c_str();
-#endif
-
- strlcpy(buf, default_data_dir_path, sizeof(buf));
- strlcat(buf, PATH_SEPARATOR, sizeof(buf));
- strlcat(buf, THE_SS_CONFIG_FILE, sizeof(buf));
-
- f = boinc_fopen(buf, "r");
- if (!f) return;
-
- mf.init_file(f);
- XML_PARSER xp(&mf);
-
- while (mf.fgets(buf, sizeof(buf))) {
- if (parse_bool(buf, "default_ss_first", periods.Show_default_ss_first)) continue;
- if (parse_double(buf, "", periods.GFXDefaultPeriod)) continue;
- if (parse_double(buf, "", periods.GFXSciencePeriod)) continue;
- if (parse_double(buf, "", periods.GFXChangePeriod)) continue;
-
- }
- fclose(f);
-
- BOINCTRACE(_T("CScreensaver::GetDefaultDisplayPeriods: m_bShow_default_ss_first=%d, m_fGFXDefaultPeriod=%f, m_fGFXSciencePeriod=%f, m_fGFXChangePeriod=%f\n"),
- (int)periods.Show_default_ss_first, periods.GFXDefaultPeriod, periods.GFXSciencePeriod, periods.GFXChangePeriod);
-}
+ }
+#endif
+
+ // For safety, call kill_program even under Apple sandbox security
+ kill_program(graphics_application);
+ return retval;
+}
+
+
+// Terminate the project (science) graphics application
+//
+#ifdef _WIN32
+int CScreensaver::terminate_screensaver(HANDLE& graphics_application, RESULT *worker_app)
+#else
+int CScreensaver::terminate_screensaver(int& graphics_application, RESULT *worker_app)
+#endif
+{
+ int retval = 0;
+
+ if (graphics_application) {
+ // V6 Graphics
+ if (m_bScience_gfx_running) {
+ terminate_v6_screensaver(graphics_application);
+ }
+ }
+ return retval;
+}
+
+
+// Launch the default graphics application
+//
+#ifdef _WIN32
+int CScreensaver::launch_default_screensaver(char *dir_path, HANDLE& graphics_application)
+#else
+int CScreensaver::launch_default_screensaver(char *dir_path, int& graphics_application)
+#endif
+{
+ int retval = 0;
+ int num_args;
+
+#ifdef __APPLE__
+ // For sandbox security, use gfx_switcher to launch default
+ // gfx app as user boinc_master and group boinc_master.
+ char* argv[6];
+
+ argv[0] = "gfx_switcher";
+ argv[1] = "-default_gfx";
+ argv[2] = THE_DEFAULT_SS_EXECUTABLE; // Will be changed by gfx_switcher
+ argv[3] = "--fullscreen";
+ argv[4] = 0;
+ argv[5] = 0;
+ if (!m_bConnected) {
+ BOINCTRACE(_T("launch_default_screensaver using --retry_connect argument\n"));
+ argv[4] = "--retry_connect";
+ num_args = 5;
+ } else {
+ num_args = 4;
+ }
+
+ retval = run_program(
+ dir_path,
+ m_gfx_Switcher_Path,
+ num_args,
+ argv,
+ 0,
+ graphics_application
+ );
+
+ BOINCTRACE(_T("launch_default_screensaver returned %d\n"), retval);
+
+#else
+ // For unknown reasons, the graphics application exits with
+ // "RegisterProcess failed (error = -50)" unless we pass its
+ // full path twice in the argument list to execv on Macs.
+
+ char* argv[4];
+ char full_path[1024];
+
+ strlcpy(full_path, dir_path, sizeof(full_path));
+ strlcat(full_path, PATH_SEPARATOR, sizeof(full_path));
+ strlcat(full_path, THE_DEFAULT_SS_EXECUTABLE, sizeof(full_path));
+
+ argv[0] = full_path; // not used
+ argv[1] = "--fullscreen";
+ argv[2] = 0;
+ argv[3] = 0;
+ if (!m_bConnected) {
+ BOINCTRACE(_T("launch_default_screensaver using --retry_connect argument\n"));
+ argv[2] = "--retry_connect";
+ num_args = 3;
+ } else {
+ num_args = 2;
+ }
+
+ retval = run_program(
+ dir_path,
+ full_path,
+ num_args,
+ argv,
+ 0,
+ graphics_application
+ );
+
+ BOINCTRACE(_T("launch_default_screensaver %s returned %d\n"), full_path, retval);
+
+#endif
+ return retval;
+}
+
+
+// Terminate the default graphics application
+//
+#ifdef _WIN32
+int CScreensaver::terminate_default_screensaver(HANDLE& graphics_application)
+#else
+int CScreensaver::terminate_default_screensaver(int& graphics_application)
+#endif
+{
+ int retval = 0;
+
+ if (! graphics_application) return 0;
+ retval = terminate_v6_screensaver(graphics_application);
+ return retval;
+}
+
+
+// If we cannot connect to the core client:
+// - we retry connecting every 10 seconds
+// - we launch the default graphics application with the argument --retry_connect, so
+// it will continue running and will also retry connecting every 10 seconds.
+//
+// If we successfully connected to the core client, launch the default graphics application
+// without the argument --retry_connect. If it can't connect, it will return immediately
+// with the exit code ERR_CONNECT. In that case, we assume it was blocked by a firewall
+// and so we run only project (science) graphics.
+
+#ifdef _WIN32
+DWORD WINAPI CScreensaver::DataManagementProc()
+#else
+void *CScreensaver::DataManagementProc()
+#endif
+{
+ int retval = 0;
+ int suspend_reason = 0;
+ RESULT* theResult = NULL;
+ RESULT* graphics_app_result_ptr = NULL;
+ RESULT previous_result;
+ // previous_result_ptr = &previous_result when previous_result is valid, else NULL
+ RESULT* previous_result_ptr = NULL;
+ int iResultCount = 0;
+ int iIndex = 0;
+ double default_phase_start_time = 0.0;
+ double science_phase_start_time = 0.0;
+ double last_change_time = 0.0;
+ // If we run default screensaver during science phase because no science graphics
+ // are available, then shorten next default graphics phase by that much time.
+ double default_saver_start_time_in_science_phase = 0.0;
+ double default_saver_duration_in_science_phase = 0.0;
+
+ SS_PHASE ss_phase = DEFAULT_SS_PHASE;
+ bool switch_to_default_gfx = false;
+ bool killing_default_gfx = false;
+ int exit_status = 0;
+
+ char* default_ss_dir_path = NULL;
+ char full_path[1024];
+
+ BOINCTRACE(_T("CScreensaver::DataManagementProc - Display screen saver loading message\n"));
+ SetError(TRUE, SCRAPPERR_BOINCSCREENSAVERLOADING); // No GFX App is running: show moving BOINC logo
+#ifdef _WIN32
+ m_tThreadCreateTime = time(0);
+
+ // Set the starting point for iterating through the results
+ m_iLastResultShown = 0;
+ m_tLastResultChangeTime = 0;
+#endif
+
+ m_bDefault_ss_exists = false;
+ m_bScience_gfx_running = false;
+ m_bDefault_gfx_running = false;
+ m_bShow_default_ss_first = false;
+
+#ifdef __APPLE__
+ default_ss_dir_path = "/Library/Application Support/BOINC Data";
+#else
+ default_ss_dir_path = (char*)m_strBOINCInstallDirectory.c_str();
+#endif
+
+ strlcpy(full_path, default_ss_dir_path, sizeof(full_path));
+ strlcat(full_path, PATH_SEPARATOR, sizeof(full_path));
+ strlcat(full_path, THE_DEFAULT_SS_EXECUTABLE, sizeof(full_path));
+
+ if (boinc_file_exists(full_path)) {
+ m_bDefault_ss_exists = true;
+ } else {
+ SetError(TRUE, SCRAPPERR_CANTLAUNCHDEFAULTGFXAPP); // No GFX App is running: show moving BOINC logo
+ }
+
+ if (m_bDefault_ss_exists && m_bShow_default_ss_first) {
+ ss_phase = DEFAULT_SS_PHASE;
+ default_phase_start_time = dtime();
+ science_phase_start_time = 0;
+ switch_to_default_gfx = true;
+ } else {
+ ss_phase = SCIENCE_SS_PHASE;
+ default_phase_start_time = 0;
+ science_phase_start_time = dtime();
+ }
+
+ while (true) {
+
+ for (int i = 0; i < 4; i++) {
+ // ***
+ // *** Things that should be run frequently.
+ // *** 4 times per second.
+ // ***
+
+ // Are we supposed to exit the screensaver?
+ if (m_bQuitDataManagementProc) { // If main thread has requested we exit
+ BOINCTRACE(_T("CScreensaver::DataManagementProc - Thread told to stop\n"));
+ if (m_hGraphicsApplication || graphics_app_result_ptr) {
+ if (m_bDefault_gfx_running) {
+ BOINCTRACE(_T("CScreensaver::DataManagementProc - Terminating default screensaver\n"));
+ terminate_default_screensaver(m_hGraphicsApplication);
+ } else {
+ BOINCTRACE(_T("CScreensaver::DataManagementProc - Terminating screensaver\n"));
+ terminate_screensaver(m_hGraphicsApplication, graphics_app_result_ptr);
+ }
+ graphics_app_result_ptr = NULL;
+ previous_result_ptr = NULL;
+ m_hGraphicsApplication = 0;
+ }
+ BOINCTRACE(_T("CScreensaver::DataManagementProc - Stopping...\n"));
+ m_bDataManagementProcStopped = true; // Tell main thread that we exited
+ return 0; // Exit the thread
+ }
+ boinc_sleep(0.25);
+ }
+
+ // ***
+ // *** Things that should be run less frequently.
+ // *** 1 time per second.
+ // ***
+
+ // Blank screen saver?
+ if ((m_dwBlankScreen) && (time(0) > m_dwBlankTime) && (m_dwBlankTime > 0)) {
+ BOINCTRACE(_T("CScreensaver::DataManagementProc - Time to blank\n"));
+ SetError(FALSE, SCRAPPERR_SCREENSAVERBLANKED); // Blanked - hide moving BOINC logo
+ m_bQuitDataManagementProc = true;
+ continue; // Code above will exit the thread
+ }
+
+ BOINCTRACE(_T("CScreensaver::DataManagementProc - ErrorMode = '%d', ErrorCode = '%x'\n"), m_bErrorMode, m_hrError);
+
+ if (!m_bConnected) {
+ HandleRPCError();
+ }
+
+ if (m_bConnected) {
+ // Do we need to get the core client state?
+ if (m_bResetCoreState) {
+ // Try and get the current state of the CC
+ retval = rpc->get_state(state);
+ if (retval) {
+ // CC may not yet be running
+ HandleRPCError();
+ continue;
+ } else {
+ m_bResetCoreState = false;
+ }
+ }
+
+ // Update our task list
+ retval = rpc->get_screensaver_tasks(suspend_reason, results);
+ if (retval) {
+ // rpc call returned error
+ HandleRPCError();
+ m_bResetCoreState = true;
+ continue;
+ }
+ } else {
+ results.clear();
+ }
+
+ // Time to switch to default graphics phase?
+ if (m_bDefault_ss_exists && (ss_phase == SCIENCE_SS_PHASE) && (m_fGFXDefaultPeriod > 0)) {
+ if (science_phase_start_time && ((dtime() - science_phase_start_time) > m_fGFXSciencePeriod)) {
+ if (!m_bDefault_gfx_running) {
+ switch_to_default_gfx = true;
+ }
+ ss_phase = DEFAULT_SS_PHASE;
+ default_phase_start_time = dtime();
+ science_phase_start_time = 0;
+ if (m_bDefault_gfx_running && default_saver_start_time_in_science_phase) {
+ // Remember how long default graphics ran during science phase
+ default_saver_duration_in_science_phase += (dtime() - default_saver_start_time_in_science_phase);
+ }
+ default_saver_start_time_in_science_phase = 0;
+ }
+ }
+
+ // Time to switch to science graphics phase?
+ if ((ss_phase == DEFAULT_SS_PHASE) && m_bConnected && (m_fGFXSciencePeriod > 0)) {
+ if (default_phase_start_time &&
+ ((dtime() - default_phase_start_time + default_saver_duration_in_science_phase)
+ > m_fGFXDefaultPeriod)) {
+ // BOINCTRACE(_T("CScreensaver::Ending Default phase: now=%f, default_phase_start_time=%f, default_saver_duration_in_science_phase=%f\n"),
+ // dtime(), default_phase_start_time, default_saver_duration_in_science_phase);
+ ss_phase = SCIENCE_SS_PHASE;
+ default_phase_start_time = 0;
+ default_saver_duration_in_science_phase = 0;
+ science_phase_start_time = dtime();
+ if (m_bDefault_gfx_running) {
+ default_saver_start_time_in_science_phase = science_phase_start_time;
+ }
+ switch_to_default_gfx = false;
+ }
+ }
+
+ // Core client suspended?
+ if (suspend_reason && !(suspend_reason & (SUSPEND_REASON_CPU_THROTTLE | SUSPEND_REASON_CPU_USAGE))) {
+ if (!m_bDefault_gfx_running) {
+ SetError(TRUE, m_hrError); // No GFX App is running: show moving BOINC logo
+ if (m_bDefault_ss_exists) {
+ switch_to_default_gfx = true;
+ }
+ }
+ }
+
+ if (switch_to_default_gfx) {
+ if (m_bScience_gfx_running) {
+ if (m_hGraphicsApplication || previous_result_ptr) {
+ // use previous_result_ptr because graphics_app_result_ptr may no longer be valid
+ terminate_screensaver(m_hGraphicsApplication, previous_result_ptr);
+ if (m_hGraphicsApplication == 0) {
+ graphics_app_result_ptr = NULL;
+ m_bScience_gfx_running = false;
+ } else {
+ // HasProcessExited() test will clear m_hGraphicsApplication and graphics_app_result_ptr
+ }
+ previous_result_ptr = NULL;
+ }
+ } else {
+ if (!m_bDefault_gfx_running) {
+ switch_to_default_gfx = false;
+ retval = launch_default_screensaver(default_ss_dir_path, m_hGraphicsApplication);
+ if (retval) {
+ m_hGraphicsApplication = 0;
+ previous_result_ptr = NULL;
+ graphics_app_result_ptr = NULL;
+ m_bDefault_gfx_running = false;
+ SetError(TRUE, SCRAPPERR_CANTLAUNCHDEFAULTGFXAPP); // No GFX App is running: show moving BOINC logo
+ } else {
+ m_bDefault_gfx_running = true;
+ if (ss_phase == SCIENCE_SS_PHASE) {
+ default_saver_start_time_in_science_phase = dtime();
+ }
+ SetError(FALSE, SCRAPPERR_BOINCSCREENSAVERLOADING); // A GFX App is running: hide moving BOINC logo
+ }
+ }
+ }
+ }
+
+ if ((ss_phase == SCIENCE_SS_PHASE) && !switch_to_default_gfx) {
+
+#if SIMULATE_NO_GRAPHICS /* FOR TESTING */
+
+ if (!m_bDefault_gfx_running) {
+ SetError(TRUE, m_hrError); // No GFX App is running: show moving BOINC logo
+ if (m_bDefault_ss_exists) {
+ switch_to_default_gfx = true;
+ }
+ }
+
+#else /* NORMAL OPERATION */
+
+ if (m_bScience_gfx_running) {
+ // Is the current graphics app's associated task still running?
+
+ if ((m_hGraphicsApplication) || (graphics_app_result_ptr)) {
+ iResultCount = (int)results.results.size();
+ graphics_app_result_ptr = NULL;
+
+ // Find the current task in the new results vector (if it still exists)
+ for (iIndex = 0; iIndex < iResultCount; iIndex++) {
+ theResult = results.results.at(iIndex);
+
+ if (is_same_task(theResult, previous_result_ptr)) {
+ graphics_app_result_ptr = theResult;
+ previous_result = *theResult;
+ previous_result_ptr = &previous_result;
+ break;
+ }
+ }
+
+ // V6 graphics only: if worker application has stopped running, terminate_screensaver
+ if ((graphics_app_result_ptr == NULL) && (m_hGraphicsApplication != 0)) {
+ if (previous_result_ptr) {
+ BOINCTRACE(_T("CScreensaver::DataManagementProc - %s finished\n"),
+ previous_result.graphics_exec_path
+ );
+ }
+ terminate_screensaver(m_hGraphicsApplication, previous_result_ptr);
+ previous_result_ptr = NULL;
+ if (m_hGraphicsApplication == 0) {
+ graphics_app_result_ptr = NULL;
+ m_bScience_gfx_running = false;
+ // Save previous_result and previous_result_ptr for get_random_graphics_app() call
+ } else {
+ // HasProcessExited() test will clear m_hGraphicsApplication and graphics_app_result_ptr
+ }
+ }
+
+ if (last_change_time && (m_fGFXChangePeriod > 0) && ((dtime() - last_change_time) > m_fGFXChangePeriod) ) {
+ if (count_active_graphic_apps(results, previous_result_ptr) > 0) {
+ if (previous_result_ptr) {
+ BOINCTRACE(_T("CScreensaver::DataManagementProc - time to change: %s / %s\n"),
+ previous_result.name, previous_result.graphics_exec_path
+ );
+ }
+ terminate_screensaver(m_hGraphicsApplication, graphics_app_result_ptr);
+ if (m_hGraphicsApplication == 0) {
+ graphics_app_result_ptr = NULL;
+ m_bScience_gfx_running = false;
+ // Save previous_result and previous_result_ptr for get_random_graphics_app() call
+ } else {
+ // HasProcessExited() test will clear m_hGraphicsApplication and graphics_app_result_ptr
+ }
+ }
+ last_change_time = dtime();
+ }
+ }
+ } // End if (m_bScience_gfx_running)
+
+ // If no current graphics app, pick an active task at random and launch its graphics app
+ if ((m_bDefault_gfx_running || (m_hGraphicsApplication == 0)) && (graphics_app_result_ptr == NULL)) {
+ graphics_app_result_ptr = get_random_graphics_app(results, previous_result_ptr);
+ previous_result_ptr = NULL;
+
+ if (graphics_app_result_ptr) {
+ if (m_bDefault_gfx_running) {
+ terminate_default_screensaver(m_hGraphicsApplication);
+ killing_default_gfx = true;
+ // Remember how long default graphics ran during science phase
+ if (default_saver_start_time_in_science_phase) {
+ default_saver_duration_in_science_phase += (dtime() - default_saver_start_time_in_science_phase);
+ //BOINCTRACE(_T("CScreensaver::During Science phase: now=%f, default_saver_start_time=%f, default_saver_duration=%f\n"),
+ // dtime(), default_saver_start_time_in_science_phase, default_saver_duration_in_science_phase);
+ }
+ default_saver_start_time_in_science_phase = 0;
+ // HasProcessExited() test will clear m_hGraphicsApplication and graphics_app_result_ptr
+ } else {
+ retval = launch_screensaver(graphics_app_result_ptr, m_hGraphicsApplication);
+ if (retval) {
+ m_hGraphicsApplication = 0;
+ previous_result_ptr = NULL;
+ graphics_app_result_ptr = NULL;
+ m_bScience_gfx_running = false;
+ } else {
+ SetError(FALSE, SCRAPPERR_BOINCSCREENSAVERLOADING); // A GFX App is running: hide moving BOINC logo
+ last_change_time = dtime();
+ m_bScience_gfx_running = true;
+ // Make a local copy of current result, since original pointer
+ // may have been freed by the time we perform later tests
+ previous_result = *graphics_app_result_ptr;
+ previous_result_ptr = &previous_result;
+ if (previous_result_ptr) {
+ BOINCTRACE(_T("CScreensaver::DataManagementProc - launching %s\n"),
+ previous_result.graphics_exec_path
+ );
+ }
+ }
+ }
+ } else {
+ if (!m_bDefault_gfx_running) {
+ // We can't run a science graphics app, so run the default graphics if available
+ SetError(TRUE, m_hrError);
+ if (m_bDefault_ss_exists) {
+ switch_to_default_gfx = true;
+ }
+ }
+
+ } // End if no science graphics available
+ } // End if no current science graphics app is running
+
+#endif // ! SIMULATE_NO_GRAPHICS
+
+ if (switch_to_default_gfx) {
+ switch_to_default_gfx = false;
+ if (!m_bDefault_gfx_running) {
+ retval = launch_default_screensaver(default_ss_dir_path, m_hGraphicsApplication);
+ if (retval) {
+ m_hGraphicsApplication = 0;
+ previous_result_ptr = NULL;
+ graphics_app_result_ptr = NULL;
+ m_bDefault_gfx_running = false;
+ SetError(TRUE, SCRAPPERR_CANTLAUNCHDEFAULTGFXAPP); // No GFX App is running: show BOINC logo
+ } else {
+ m_bDefault_gfx_running = true;
+ default_saver_start_time_in_science_phase = dtime();
+ SetError(FALSE, SCRAPPERR_BOINCSCREENSAVERLOADING); // Default GFX App is running: hide moving BOINC logo
+ }
+ }
+ }
+ } // End if ((ss_phase == SCIENCE_SS_PHASE) && !switch_to_default_gfx)
+
+
+
+ // Is the graphics app still running?
+ if (m_hGraphicsApplication) {
+ if (HasProcessExited(m_hGraphicsApplication, exit_status)) {
+ // Something has happened to the previously selected screensaver
+ // application. Start a different one.
+ BOINCTRACE(_T("CScreensaver::DataManagementProc - Graphics application isn't running, start a new one.\n"));
+ if (m_bDefault_gfx_running) {
+ // If we were able to connect to core client but gfx app can't, don't use it.
+ BOINCTRACE(_T("CScreensaver::DataManagementProc - Default graphics application exited with code %d.\n"), exit_status);
+ if (!killing_default_gfx) { // If this is an unexpected exit
+ if (exit_status == DEFAULT_GFX_CANT_CONNECT) {
+ SetError(TRUE, SCRAPPERR_DEFAULTGFXAPPCANTCONNECT); // No GFX App is running: show moving BOINC logo
+ } else {
+ SetError(TRUE, SCRAPPERR_DEFAULTGFXAPPCRASHED); // No GFX App is running: show moving BOINC logo
+ }
+ m_bDefault_ss_exists = false;
+ ss_phase = SCIENCE_SS_PHASE;
+ }
+ killing_default_gfx = false;
+ }
+ SetError(TRUE, SCRAPPERR_BOINCNOGRAPHICSAPPSEXECUTING); // No GFX App is running: show moving BOINC logo
+ m_hGraphicsApplication = 0;
+ graphics_app_result_ptr = NULL;
+ m_bDefault_gfx_running = false;
+ m_bScience_gfx_running = false;
+ continue;
+ }
+ }
+ } // end while(true)
+}
+
+
+#ifdef _WIN32
+BOOL CScreensaver::HasProcessExited(HANDLE pid_handle, int &exitCode) {
+ unsigned long status = 1;
+ if (GetExitCodeProcess(pid_handle, &status)) {
+ if (status == STILL_ACTIVE) {
+ exitCode = 0;
+ return false;
+ }
+ }
+ exitCode = (int)status;
+ return true;
+}
+#else
+bool CScreensaver::HasProcessExited(pid_t pid, int &exitCode) {
+ int status;
+ pid_t p;
+
+ p = waitpid(pid, &status, WNOHANG);
+ exitCode = WEXITSTATUS(status);
+ if (p == pid) return true; // process has exited
+ if (p == -1) return true; // PID doesn't exist
+ exitCode = 0;
+ return false;
+}
+#endif
+
+
+void CScreensaver::GetDefaultDisplayPeriods(struct ss_periods &periods)
+{
+ char* default_data_dir_path = NULL;
+ char buf[1024];
+ FILE* f;
+ MIOFILE mf;
+
+ periods.GFXDefaultPeriod = GFX_DEFAULT_PERIOD;
+ periods.GFXSciencePeriod = GFX_SCIENCE_PERIOD;
+ periods.GFXChangePeriod = GFX_CHANGE_PERIOD;
+ periods.Show_default_ss_first = false;
+
+#ifdef __APPLE__
+ default_data_dir_path = "/Library/Application Support/BOINC Data";
+#else
+ default_data_dir_path = (char*)m_strBOINCDataDirectory.c_str();
+#endif
+
+ strlcpy(buf, default_data_dir_path, sizeof(buf));
+ strlcat(buf, PATH_SEPARATOR, sizeof(buf));
+ strlcat(buf, THE_SS_CONFIG_FILE, sizeof(buf));
+
+ f = boinc_fopen(buf, "r");
+ if (!f) return;
+
+ mf.init_file(f);
+ XML_PARSER xp(&mf);
+
+ while (mf.fgets(buf, sizeof(buf))) {
+ if (parse_bool(buf, "default_ss_first", periods.Show_default_ss_first)) continue;
+ if (parse_double(buf, "", periods.GFXDefaultPeriod)) continue;
+ if (parse_double(buf, "", periods.GFXSciencePeriod)) continue;
+ if (parse_double(buf, "", periods.GFXChangePeriod)) continue;
+
+ }
+ fclose(f);
+
+ BOINCTRACE(_T("CScreensaver::GetDefaultDisplayPeriods: m_bShow_default_ss_first=%d, m_fGFXDefaultPeriod=%f, m_fGFXSciencePeriod=%f, m_fGFXChangePeriod=%f\n"),
+ (int)periods.Show_default_ss_first, periods.GFXDefaultPeriod, periods.GFXSciencePeriod, periods.GFXChangePeriod);
+}
diff --git a/clientscr/screensaver_win.h b/clientscr/screensaver_win.h
index c5eb36ed7f..ea1c0ead56 100644
--- a/clientscr/screensaver_win.h
+++ b/clientscr/screensaver_win.h
@@ -196,7 +196,6 @@ protected:
BOOL m_bResetCoreState;
bool m_bQuitDataManagementProc;
bool m_bDataManagementProcStopped;
- bool m_bV5_GFX_app_is_running;
int m_iLastResultShown;
time_t m_tLastResultChangeTime;
time_t m_tThreadCreateTime;