|
From: Tapio V. <aa...@us...> - 2009-10-29 22:06:47
|
Module: performous
Branch: master
Commit: c52eb54050375c73ea973019eb057146e35a584a
Author: Tapio Vierros <tap...@gm...>
Date: Thu Oct 29 23:49:41 2009 +0200
New class for handling random backgrounds for songs that haven't their own.
---
game/backgrounds.cc | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++
game/backgrounds.hh | 53 ++++++++++++++++++++++++++++++++++++
2 files changed, 127 insertions(+), 0 deletions(-)
diff --git a/game/backgrounds.cc b/game/backgrounds.cc
new file mode 100644
index 0000000..14816f8
--- /dev/null
+++ b/game/backgrounds.cc
@@ -0,0 +1,74 @@
+#include "backgrounds.hh"
+
+#include "configuration.hh"
+#include "fs.hh"
+
+#include <boost/bind.hpp>
+#include <boost/format.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/regex.hpp>
+#include <algorithm>
+#include <iostream>
+#include <sstream>
+#include <stdexcept>
+#include <cstdlib>
+
+void Backgrounds::reload() {
+ if (m_loading) return;
+ // Copy backgrounddirs from config into m_bgdirs
+ ConfigItem::StringList const& sd = config["system/path_backgrounds"].sl();
+ m_bgs.clear();
+ std::transform(sd.begin(), sd.end(), std::inserter(m_bgdirs, m_bgdirs.end()), pathMangle);
+ // Run loading thread
+ m_loading = true;
+ m_thread.reset(new boost::thread(boost::bind(&Backgrounds::reload_internal, boost::ref(*this))));
+}
+
+void Backgrounds::reload_internal() {
+ {
+ boost::mutex::scoped_lock l(m_mutex);
+ m_bgs.clear();
+ m_dirty = true;
+ }
+ for (BGDirs::const_iterator it = m_bgdirs.begin(); m_loading && it != m_bgdirs.end(); ++it) {
+ if (!fs::is_directory(*it)) { std::cout << ">>> Not scanning: " << *it << " (no such directory)" << std::endl; continue; }
+ std::cout << ">>> Scanning " << *it << " (for backgrounds)" << std::endl;
+ size_t count = m_bgs.size();
+ reload_internal(*it);
+ size_t diff = m_bgs.size() - count;
+ if (diff > 0 && m_loading) std::cout << diff << " backgrounds loaded" << std::endl;
+ }
+ m_loading = false;
+ {
+ boost::mutex::scoped_lock l(m_mutex);
+ random_shuffle(m_bgs.begin(), m_bgs.end());
+ m_dirty = false;
+ m_bgiter = 0;
+ }
+}
+
+void Backgrounds::reload_internal(fs::path const& parent) {
+ namespace fs = fs;
+ if (std::distance(parent.begin(), parent.end()) > 20) { std::cout << ">>> Not scanning: " << parent.string() << " (maximum depth reached, possibly due to cyclic symlinks)" << std::endl; return; }
+ try {
+ boost::regex expression("(.*\\.(png|jpeg|jpg|svg|bmp|gif))$", boost::regex_constants::icase);
+ boost::cmatch match;
+ for (fs::directory_iterator dirIt(parent), dirEnd; m_loading && dirIt != dirEnd; ++dirIt) {
+ fs::path p = dirIt->path();
+ if (fs::is_directory(p)) { reload_internal(p); continue; }
+ std::string name = p.leaf(); // File basename
+ std::string path = p.directory_string(); // Path without filename
+ path.erase(path.size() - name.size());
+ if (!regex_match(name.c_str(), match, expression)) continue;
+ {
+ boost::mutex::scoped_lock l(m_mutex);
+ m_bgs.push_back(path + name);
+ m_dirty = true;
+ }
+ }
+ } catch (std::exception const& e) {
+ std::cout << "Error accessing " << parent << std::endl;
+ }
+}
+
+
diff --git a/game/backgrounds.hh b/game/backgrounds.hh
new file mode 100644
index 0000000..5d85da6
--- /dev/null
+++ b/game/backgrounds.hh
@@ -0,0 +1,53 @@
+#pragma once
+
+#include "animvalue.hh"
+#include "fs.hh"
+#include "song.hh"
+#include <boost/shared_ptr.hpp>
+#include <boost/scoped_ptr.hpp>
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/thread.hpp>
+#include <set>
+#include <vector>
+
+/// songs class for songs screen
+class Backgrounds: boost::noncopyable {
+ public:
+ /// constructor
+ Backgrounds(): m_bgiter(0), m_dirty(false), m_loading(false)
+ {
+ std::cout << "BACKGROUNDS!" << std::endl;
+ reload();
+ }
+ ~Backgrounds() {
+ m_loading = false; // Terminate loading if currently in progress
+ m_thread->join();
+ }
+ /// reloads backgrounds list
+ void reload();
+ /// array access
+ std::string& operator[](std::size_t pos) { return m_bgs.at(pos); }
+ /// number of backgrounds
+ int size() const { return m_bgs.size(); };
+ /// true if empty
+ int empty() const { return m_bgs.empty(); };
+ /// returns random background
+ std::string getRandom() {
+ if (!m_bgs.empty()) return m_bgs.at((++m_bgiter) % m_bgs.size());
+ else return "";
+ }
+
+ private:
+ typedef std::set<fs::path> BGDirs;
+ typedef std::vector<std::string> BGVector;
+ BGDirs m_bgdirs;
+ BGVector m_bgs;
+ int m_bgiter;
+ void reload_internal();
+ void reload_internal(fs::path const& p);
+ volatile bool m_dirty;
+ volatile bool m_loading;
+ boost::scoped_ptr<boost::thread> m_thread;
+ mutable boost::mutex m_mutex;
+};
+
|