Revert "Load audio earlier in the process. Might save us some time"
[supertux.git] / src / supertux / main.cpp
index 5fc1db1..1cfba9c 100644 (file)
 #include <version.h>
 
 #include <SDL_image.h>
-#include <physfs.h>
-#include <iostream>
-#include <binreloc.h>
-#include <tinygettext/log.hpp>
 #include <boost/format.hpp>
+#include <boost/optional.hpp>
+#include <iostream>
+#include <physfs.h>
 #include <stdio.h>
+#include <tinygettext/log.hpp>
 extern "C" {
 #include <findlocale.h>
 }
@@ -64,8 +64,8 @@ public:
     g_config.reset(new Config);
     try {
       g_config->load();
-    } 
-    catch(const std::exception& e) 
+    }
+    catch(const std::exception& e)
     {
       log_info << "Couldn't load config file: " << e.what() << ", using default settings" << std::endl;
     }
@@ -83,7 +83,7 @@ public:
     {
       g_config->save();
     }
-    g_config.reset();  
+    g_config.reset();
   }
 };
 
@@ -114,99 +114,116 @@ Main::init_tinygettext()
 
 class PhysfsSubsystem
 {
+private:
+  boost::optional<std::string> m_forced_datadir;
+  boost::optional<std::string> m_forced_userdir;
+
 public:
-  PhysfsSubsystem(const char* argv0)
+  PhysfsSubsystem(const char* argv0,
+                  boost::optional<std::string> forced_datadir,
+                  boost::optional<std::string> forced_userdir) :
+    m_forced_datadir(forced_datadir),
+    m_forced_userdir(forced_userdir)
   {
-    if(!PHYSFS_init(argv0)) {
+    if (!PHYSFS_init(argv0))
+    {
       std::stringstream msg;
       msg << "Couldn't initialize physfs: " << PHYSFS_getLastError();
       throw std::runtime_error(msg.str());
     }
+    else
+    {
+      // allow symbolic links
+      PHYSFS_permitSymbolicLinks(1);
 
-    // allow symbolic links
-    PHYSFS_permitSymbolicLinks(1);
-
-    // Initialize physfs (this is a slightly modified version of
-    // PHYSFS_setSaneConfig)
-    const char *env_writedir;
-    std::string writedir;
-
-    if ((env_writedir = getenv("SUPERTUX2_USER_DIR")) != NULL) {
-      writedir = env_writedir;
-      if(!PHYSFS_setWriteDir(writedir.c_str())) {
-        std::ostringstream msg;
-        msg << "Failed to use configuration directory '"
-            <<  writedir << "': " << PHYSFS_getLastError();
-        throw std::runtime_error(msg.str());
-      }
+      find_userdir();
+      find_datadir();
+    }
+  }
 
-    } else {
-      std::string userdir = PHYSFS_getUserDir();
-
-      // Set configuration directory
-      writedir = userdir + WRITEDIR_NAME;
-      if(!PHYSFS_setWriteDir(writedir.c_str())) {
-        // try to create the directory
-        if(!PHYSFS_setWriteDir(userdir.c_str()) || !PHYSFS_mkdir(WRITEDIR_NAME)) {
-          std::ostringstream msg;
-          msg << "Failed creating configuration directory '"
-              << writedir << "': " << PHYSFS_getLastError();
-          throw std::runtime_error(msg.str());
-        }
-
-        if(!PHYSFS_setWriteDir(writedir.c_str())) {
-          std::ostringstream msg;
-          msg << "Failed to use configuration directory '"
-              <<  writedir << "': " << PHYSFS_getLastError();
-          throw std::runtime_error(msg.str());
-        }
-      }
+  void find_datadir()
+  {
+    std::string datadir;
+    if (m_forced_datadir)
+    {
+      datadir = *m_forced_datadir;
     }
-    PHYSFS_addToSearchPath(writedir.c_str(), 0);
-
-    // when started from source dir...
-    char* base_path = SDL_GetBasePath();
-    std::string dir = base_path;
-    SDL_free(base_path);
-
-    if (dir[dir.length() - 1] != '/')
-      dir += "/";
-    dir += "data";
-    std::string testfname = dir;
-    testfname += "/credits.txt";
-    bool sourcedir = false;
-    FILE* f = fopen(testfname.c_str(), "r");
-    if(f) {
-      fclose(f);
-      if(!PHYSFS_addToSearchPath(dir.c_str(), 1)) {
-        log_warning << "Couldn't add '" << dir << "' to physfs searchpath: " << PHYSFS_getLastError() << std::endl;
-      } else {
-        sourcedir = true;
+    else if (const char* env_datadir = getenv("SUPERTUX2_DATA_DIR"))
+    {
+      datadir = env_datadir;
+    }
+    else
+    {
+      // check if we run from source dir
+      char* basepath_c = SDL_GetBasePath();
+      std::string basepath = basepath_c;
+      SDL_free(basepath_c);
+
+      datadir = FileSystem::join(basepath, "data");
+      std::string testfname = FileSystem::join(datadir, "credits.txt");
+      if (!FileSystem::exists(testfname))
+      {
+        // if the game is not run from the source directory, try to find
+        // the global install location
+        datadir = datadir.substr(0, datadir.rfind(INSTALL_SUBDIR_BIN));
+        datadir = FileSystem::join(datadir, INSTALL_SUBDIR_SHARE);
       }
     }
 
-    if(!sourcedir) {
-      std::string datadir = PHYSFS_getBaseDir();
-      datadir = datadir.substr(0, datadir.rfind(INSTALL_SUBDIR_BIN));
-      datadir += "/" INSTALL_SUBDIR_SHARE;
-#ifdef ENABLE_BINRELOC
-
-      char* dir;
-      br_init (NULL);
-      dir = br_find_data_dir(datadir.c_str());
-      datadir = dir;
-      free(dir);
+    if (!PHYSFS_addToSearchPath(datadir.c_str(), 1))
+    {
+      log_warning << "Couldn't add '" << datadir << "' to physfs searchpath: " << PHYSFS_getLastError() << std::endl;
+    }
+  }
 
+  void find_userdir()
+  {
+    std::string userdir;
+    if (m_forced_userdir)
+    {
+      userdir = *m_forced_userdir;
+    }
+    else if (const char* env_userdir = getenv("SUPERTUX2_USER_DIR"))
+    {
+      userdir = env_userdir;
+    }
+    else
+    {
+      std::string physfs_userdir = PHYSFS_getUserDir();
+#ifdef _WIN32
+      userdir = FileSystem::join(physfs_userdir, PACKAGE_NAME);
+#else
+      userdir = FileSystem::join(physfs_userdir, "." PACKAGE_NAME);
 #endif
-      if(!PHYSFS_addToSearchPath(datadir.c_str(), 1)) {
-        log_warning << "Couldn't add '" << datadir << "' to physfs searchpath: " << PHYSFS_getLastError() << std::endl;
-      }
     }
 
-    //show search Path
+    if (!FileSystem::is_directory(userdir))
+    {
+      FileSystem::mkdir(userdir);
+      log_info << "Created SuperTux userdir: " << userdir << std::endl;
+    }
+
+    if (!PHYSFS_setWriteDir(userdir.c_str()))
+    {
+      std::ostringstream msg;
+      msg << "Failed to use userdir directory '"
+          <<  userdir << "': " << PHYSFS_getLastError();
+      throw std::runtime_error(msg.str());
+    }
+
+    PHYSFS_addToSearchPath(userdir.c_str(), 0);
+  }
+
+  void print_search_path()
+  {
+    const char* writedir = PHYSFS_getWriteDir();
+    log_info << "PhysfsWritedDir: " << (writedir ? writedir : "(null)") << std::endl;
+    log_info << "PhysfsSearchPath:" << std::endl;
     char** searchpath = PHYSFS_getSearchPath();
-    for(char** i = searchpath; *i != NULL; i++)
-      log_info << "[" << *i << "] is in the search path" << std::endl;
+    for(char** i = searchpath; *i != NULL; ++i)
+    {
+      log_info << "  " << *i << std::endl;
+    }
     PHYSFS_freeList(searchpath);
   }
 
@@ -283,14 +300,13 @@ Main::launch_game()
   ConsoleBuffer console_buffer;
 
   timelog("controller");
-  InputManager input_manager;
+  InputManager input_manager(g_config->keyboard_config, g_config->joystick_config);
 
   timelog("commandline");
 
   timelog("video");
   std::unique_ptr<VideoSystem> video_system = VideoSystem::create(g_config->video);
-  DrawingContext context(video_system->get_renderer(),
-                         video_system->get_lightmap());
+  DrawingContext context(*video_system);
   init_video();
 
   timelog("audio");
@@ -309,8 +325,7 @@ Main::launch_game()
   Resources resources;
 
   timelog("addons");
-  AddonManager addon_manager;
-  addon_manager.load_addons();
+  AddonManager addon_manager("addons", g_config->addons);
 
   timelog(0);
 
@@ -368,10 +383,6 @@ Main::run(int argc, char** argv)
   {
     CommandLineArguments args;
 
-    // Do this before pre_parse_commandline, because --help now shows the
-    // default user data dir.
-    PhysfsSubsystem physfs_subsystem(argv[0]);
-
     try
     {
       args.parse_args(argc, argv);
@@ -383,6 +394,9 @@ Main::run(int argc, char** argv)
       return EXIT_FAILURE;
     }
 
+    PhysfsSubsystem physfs_subsystem(argv[0], args.datadir, args.userdir);
+    physfs_subsystem.print_search_path();
+
     timelog("config");
     ConfigSubsystem config_subsystem;
     args.merge_into(*g_config);