+Core core;
+
+
+class Backend_;
+typedef boost::shared_ptr<Backend_> BackendP;
+
+class Backend_
+{
+public:
+
+ void init()
+ {
+#if defined(_WIN32) || defined(__WIN32__)
+ if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) != 0)
+#else
+ if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTTHREAD) != 0)
+#endif
+ {
+ const char* error = SDL_GetError();
+ gError.init(Error::SDL_INIT, error);
+ return; // fatal
+ }
+ else
+ {
+ char name[128];
+ SDL_VideoDriverName(name, sizeof(name));
+ logInfo << "initialized SDL; using video driver `"
+ << name << "'" << std::endl;
+ }
+
+ if (FE_Init() != 0)
+ {
+ const char* error = FE_GetError();
+ gError.init(Error::FASTEVENTS_INIT, error);
+ return; // fatal
+ }
+
+ mAlDevice = alcOpenDevice(0);
+ mAlContext = alcCreateContext(mAlDevice, 0);
+ if (!mAlDevice || !mAlContext)
+ {
+ const char* error = alcGetString(mAlDevice,alcGetError(mAlDevice));
+ gError.init(Error::OPENAL_INIT, error);
+ return;
+ }
+ else
+ {
+ alcMakeContextCurrent(mAlContext);
+ logInfo << "opened sound device `"
+ << alcGetString(mAlDevice, ALC_DEFAULT_DEVICE_SPECIFIER)
+ << "'" << std::endl;
+ }
+
+ gError.init(Error::NONE);
+ }
+
+ ~Backend_()
+ {
+ alcMakeContextCurrent(0);
+ alcDestroyContext(mAlContext);
+ alcCloseDevice(mAlDevice);
+
+ FE_Quit();
+ SDL_Quit();
+ }
+
+ static void retain()
+ {
+ if (gRetainCount++ == 0)
+ {
+ gInstance = BackendP(new Backend_);
+ gInstance->init();
+ }
+ }
+
+ static void release()
+ {
+ if (--gRetainCount == 0)
+ {
+ gInstance.reset();
+ gError.reset();
+ }
+ }
+
+ static bool check(Error& error)
+ {
+ error = gError;
+ return error.code() == Error::NONE;
+ }
+
+private:
+
+ ALCdevice* mAlDevice;
+ ALCcontext* mAlContext;
+
+ static Error gError;
+ static int gRetainCount;
+ static BackendP gInstance;
+};
+
+Error Backend_::gError(Error::UNINITIALIZED);
+int Backend_::gRetainCount = 0;
+BackendP Backend_::gInstance;
+
+
+Backend::Backend()
+{
+ Backend_::retain();
+}
+
+Backend::~Backend()
+{
+ Backend_::release();
+}
+
+bool Backend::check(Error& error)
+{
+ return Backend_::check(error);
+}