Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

adding a server/headless mode to xbmc #890

Closed
wants to merge 1 commit into from

10 participants

vajonam jmarshallnz Sascha Montellese Andres Mejia Cory Fields blades David Robins Piethein Strengholt Bas Rieter xbmcfanboy
vajonam
  • re-based with pull instead of merge
  • cleaned up indenting

this allows a headless xbmc, that can be used to keep the DB upto date, when content is added automatically using an internet pvr like sickbeard or couchpotato

jmarshallnz
Owner

Please squash down the commits and take care of any cosmetics (there's a double bracket (indent?) in 379884e.

Am I right that this is essentially a rebase of #542 ?

vajonam

cleaned up rebased and squashed commits.

jmarshall yes that is right this a rebase of #542

Sascha Montellese
Owner

First of all there's a lot of bad indentation in these changes. We use 2 spaces (not tabs) per indentation level. Furthermore you should squash the last two commits into the first. And you don't really need to put the URL to a github repo into the commit message as the commit would show up under your name anyway.

On topic I have to say I don't really like this because it's very hacky. After installing XBMC you first need to start it as usual (without the new --server command line option) to be able to configure it. So you'll need to install XBMC onto a machine which actually has a graphics card, an attached monitor etc. Once configured you can either remove the attached monitor etc or you can copy the XBMC installation onto a headless server and then run XBMC with --server there. The only other way I can see is to manually adjust guisettings.xml, which is even more hacky (and you can easily mess up the settings).

IMO that's so far from user-friendly that I can't even see it anymore.

Sascha Montellese Montellese referenced this pull request
Closed

xbmc server code #542

Andres Mejia
Collaborator

I presume a dedicated XBMC server wouldn't need various configuration settings anyway. Ideally, a server instance of XBMC should be able to run with default settings and without the need of any config file. A local admin can then adjust settings via a config file, say /etc/xbmc/*.

vajonam

I did already squash the code down. into a commit, am not sure why that isn't showing up as one commit. I have also fixed all the indents. again not sure why git hub isn't showing the squashed

regarding the actual code, I agree with most of the comments, except that you don't need a graphics card to install this package, I have tested this on a system without a card. But that being said the current dependencies on an ubuntu include a number of sdl packages.

The main point of this server is to be always available on the network so internet pvrs can notify it of changes and keep the db upto date. or to run periodic updates to keep db upto date for a multi seat install.

there is a lot of hackery in here I agree. What is the suggested approach to keep this moving forward?

Sascha Montellese
Owner

@vajonam When I look at the rebased version of e.g. Application.cpp on github I still see a lot of bad indentation. Maybe your editor/IDE hides them from you?
And my comment with the graphics card wasn't meant as "you need a graphics card to install XBMC". I meant that you need to install it on a computer which has a monitor attached (and therefore needs an (internal or external) graphics card), because you need a monitor to view xbmc's GUI to change the settings/set up sources.

@amejia1 Well first of all you need to setup video sources etc because otherwise xbmc won't be of much use to you. This is something everyone must do. Then (at least) I always need to change the settings of the default scraper because they don't match my preferences. You'll also need to setup the corresponding services (upnp, webserver, json-rpc, airplay etc) if you want to be able to access your library from somewhere else. All the other settings that I normally change are GUI related so they won't be needed but at least setting up the sources is absolutely necessary (and probably adjusting the scrapers as well).
Sure this could be done in an extra configuration file but xbmc already has a ton of configuration files so not sure if adding another one is a good call. And it still means that the user needs to manually change a text file. While this is certainly no problem for the more advanced user (and linux user) I am pretty sure that if this hits an official build, everyone will want to try out the new "server mode" and then they end up frustrated because they don't know how to set it up or it's too difficult for them.

vajonam

@Montellese, I use vi and set the tabstop and shiftinden and expandtab and then did a retab and ensured the indents a re okay. If you are mean the if-defs those indents aren't consistent in Application.cpp to being with, I have made them have no indents as per spec in the sections I touched.

@Montellese,@amejia1 assuming that mysql / shared database is used. there is no need for a sources or gui to adjust the scrapers. they can all be done from another headed machine. since all the scraper information is stored in the database anyway. Any additional sources and so on can also be configued from the headed machine again which gets added to the db. the scrapers and scanners all use this rather than the sources.xml anyway!

the only config this server needs its to point to the same mysql database, if it will make this less easy to stumble upon I can change it that the server mode can be set only by editing the advancedsettings.xml this will remove the -s or --server switch. Which would mean for now this would be just for advanced users who are familiar with using the advanced settings file.

as i see it this is what I see as the minimum requirements

  1. atleast 1 XMBC running in full GUI/Headed mode this will be used to configure.
  2. use of MySQL for a shared database
  3. ability to edit / create advancedsettings.xml for the server/headless under the userdata folder

I think this makes sense because. to use MySQL the user modified and edited an advancedsettings.xml anyway even in the headed GUI XBMC instance.

xbmc/Application.cpp
@@ -625,62 +628,67 @@ bool CApplication::Create()
}
#ifdef HAS_XRANDR
- g_xrandr.LoadCustomModeLinesToAllOutputs();
+ if (!g_application.IsServerMode())
+ {
Sascha Montellese Owner

bad indentation

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
xbmc/Application.cpp
((9 lines not shown))
#endif
// Init our DllLoaders emu env
init_emu_environ();
+ if (!g_application.IsServerMode())
+ {
Sascha Montellese Owner

bad indentation

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
xbmc/Application.cpp
((7 lines not shown))
{
- CLog::Log(LOGFATAL, "CApplication::Create: Unable to init windowing system");
- return false;
+ if (!g_Windowing.InitWindowSystem())
+ {
Sascha Montellese Owner

bad indentation

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
xbmc/Application.cpp
((30 lines not shown))
#if defined(__APPLE__) && !defined(__arm__)
// Configure and possible manually start the helper.
XBMCHelper::GetInstance().Configure();
#endif
+ if (!g_application.IsServerMode())
+ {
Sascha Montellese Owner

bad indentation

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Sascha Montellese
Owner

Just to show you what I mean I picked out a few places with bad indentation. I didn't bother to mark them all because they are pretty obvious when looking at the diff off this PR here on github.

vajonam

@Montellese thats for pointing those out, stopped seeing them after seeing the patch for so long.. but doesn't look like this PR is going too far based on the discussion thus far?

Sascha Montellese
Owner

@vajonam I know that feeling when you have seen some code for too long ;-)

What I stated above is just my personal opinion. Considering that I neither have multiple XBMC installations nor use MySQL I'm not really your target audience anyway.

Cory Fields
Owner

I'm really not sure that this is the way to go here. Compare to #214

With a headless xbmc, you don't get much. But by using xbmc as a lib and being able to create a server around it, you could add lots of functionality that we would never want in mainline.

vajonam

interesting, if this is path that we want to take, I can offer to code something but will need some help / direction I am just bit of hacker when it comes to XBMC i am afraid, enough to be dangerous!

what will be needed to achieve the following?

  • a server that listens exposing the http-api or jsonrpc api
  • updates a mysql db by running the scan and updating content.

wont this almost duplicate a lot of code that is already written in xbmc?

Cory Fields
Owner

well, the idea would be to start breaking breaking stuff out of Application.cpp and into a "services" class.

So then you would have an application that includes xbmc's "services" header, starts those services, then does whatever else it needs to do. So there would be no duplication, it would be running the same code as the desktop binary.

I'm not opposed to the headless idea, but it does seem to conflict with the notion of having a libxbmc for similar functionality. So I just want to be sure we think it through before going either route.

Cory Fields
Owner

I've pushed a branch that's updated for master. I'll get it cleaned up and working this week.

https://github.com/theuni/xbmc/tree/shared-lib

blades

@theuni going down the lib route is definitely the preferred long-term solution to this. however, that's a long-term solution as opposed to something available right now, and on top of that there wasn't much interest in making that happen right at this moment in time. the original pull request i created was a quick hack to get something available with the bare minimum of changes such that we could have a working server mode available here and now that wasn't going to need a massive re-architecting of the mainline codebase. i fully agree that it's not the ideal solution, but it works, and it's available now with only a few minor changes to the mainline codebase that don't impact anything else.

ultimately, so long as there's a server mode, that's the important thing. people have been begging for this for a very, very long time, and i saw a simple and quick way of getting it working. personally, i don't particularly care how it's done, just that it is done. this was within my abilities; shared libraries and building an entirely new server application to use them isn't.

Cory Fields
Owner

Well it's not an issue of getting it done, clearly the headless approach works. The issue is that once it goes in we have to support it. And indeed a server-mode is a big deal. Think of all the new-functionality requests we'll get and have to add to xbmc, for a short-term solution.

But rather than stalling for the future's sake, I'm working on getting something done up that resembles the current functionality here, but done in a lib-way.

Cory Fields
Owner

Additionally, looking closer at the changes here...

Most of the things that are special-cased for server mode should instead just not be compiled in. For ex, X, SDL, peripherals, etc.. Otherwise we still end up with tons of deps.. unsuitable for installing in places where this would be the most helpful.

Cory Fields
Owner

Ok, I've pushed some changes that do this using xbmc as a lib, while keeping the spirit of this PR. See my branch here: https://github.com/theuni/xbmc/tree/shared-lib

At the moment, it basically functions as @vajonam's headless binary would. The difference is that it is actually only a tiny stub application, that calls into libxbmc and blocks there. See here: https://github.com/theuni/xbmc/blob/shared-lib/xbmc/xbmc_headless.cpp for the example.

So it's very uninteresting in its current form. But. If we go this route, we can begin splitting things out into more reasonable chunks. For example, you may want a binary that does nothing more than serves XBMC's webinterface. In that case, a huge chunk of system libs could be removed, leaving you with a clean unit-testable application, or functional server.

The work isn't too bad, it mainly entails pulling Application::Create() and Application::Initialize apart and exposing the bits that start services to xbmc.h. Then, it would be dead-simple to create an application that just starts a few of our services and waits.

I think this also lends itself towards @jimfcarroll's world-domination plans, as iirc he was looking to nuke CApplication altogether.

Cory Fields
Owner

Most credit for the above belongs to @dbrobins btw. I'll be sure to mention that in the commits if we go this way.

David Robins

Thanks. It would be great if the shared lib/headless changes finally made make it in in some form. :)

Piethein Strengholt
Collaborator

Maybe just an idea.. Can't we ask Alasdair Campbell to have a look at this as well? He's Google Summer project is all about XBMC serving content by UPnP / DLNA. Would be nice to see a headless xbmc server serving content to other (xbmc) clients.

blades

@theuni the only downside is that you've now got a separate application: it's not a server-mode within xbmc, but instead an entirely new application using a shared library. to be honest, that's not even remotely a problem, but it's not something that i had the temerity to suggest with my changes :p

my only intention with this was to provide a quick-win that could be in use, and indeed it's been in use for the last few months with a hardcore bunch who were happy to compile it for themselves on the original thread here: http://forum.xbmc.org/showthread.php?tid=114612

now that there's a better solution that does this properly, i'd much rather see this brought up to a usable state instead. yeah, i'm a little gutted that i don't end up actually contributing to the project, but i can console myself with the thought that i've poked and prodded it enough to get an xbmc server onto the radar!

to be honest, it'll be nice not to have to be constantly defending the approach i took with this, too. all i wanted was a quick win to give the dev team space to do it properly while giving those who wanted a server mode something usable to play with.

anyway. what needs to be done from here to get your new branch into a state whereby i can give the thread something to use? how would i go about running your headless version?

Cory Fields
Owner

Wow, what a helpful response. You know we're supposed to be nerds with monstrous egos, right? :p

Here's how this really went. I have been meaning to get the lib concept into shape for quite a while. You guys came along with something that conflicted with it, so I had no choice but to do my part or shut up and let it go a different direction. So in that way, you definitely got things rolling.

All I've done so far is to get things building in a way that facilitates running headless. I created a stub app (xbmc_headless.bin) and verified that it runs the webserver.

The todo's mainly look like this:

  • Verify that the reorg in Application.cpp didn't break anything in the desktop usage of XBMC. @jmarshallnz had some valid concerns. This needs to happen first as we can't pull it in if it's breaking stuff.

  • Verify that server stuff actually works. There are bound to be some things that rely on the GUI being present. I don't know how to find these problems other than just hitting them during use.

  • Begin breaking things out into xbmc.h. Again, the hope is that run_xbmc() could go away, and the headless app could just launch individual services instead.

I could use some help with all of the above. I'd guess that the third probably won't be done until it hits mainline.

To help, just merge my branch, commit with --enable-shared-lib on or off, and start hacking.

I suppose I'll do some github cleanup. Will close this PR as well as the other, and do mine as an RFC. That will make it easier to discuss.

Thanks for the help!

vajonam

@theuni where do you want feedback about bugs? forum or here?

blades

well, i've got an ego somewhere around here if there's one missing :p

i have to admit, i know very, very little about C++. however, there's never a bad time to learn some new skills! i may need a little help to get things moving, though - is there a better way to communicate with you than via here? i'm happy to pass over my email address to you to take this off here, for example...

as to gui reliance, we did find a few bits for database updates (http://forum.xbmc.org/showthread.php?tid=114612&pid=985613#pid985613):

"You have to allow creation of two windows in Application.cpp:

  • g_windowManager.Add(new CGUIDialogMusicScan);
  • g_windowManager.Add(new CGUIDialogVideoScan);"

i also disabled some functionality in the builtins class when running as a server, just to be on the safe side, too.

Bas Rieter

Wow! I really appreciate that this is being picked up and supported by the XBMC team! Nice.

Would it be a good idea to start a central topic on this headless version on the XBMC forums so we can discuss builds, bugs and features there?

I myself an not a very skilled c++ coder. I did however created a tiny service addon that allows a user to schedule Video and Music backups on a daily basis. As soon as this headless server is official it might be a nice addition?

xbmcfanboy

@theuni I would like to help. Can you give more information about "commit with --enable-shared-lib on or off" please.

Cory Fields
Owner

@xbmcfanboy what OS are you running? I meant ./configure with --enable-shared-lib

I will need to discuss with the others, but I'd be ok with merging this in as soon as we could verify that the current functionality works as intended without breaking mainline. It's obviously a popular feature.

@blades: Thanks, I'll have a look at those. I'd much rather remove those dependencies on the gui than work around them, but I'm not sure what work is involved there yet.

@vajonam forum probably makes the most sense.

Cory Fields
Owner

I've taken a stab at fixing the scan+gui dependency here: #916. That will mean we won't need those hacks for allowing certain windows to be created. As I mentioned above, I'd prefer to fix any of those dependencies rather than just working around them.

Once we get that into mainline (assuming it works!), I'll rebase my lib work and do a new PR. We can begin testing/discussing then.

Cory Fields
Owner

Closing this in favor of #1049

Cory Fields theuni closed this
Cory Fields theuni referenced this pull request
Merged

Build Shared Lib #1049

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Apr 22, 2012
  1. vajonam

    XBMC Server modifications

    vajonam authored
This page is out of date. Refresh to see the latest.
502 xbmc/Application.cpp
View
@@ -395,6 +395,7 @@ CApplication::CApplication(void)
m_bPlatformDirectories = true;
m_bStandalone = false;
+ m_bServerMode = false;
m_bEnableLegacyRes = false;
m_bSystemScreenSaverEnable = false;
m_pInertialScrollingHandler = new CInertialScrollingHandler();
@@ -539,8 +540,10 @@ void CApplication::Preflight()
bool CApplication::Create()
{
g_settings.Initialize(); //Initialize default AdvancedSettings
-
- m_bSystemScreenSaverEnable = g_Windowing.IsSystemScreenSaverEnabled();
+ if (!g_application.IsServerMode())
+ {
+ m_bSystemScreenSaverEnable = g_Windowing.IsSystemScreenSaverEnabled();
+ }
g_Windowing.EnableSystemScreenSaver(false);
#ifdef _LINUX
@@ -625,62 +628,67 @@ bool CApplication::Create()
}
#ifdef HAS_XRANDR
- g_xrandr.LoadCustomModeLinesToAllOutputs();
+ if (!g_application.IsServerMode())
+ {
+ g_xrandr.LoadCustomModeLinesToAllOutputs();
+ }
#endif
// Init our DllLoaders emu env
init_emu_environ();
+ if (!g_application.IsServerMode())
+ {
#ifdef HAS_SDL
- CLog::Log(LOGNOTICE, "Setup SDL");
+ CLog::Log(LOGNOTICE, "Setup SDL");
- /* Clean up on exit, exit on window close and interrupt */
- atexit(SDL_Quit);
+ /* Clean up on exit, exit on window close and interrupt */
+ atexit(SDL_Quit);
- uint32_t sdlFlags = 0;
+ uint32_t sdlFlags = 0;
#if defined(HAS_SDL_OPENGL) || (HAS_GLES == 2)
- sdlFlags |= SDL_INIT_VIDEO;
+ sdlFlags |= SDL_INIT_VIDEO;
#endif
#ifdef HAS_SDL_AUDIO
- sdlFlags |= SDL_INIT_AUDIO;
+ sdlFlags |= SDL_INIT_AUDIO;
#endif
#ifdef HAS_SDL_JOYSTICK
- sdlFlags |= SDL_INIT_JOYSTICK;
+ sdlFlags |= SDL_INIT_JOYSTICK;
#endif
- //depending on how it's compiled, SDL periodically calls XResetScreenSaver when it's fullscreen
- //this might bring the monitor out of standby, so we have to disable it explicitly
- //by passing 0 for overwrite to setsenv, the user can still override this by setting the environment variable
+ //depending on how it's compiled, SDL periodically calls XResetScreenSaver when it's fullscreen
+ //this might bring the monitor out of standby, so we have to disable it explicitly
+ //by passing 0 for overwrite to setsenv, the user can still override this by setting the environment variable
#if defined(_LINUX) && !defined(__APPLE__)
- setenv("SDL_VIDEO_ALLOW_SCREENSAVER", "1", 0);
+ setenv("SDL_VIDEO_ALLOW_SCREENSAVER", "1", 0);
#endif
#endif // HAS_SDL
#ifdef _LINUX
- // for nvidia cards - vsync currently ALWAYS enabled.
- // the reason is that after screen has been setup changing this env var will make no difference.
- setenv("__GL_SYNC_TO_VBLANK", "1", 0);
- setenv("__GL_YIELD", "USLEEP", 0);
+ // for nvidia cards - vsync currently ALWAYS enabled.
+ // the reason is that after screen has been setup changing this env var will make no difference.
+ setenv("__GL_SYNC_TO_VBLANK", "1", 0);
+ setenv("__GL_YIELD", "USLEEP", 0);
#endif
#ifdef HAS_SDL
- if (SDL_Init(sdlFlags) != 0)
- {
- CLog::Log(LOGFATAL, "XBAppEx: Unable to initialize SDL: %s", SDL_GetError());
- return false;
- }
- #if defined(TARGET_DARWIN)
- // SDL_Init will install a handler for segfaults, restore the default handler.
- signal(SIGSEGV, SIG_DFL);
- #endif
+ if (SDL_Init(sdlFlags) != 0)
+ {
+ CLog::Log(LOGFATAL, "XBAppEx: Unable to initialize SDL: %s", SDL_GetError());
+ return false;
+ }
+#if defined(TARGET_DARWIN)
+ // SDL_Init will install a handler for segfaults, restore the default handler.
+ signal(SIGSEGV, SIG_DFL);
#endif
-
- // for python scripts that check the OS
+#endif
+ }
+// for python scripts that check the OS
#ifdef __APPLE__
setenv("OS","OS X",true);
#elif defined(_LINUX)
@@ -692,12 +700,15 @@ bool CApplication::Create()
// Initialize core peripheral port support. Note: If these parameters
// are 0 and NULL, respectively, then the default number and types of
// controllers will be initialized.
- if (!g_Windowing.InitWindowSystem())
+
+ if (!g_application.IsServerMode())
{
- CLog::Log(LOGFATAL, "CApplication::Create: Unable to init windowing system");
- return false;
+ if (!g_Windowing.InitWindowSystem())
+ {
+ CLog::Log(LOGFATAL, "CApplication::Create: Unable to init windowing system");
+ return false;
+ }
}
-
g_powerManager.Initialize();
CLog::Log(LOGNOTICE, "load settings...");
@@ -709,13 +720,19 @@ bool CApplication::Create()
CLog::Log(LOGINFO, "creating subdirectories");
CLog::Log(LOGINFO, "userdata folder: %s", g_settings.GetProfileUserDataFolder().c_str());
- CLog::Log(LOGINFO, "recording folder: %s", g_guiSettings.GetString("audiocds.recordingpath",false).c_str());
- CLog::Log(LOGINFO, "screenshots folder: %s", g_guiSettings.GetString("debug.screenshotpath",false).c_str());
+ if (!g_application.IsServerMode())
+ {
+ CLog::Log(LOGINFO, "recording folder: %s", g_guiSettings.GetString("audiocds.recordingpath",false).c_str());
+ CLog::Log(LOGINFO, "screenshots folder: %s", g_guiSettings.GetString("debug.screenshotpath",false).c_str());
+ }
CDirectory::Create(g_settings.GetUserDataFolder());
CDirectory::Create(g_settings.GetProfileUserDataFolder());
g_settings.CreateProfileFolders();
- update_emu_environ();//apply the GUI settings
+ if (!g_application.IsServerMode())
+ {
+ update_emu_environ();//apply the GUI settings
+ }
// initialize our charset converter
g_charsetConverter.reset();
@@ -745,94 +762,97 @@ bool CApplication::Create()
FatalErrorHandler(true, true, true);
}
- g_peripherals.Initialise();
+ if (!g_application.IsServerMode())
+ {
+ g_peripherals.Initialise();
- // Create the Mouse, Keyboard, Remote, and Joystick devices
- // Initialize after loading settings to get joystick deadzone setting
- g_Mouse.Initialize();
- g_Mouse.SetEnabled(g_guiSettings.GetBool("input.enablemouse"));
+ // Create the Mouse, Keyboard, Remote, and Joystick devices
+ // Initialize after loading settings to get joystick deadzone setting
+ g_Mouse.Initialize();
+ g_Mouse.SetEnabled(g_guiSettings.GetBool("input.enablemouse"));
- g_Keyboard.Initialize();
+ g_Keyboard.Initialize();
#if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
- g_RemoteControl.Initialize();
+ g_RemoteControl.Initialize();
#endif
#ifdef HAS_SDL_JOYSTICK
- g_Joystick.Initialize();
+ g_Joystick.Initialize();
#endif
-
+ }
#if defined(__APPLE__) && !defined(__arm__)
// Configure and possible manually start the helper.
XBMCHelper::GetInstance().Configure();
#endif
+ if (!g_application.IsServerMode())
+ {
+ // update the window resolution
+ g_Windowing.SetWindowResolution(g_guiSettings.GetInt("window.width"), g_guiSettings.GetInt("window.height"));
- // update the window resolution
- g_Windowing.SetWindowResolution(g_guiSettings.GetInt("window.width"), g_guiSettings.GetInt("window.height"));
-
- if (g_advancedSettings.m_startFullScreen && g_guiSettings.m_LookAndFeelResolution == RES_WINDOW)
- g_guiSettings.m_LookAndFeelResolution = RES_DESKTOP;
+ if (g_advancedSettings.m_startFullScreen && g_guiSettings.m_LookAndFeelResolution == RES_WINDOW)
+ g_guiSettings.m_LookAndFeelResolution = RES_DESKTOP;
- if (!g_graphicsContext.IsValidResolution(g_guiSettings.m_LookAndFeelResolution))
- {
- // Oh uh - doesn't look good for starting in their wanted screenmode
- CLog::Log(LOGERROR, "The screen resolution requested is not valid, resetting to a valid mode");
- g_guiSettings.m_LookAndFeelResolution = RES_DESKTOP;
- }
+ if (!g_graphicsContext.IsValidResolution(g_guiSettings.m_LookAndFeelResolution))
+ {
+ // Oh uh - doesn't look good for starting in their wanted screenmode
+ CLog::Log(LOGERROR, "The screen resolution requested is not valid, resetting to a valid mode");
+ g_guiSettings.m_LookAndFeelResolution = RES_DESKTOP;
+ }
#ifdef TARGET_DARWIN_OSX
- // force initial window creation to be windowed, if fullscreen, it will switch to it below
- // fixes the white screen of death if starting fullscreen and switching to windowed.
- bool bFullScreen = false;
- if (!g_Windowing.CreateNewWindow("XBMC", bFullScreen, g_settings.m_ResInfo[RES_WINDOW], OnEvent))
- {
- CLog::Log(LOGFATAL, "CApplication::Create: Unable to create window");
- return false;
- }
+ // force initial window creation to be windowed, if fullscreen, it will switch to it below
+ // fixes the white screen of death if starting fullscreen and switching to windowed.
+ bool bFullScreen = false;
+ if (!g_Windowing.CreateNewWindow("XBMC", bFullScreen, g_settings.m_ResInfo[RES_WINDOW], OnEvent))
+ {
+ CLog::Log(LOGFATAL, "CApplication::Create: Unable to create window");
+ return false;
+ }
#else
- bool bFullScreen = g_guiSettings.m_LookAndFeelResolution != RES_WINDOW;
- if (!g_Windowing.CreateNewWindow("XBMC", bFullScreen, g_settings.m_ResInfo[g_guiSettings.m_LookAndFeelResolution], OnEvent))
- {
- CLog::Log(LOGFATAL, "CApplication::Create: Unable to create window");
- return false;
- }
+ bool bFullScreen = g_guiSettings.m_LookAndFeelResolution != RES_WINDOW;
+ if (!g_Windowing.CreateNewWindow("XBMC", bFullScreen, g_settings.m_ResInfo[g_guiSettings.m_LookAndFeelResolution], OnEvent))
+ {
+ CLog::Log(LOGFATAL, "CApplication::Create: Unable to create window");
+ return false;
+ }
#endif
- if (!g_Windowing.InitRenderSystem())
- {
- CLog::Log(LOGFATAL, "CApplication::Create: Unable to init rendering system");
- return false;
- }
-
- // set GUI res and force the clear of the screen
- g_graphicsContext.SetVideoResolution(g_guiSettings.m_LookAndFeelResolution);
-
- if (g_advancedSettings.m_splashImage)
- {
- CStdString strUserSplash = "special://home/media/Splash.png";
- if (CFile::Exists(strUserSplash))
+ if (!g_Windowing.InitRenderSystem())
{
- CLog::Log(LOGINFO, "load user splash image: %s", CSpecialProtocol::TranslatePath(strUserSplash).c_str());
- m_splash = new CSplash(strUserSplash);
+ CLog::Log(LOGFATAL, "CApplication::Create: Unable to init rendering system");
+ return false;
}
- else
+
+ // set GUI res and force the clear of the screen
+ g_graphicsContext.SetVideoResolution(g_guiSettings.m_LookAndFeelResolution);
+
+ if (g_advancedSettings.m_splashImage)
{
- CLog::Log(LOGINFO, "load default splash image: %s", CSpecialProtocol::TranslatePath("special://xbmc/media/Splash.png").c_str());
- m_splash = new CSplash("special://xbmc/media/Splash.png");
- }
- m_splash->Show();
- }
+ CStdString strUserSplash = "special://home/media/Splash.png";
+ if (CFile::Exists(strUserSplash))
+ {
+ CLog::Log(LOGINFO, "load user splash image: %s", CSpecialProtocol::TranslatePath(strUserSplash).c_str());
+ m_splash = new CSplash(strUserSplash);
+ }
+ else
+ {
+ CLog::Log(LOGINFO, "load default splash image: %s", CSpecialProtocol::TranslatePath("special://xbmc/media/Splash.png").c_str());
+ m_splash = new CSplash("special://xbmc/media/Splash.png");
+ }
+ m_splash->Show();
+ }
- // The key mappings may already have been loaded by a peripheral
- CLog::Log(LOGINFO, "load keymapping");
- if (!CButtonTranslator::GetInstance().Load())
+ // The key mappings may already have been loaded by a peripheral
+ CLog::Log(LOGINFO, "load keymapping");
+ if (!CButtonTranslator::GetInstance().Load())
FatalErrorHandler(false, false, true);
- int iResolution = g_graphicsContext.GetVideoResolution();
- CLog::Log(LOGINFO, "GUI format %ix%i %s",
- g_settings.m_ResInfo[iResolution].iWidth,
- g_settings.m_ResInfo[iResolution].iHeight,
- g_settings.m_ResInfo[iResolution].strMode.c_str());
- g_windowManager.Initialize();
-
+ int iResolution = g_graphicsContext.GetVideoResolution();
+ CLog::Log(LOGINFO, "GUI format %ix%i %s",
+ g_settings.m_ResInfo[iResolution].iWidth,
+ g_settings.m_ResInfo[iResolution].iHeight,
+ g_settings.m_ResInfo[iResolution].strMode.c_str());
+ g_windowManager.Initialize();
+ }
CUtil::InitRandomSeed();
g_mediaManager.Initialize();
@@ -1120,135 +1140,151 @@ bool CApplication::Initialize()
// Init DPMS, before creating the corresponding setting control.
m_dpms = new DPMSSupport();
- g_guiSettings.GetSetting("powermanagement.displaysoff")->SetVisible(m_dpms->IsSupported());
-
- g_windowManager.Add(new CGUIWindowHome); // window id = 0
- g_windowManager.Add(new CGUIWindowPrograms); // window id = 1
- g_windowManager.Add(new CGUIWindowPictures); // window id = 2
- g_windowManager.Add(new CGUIWindowFileManager); // window id = 3
- g_windowManager.Add(new CGUIWindowSettings); // window id = 4
- g_windowManager.Add(new CGUIWindowSystemInfo); // window id = 7
+ if (!g_application.IsServerMode())
+ {
+ g_guiSettings.GetSetting("powermanagement.displaysoff")->SetVisible(m_dpms->IsSupported());
+
+ g_windowManager.Add(new CGUIWindowHome); // window id = 0
+ g_windowManager.Add(new CGUIWindowPrograms); // window id = 1
+ g_windowManager.Add(new CGUIWindowPictures); // window id = 2
+ g_windowManager.Add(new CGUIWindowFileManager); // window id = 3
+ g_windowManager.Add(new CGUIWindowSettings); // window id = 4
+ g_windowManager.Add(new CGUIWindowSystemInfo); // window id = 7
#ifdef HAS_GL
- g_windowManager.Add(new CGUIWindowTestPatternGL); // window id = 8
+ g_windowManager.Add(new CGUIWindowTestPatternGL); // window id = 8
#endif
#ifdef HAS_DX
- g_windowManager.Add(new CGUIWindowTestPatternDX); // window id = 8
-#endif
- g_windowManager.Add(new CGUIDialogTeletext); // window id =
- g_windowManager.Add(new CGUIWindowSettingsScreenCalibration); // window id = 11
- g_windowManager.Add(new CGUIWindowSettingsCategory); // window id = 12 slideshow:window id 2007
- g_windowManager.Add(new CGUIWindowVideoNav); // window id = 36
- g_windowManager.Add(new CGUIWindowVideoPlaylist); // window id = 28
- g_windowManager.Add(new CGUIWindowLoginScreen); // window id = 29
- g_windowManager.Add(new CGUIWindowSettingsProfile); // window id = 34
- g_windowManager.Add(new CGUIWindowAddonBrowser); // window id = 40
- g_windowManager.Add(new CGUIWindowScreensaverDim); // window id = 97
- g_windowManager.Add(new CGUIWindowDebugInfo); // window id = 98
- g_windowManager.Add(new CGUIWindowPointer); // window id = 99
- g_windowManager.Add(new CGUIDialogYesNo); // window id = 100
- g_windowManager.Add(new CGUIDialogProgress); // window id = 101
- g_windowManager.Add(new CGUIDialogKeyboard); // window id = 103
- g_windowManager.Add(new CGUIDialogVolumeBar); // window id = 104
- g_windowManager.Add(new CGUIDialogSeekBar); // window id = 115
- g_windowManager.Add(new CGUIDialogSubMenu); // window id = 105
- g_windowManager.Add(new CGUIDialogContextMenu); // window id = 106
- g_windowManager.Add(new CGUIDialogKaiToast); // window id = 107
- g_windowManager.Add(new CGUIDialogNumeric); // window id = 109
- g_windowManager.Add(new CGUIDialogGamepad); // window id = 110
- g_windowManager.Add(new CGUIDialogButtonMenu); // window id = 111
+ g_windowManager.Add(new CGUIWindowTestPatternDX); // window id = 8
+#endif
+ g_windowManager.Add(new CGUIDialogTeletext); // window id =
+ g_windowManager.Add(new CGUIWindowSettingsScreenCalibration); // window id = 11
+ g_windowManager.Add(new CGUIWindowSettingsCategory); // window id = 12 slideshow:window id 2007
+ g_windowManager.Add(new CGUIWindowVideoNav); // window id = 36
+ g_windowManager.Add(new CGUIWindowVideoPlaylist); // window id = 28
+ g_windowManager.Add(new CGUIWindowLoginScreen); // window id = 29
+ g_windowManager.Add(new CGUIWindowSettingsProfile); // window id = 34
+ g_windowManager.Add(new CGUIWindowAddonBrowser); // window id = 40
+ g_windowManager.Add(new CGUIWindowScreensaverDim); // window id = 97
+ g_windowManager.Add(new CGUIWindowDebugInfo); // window id = 98
+ g_windowManager.Add(new CGUIWindowPointer); // window id = 99
+ g_windowManager.Add(new CGUIDialogYesNo); // window id = 100
+ g_windowManager.Add(new CGUIDialogProgress); // window id = 101
+ g_windowManager.Add(new CGUIDialogKeyboard); // window id = 103
+ g_windowManager.Add(new CGUIDialogVolumeBar); // window id = 104
+ g_windowManager.Add(new CGUIDialogSeekBar); // window id = 115
+ g_windowManager.Add(new CGUIDialogSubMenu); // window id = 105
+ g_windowManager.Add(new CGUIDialogContextMenu); // window id = 106
+ g_windowManager.Add(new CGUIDialogKaiToast); // window id = 107
+ g_windowManager.Add(new CGUIDialogNumeric); // window id = 109
+ g_windowManager.Add(new CGUIDialogGamepad); // window id = 110
+ g_windowManager.Add(new CGUIDialogButtonMenu); // window id = 111
+ }
g_windowManager.Add(new CGUIDialogMusicScan); // window id = 112
- g_windowManager.Add(new CGUIDialogMuteBug); // window id = 113
- g_windowManager.Add(new CGUIDialogPlayerControls); // window id = 114
+ if (!g_application.IsServerMode())
+ {
+ g_windowManager.Add(new CGUIDialogMuteBug); // window id = 113
+ g_windowManager.Add(new CGUIDialogPlayerControls); // window id = 114
#ifdef HAS_KARAOKE
- g_windowManager.Add(new CGUIDialogKaraokeSongSelectorSmall); // window id 143
- g_windowManager.Add(new CGUIDialogKaraokeSongSelectorLarge); // window id 144
-#endif
- g_windowManager.Add(new CGUIDialogSlider); // window id = 145
- g_windowManager.Add(new CGUIDialogMusicOSD); // window id = 120
- g_windowManager.Add(new CGUIDialogVisualisationPresetList); // window id = 122
- g_windowManager.Add(new CGUIDialogVideoSettings); // window id = 123
- g_windowManager.Add(new CGUIDialogAudioSubtitleSettings); // window id = 124
- g_windowManager.Add(new CGUIDialogVideoBookmarks); // window id = 125
- // Don't add the filebrowser dialog - it's created and added when it's needed
- g_windowManager.Add(new CGUIDialogNetworkSetup); // window id = 128
- g_windowManager.Add(new CGUIDialogMediaSource); // window id = 129
- g_windowManager.Add(new CGUIDialogProfileSettings); // window id = 130
+ g_windowManager.Add(new CGUIDialogKaraokeSongSelectorSmall); // window id 143
+ g_windowManager.Add(new CGUIDialogKaraokeSongSelectorLarge); // window id 144
+#endif
+ g_windowManager.Add(new CGUIDialogSlider); // window id = 145
+ g_windowManager.Add(new CGUIDialogMusicOSD); // window id = 120
+ g_windowManager.Add(new CGUIDialogVisualisationPresetList); // window id = 122
+ g_windowManager.Add(new CGUIDialogVideoSettings); // window id = 123
+ g_windowManager.Add(new CGUIDialogAudioSubtitleSettings); // window id = 124
+ g_windowManager.Add(new CGUIDialogVideoBookmarks); // window id = 125
+ // Don't add the filebrowser dialog - it's created and added when it's needed
+ g_windowManager.Add(new CGUIDialogNetworkSetup); // window id = 128
+ g_windowManager.Add(new CGUIDialogMediaSource); // window id = 129
+ g_windowManager.Add(new CGUIDialogProfileSettings); // window id = 130
+ }
g_windowManager.Add(new CGUIDialogVideoScan); // window id = 133
- g_windowManager.Add(new CGUIDialogFavourites); // window id = 134
- g_windowManager.Add(new CGUIDialogSongInfo); // window id = 135
- g_windowManager.Add(new CGUIDialogSmartPlaylistEditor); // window id = 136
- g_windowManager.Add(new CGUIDialogSmartPlaylistRule); // window id = 137
- g_windowManager.Add(new CGUIDialogBusy); // window id = 138
- g_windowManager.Add(new CGUIDialogPictureInfo); // window id = 139
- g_windowManager.Add(new CGUIDialogAddonInfo);
- g_windowManager.Add(new CGUIDialogAddonSettings); // window id = 140
+ if (!g_application.IsServerMode())
+ {
+ g_windowManager.Add(new CGUIDialogFavourites); // window id = 134
+ g_windowManager.Add(new CGUIDialogSongInfo); // window id = 135
+ g_windowManager.Add(new CGUIDialogSmartPlaylistEditor); // window id = 136
+ g_windowManager.Add(new CGUIDialogSmartPlaylistRule); // window id = 137
+ g_windowManager.Add(new CGUIDialogBusy); // window id = 138
+ g_windowManager.Add(new CGUIDialogPictureInfo); // window id = 139
+ g_windowManager.Add(new CGUIDialogAddonInfo);
+ g_windowManager.Add(new CGUIDialogAddonSettings); // window id = 140
#ifdef HAS_LINUX_NETWORK
- g_windowManager.Add(new CGUIDialogAccessPoints); // window id = 141
+ g_windowManager.Add(new CGUIDialogAccessPoints); // window id = 141
#endif
- g_windowManager.Add(new CGUIDialogLockSettings); // window id = 131
+ g_windowManager.Add(new CGUIDialogLockSettings); // window id = 131
- g_windowManager.Add(new CGUIDialogContentSettings); // window id = 132
+ g_windowManager.Add(new CGUIDialogContentSettings); // window id = 132
- g_windowManager.Add(new CGUIDialogPlayEject);
+ g_windowManager.Add(new CGUIDialogPlayEject);
- g_windowManager.Add(new CGUIDialogPeripheralManager);
- g_windowManager.Add(new CGUIDialogPeripheralSettings);
+ g_windowManager.Add(new CGUIDialogPeripheralManager);
+ g_windowManager.Add(new CGUIDialogPeripheralSettings);
- g_windowManager.Add(new CGUIWindowMusicPlayList); // window id = 500
- g_windowManager.Add(new CGUIWindowMusicSongs); // window id = 501
- g_windowManager.Add(new CGUIWindowMusicNav); // window id = 502
- g_windowManager.Add(new CGUIWindowMusicPlaylistEditor); // window id = 503
+ g_windowManager.Add(new CGUIWindowMusicPlayList); // window id = 500
+ g_windowManager.Add(new CGUIWindowMusicSongs); // window id = 501
+ g_windowManager.Add(new CGUIWindowMusicNav); // window id = 502
+ g_windowManager.Add(new CGUIWindowMusicPlaylistEditor); // window id = 503
- g_windowManager.Add(new CGUIDialogSelect); // window id = 2000
- g_windowManager.Add(new CGUIDialogMusicInfo); // window id = 2001
- g_windowManager.Add(new CGUIDialogOK); // window id = 2002
- g_windowManager.Add(new CGUIDialogVideoInfo); // window id = 2003
- g_windowManager.Add(new CGUIDialogTextViewer);
- g_windowManager.Add(new CGUIWindowFullScreen); // window id = 2005
- g_windowManager.Add(new CGUIWindowVisualisation); // window id = 2006
- g_windowManager.Add(new CGUIWindowSlideShow); // window id = 2007
- g_windowManager.Add(new CGUIDialogFileStacking); // window id = 2008
+ g_windowManager.Add(new CGUIDialogSelect); // window id = 2000
+ g_windowManager.Add(new CGUIDialogMusicInfo); // window id = 2001
+ g_windowManager.Add(new CGUIDialogOK); // window id = 2002
+ g_windowManager.Add(new CGUIDialogVideoInfo); // window id = 2003
+ g_windowManager.Add(new CGUIDialogTextViewer);
+ g_windowManager.Add(new CGUIWindowFullScreen); // window id = 2005
+ g_windowManager.Add(new CGUIWindowVisualisation); // window id = 2006
+ g_windowManager.Add(new CGUIWindowSlideShow); // window id = 2007
+ g_windowManager.Add(new CGUIDialogFileStacking); // window id = 2008
#ifdef HAS_KARAOKE
- g_windowManager.Add(new CGUIWindowKaraokeLyrics); // window id = 2009
+ g_windowManager.Add(new CGUIWindowKaraokeLyrics); // window id = 2009
#endif
- g_windowManager.Add(new CGUIDialogVideoOSD); // window id = 2901
- g_windowManager.Add(new CGUIDialogMusicOverlay); // window id = 2903
- g_windowManager.Add(new CGUIDialogVideoOverlay); // window id = 2904
- g_windowManager.Add(new CGUIWindowScreensaver); // window id = 2900 Screensaver
- g_windowManager.Add(new CGUIWindowWeather); // window id = 2600 WEATHER
- g_windowManager.Add(new CGUIWindowStartup); // startup window (id 2999)
+ g_windowManager.Add(new CGUIDialogVideoOSD); // window id = 2901
+ g_windowManager.Add(new CGUIDialogMusicOverlay); // window id = 2903
+ g_windowManager.Add(new CGUIDialogVideoOverlay); // window id = 2904
+ g_windowManager.Add(new CGUIWindowScreensaver); // window id = 2900 Screensaver
+ g_windowManager.Add(new CGUIWindowWeather); // window id = 2600 WEATHER
+ g_windowManager.Add(new CGUIWindowStartup); // startup window (id 2999)
- /* window id's 3000 - 3100 are reserved for python */
+ /* window id's 3000 - 3100 are reserved for python */
- // Make sure we have at least the default skin
- if (!LoadSkin(g_guiSettings.GetString("lookandfeel.skin")) && !LoadSkin(DEFAULT_SKIN))
- {
- CLog::Log(LOGERROR, "Default skin '%s' not found! Terminating..", DEFAULT_SKIN);
- FatalErrorHandler(true, true, true);
- }
+ // Make sure we have at least the default skin
+ if (!LoadSkin(g_guiSettings.GetString("lookandfeel.skin")) && !LoadSkin(DEFAULT_SKIN))
+ {
+ CLog::Log(LOGERROR, "Default skin '%s' not found! Terminating..", DEFAULT_SKIN);
+ FatalErrorHandler(true, true, true);
+ }
- if (g_advancedSettings.m_splashImage)
- SAFE_DELETE(m_splash);
+ if (g_advancedSettings.m_splashImage)
+ SAFE_DELETE(m_splash);
- if (g_guiSettings.GetBool("masterlock.startuplock") &&
- g_settings.GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE &&
- !g_settings.GetMasterProfile().getLockCode().IsEmpty())
- {
- g_passwordManager.CheckStartUpLock();
+ if (g_guiSettings.GetBool("masterlock.startuplock") &&
+ g_settings.GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE &&
+ !g_settings.GetMasterProfile().getLockCode().IsEmpty())
+ {
+ g_passwordManager.CheckStartUpLock();
+ }
}
-
// check if we should use the login screen
if (g_settings.UsingLoginScreen())
- g_windowManager.ActivateWindow(WINDOW_LOGIN_SCREEN);
+ {
+ if (!g_application.IsServerMode())
+ {
+ g_windowManager.ActivateWindow(WINDOW_LOGIN_SCREEN);
+ }
+ }
else
{
#ifdef HAS_JSONRPC
CJSONRPC::Initialize();
#endif
ADDON::CAddonMgr::Get().StartServices(false);
- g_windowManager.ActivateWindow(g_SkinInfo->GetFirstWindow());
+ if (!g_application.IsServerMode())
+ {
+ g_windowManager.ActivateWindow(g_SkinInfo->GetFirstWindow());
+ }
}
g_sysinfo.Refresh();
@@ -1314,8 +1350,8 @@ bool CApplication::StartWebServer()
#ifdef _LINUX
if (webPort < 1024 && geteuid() != 0)
{
- CLog::Log(LOGERROR, "Cannot start Web Server as port is smaller than 1024 and user is not root");
- return false;
+ CLog::Log(LOGERROR, "Cannot start Web Server as port is smaller than 1024 and user is not root");
+ return false;
}
#endif
@@ -1360,7 +1396,8 @@ void CApplication::StopWebServer()
CZeroconf::GetInstance()->RemoveService("servers.webserver");
CZeroconf::GetInstance()->RemoveService("servers.jsonrpc-http");
CZeroconf::GetInstance()->RemoveService("servers.webapi");
- } else
+ }
+ else
CLog::Log(LOGWARNING, "Webserver: Failed to stop.");
}
#endif
@@ -2040,6 +2077,10 @@ void CApplication::Render()
if (m_bStop)
return;
+ // do not render if we're in server mode
+ if (g_application.IsServerMode())
+ return;
+
if (!m_AppActive && !m_bStop && (!IsPlayingVideo() || IsPaused()))
{
Sleep(1);
@@ -2171,6 +2212,10 @@ void CApplication::SetStandAlone(bool value)
{
g_advancedSettings.m_handleMounting = m_bStandalone = value;
}
+void CApplication::SetServerMode(bool value)
+{
+ g_advancedSettings.m_serverMode = m_bServerMode = value;
+}
// OnKey() translates the key into a CAction which is sent on to our Window Manager.
// The window manager will return true if the event is processed, false otherwise.
@@ -2729,21 +2774,22 @@ void CApplication::FrameMove(bool processEvents)
m_frameTime.StartZero();
// never set a frametime less than 2 fps to avoid problems when debuggin and on breaks
if( frameTime > 0.5 ) frameTime = 0.5;
-
- g_graphicsContext.Lock();
- // check if there are notifications to display
- CGUIDialogKaiToast *toast = (CGUIDialogKaiToast *)g_windowManager.GetWindow(WINDOW_DIALOG_KAI_TOAST);
- if (toast && toast->DoWork())
+ if (!g_application.IsServerMode())
{
- if (!toast->IsDialogRunning())
+ g_graphicsContext.Lock();
+ // check if there are notifications to display
+ CGUIDialogKaiToast *toast = (CGUIDialogKaiToast *)g_windowManager.GetWindow(WINDOW_DIALOG_KAI_TOAST);
+ if (toast && toast->DoWork())
{
- toast->Show();
+ if (!toast->IsDialogRunning())
+ {
+ toast->Show();
+ }
}
- }
- g_graphicsContext.Unlock();
-
- UpdateLCD();
+ g_graphicsContext.Unlock();
+ UpdateLCD();
+ }
#if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
// Read the input from a remote
g_RemoteControl.Update();
@@ -2759,9 +2805,12 @@ void CApplication::FrameMove(bool processEvents)
ProcessPeripherals(frameTime);
m_pInertialScrollingHandler->ProcessInertialScroll(frameTime);
}
- if (!m_bStop)
- g_windowManager.Process(CTimeUtils::GetFrameTime());
- g_windowManager.FrameMove();
+ if (!g_application.IsServerMode())
+ {
+ if (!m_bStop)
+ g_windowManager.Process(CTimeUtils::GetFrameTime());
+ g_windowManager.FrameMove();
+ }
}
bool CApplication::ProcessGamepad(float frameTime)
@@ -4858,14 +4907,19 @@ bool CApplication::ExecuteXBMCAction(std::string actionStr)
void CApplication::Process()
{
MEASURE_FUNCTION;
+ if (g_application.IsServerMode())
+ {
+ Sleep(1);
+ }
+ else
+ {
+ // dispatch the messages generated by python or other threads to the current window
+ g_windowManager.DispatchThreadMessages();
- // dispatch the messages generated by python or other threads to the current window
- g_windowManager.DispatchThreadMessages();
-
- // process messages which have to be send to the gui
- // (this can only be done after g_windowManager.Render())
- m_applicationMessenger.ProcessWindowMessages();
-
+ // process messages which have to be send to the gui
+ // (this can only be done after g_windowManager.Render())
+ m_applicationMessenger.ProcessWindowMessages();
+ }
#ifdef HAS_PYTHON
// process any Python scripts
g_pythonParser.Process();
9 xbmc/Application.h
View
@@ -284,6 +284,13 @@ class CApplication : public CXBApplicationEx, public IPlayerCallback, public IMs
return m_bStandalone;
}
+ void SetServerMode(bool value);
+
+ bool IsServerMode()
+ {
+ return m_bServerMode;
+ }
+
void SetEnableLegacyRes(bool value)
{
m_bEnableLegacyRes = value;
@@ -304,6 +311,7 @@ class CApplication : public CXBApplicationEx, public IPlayerCallback, public IMs
return m_bTestMode;
}
+
bool IsPresentFrame();
void Minimize();
@@ -365,6 +373,7 @@ class CApplication : public CXBApplicationEx, public IPlayerCallback, public IMs
unsigned int m_lastRenderTime;
bool m_bStandalone;
+ bool m_bServerMode;
bool m_bEnableLegacyRes;
bool m_bTestMode;
bool m_bSystemScreenSaverEnable;
199 xbmc/interfaces/Builtins.cpp
View
@@ -98,114 +98,115 @@ using namespace MEDIA_DETECT;
typedef struct
{
const char* command;
+ bool availableInServerMode;
bool needsParameters;
const char* description;
} BUILT_IN;
const BUILT_IN commands[] = {
- { "Help", false, "This help message" },
- { "Reboot", false, "Reboot the xbox (power cycle)" },
- { "Restart", false, "Restart the xbox (power cycle)" },
- { "ShutDown", false, "Shutdown the xbox" },
- { "Powerdown", false, "Powerdown system" },
- { "Quit", false, "Quit XBMC" },
- { "Hibernate", false, "Hibernates the system" },
- { "Suspend", false, "Suspends the system" },
- { "RestartApp", false, "Restart XBMC" },
- { "Minimize", false, "Minimize XBMC" },
- { "Reset", false, "Reset the xbox (warm reboot)" },
- { "Mastermode", false, "Control master mode" },
- { "ActivateWindow", true, "Activate the specified window" },
- { "ReplaceWindow", true, "Replaces the current window with the new one" },
- { "TakeScreenshot", false, "Takes a Screenshot" },
- { "RunScript", true, "Run the specified script" },
+ { "Help", true, false, "This help message" },
+ { "Reboot", true, false, "Reboot the xbox (power cycle)" },
+ { "Restart", true, false, "Restart the xbox (power cycle)" },
+ { "ShutDown", true, false, "Shutdown the xbox" },
+ { "Powerdown", true, false, "Powerdown system" },
+ { "Quit", true, false, "Quit XBMC" },
+ { "Hibernate", true, false, "Hibernates the system" },
+ { "Suspend", true, false, "Suspends the system" },
+ { "RestartApp", true, false, "Restart XBMC" },
+ { "Minimize", false, false, "Minimize XBMC" },
+ { "Reset", true, false, "Reset the xbox (warm reboot)" },
+ { "Mastermode", true, false, "Control master mode" },
+ { "ActivateWindow", false, true, "Activate the specified window" },
+ { "ReplaceWindow", false, true, "Replaces the current window with the new one" },
+ { "TakeScreenshot", false, false, "Takes a Screenshot" },
+ { "RunScript", true, true, "Run the specified script" },
#if defined(__APPLE__)
- { "RunAppleScript", true, "Run the specified AppleScript command" },
+ { "RunAppleScript", true, true, "Run the specified AppleScript command" },
#endif
- { "RunPlugin", true, "Run the specified plugin" },
- { "RunAddon", true, "Run the specified plugin/script" },
- { "Extract", true, "Extracts the specified archive" },
- { "PlayMedia", true, "Play the specified media file (or playlist)" },
- { "SlideShow", true, "Run a slideshow from the specified directory" },
- { "RecursiveSlideShow", true, "Run a slideshow from the specified directory, including all subdirs" },
- { "ReloadSkin", false, "Reload XBMC's skin" },
- { "UnloadSkin", false, "Unload XBMC's skin" },
- { "RefreshRSS", false, "Reload RSS feeds from RSSFeeds.xml"},
- { "PlayerControl", true, "Control the music or video player" },
- { "Playlist.PlayOffset", true, "Start playing from a particular offset in the playlist" },
- { "Playlist.Clear", false, "Clear the current playlist" },
- { "EjectTray", false, "Close or open the DVD tray" },
- { "AlarmClock", true, "Prompt for a length of time and start an alarm clock" },
- { "CancelAlarm", true, "Cancels an alarm" },
- { "Action", true, "Executes an action for the active window (same as in keymap)" },
- { "Notification", true, "Shows a notification on screen, specify header, then message, and optionally time in milliseconds and a icon." },
- { "PlayDVD", false, "Plays the inserted CD or DVD media from the DVD-ROM Drive!" },
- { "RipCD", false, "Rip the currently inserted audio CD"},
- { "Skin.ToggleSetting", true, "Toggles a skin setting on or off" },
- { "Skin.SetString", true, "Prompts and sets skin string" },
- { "Skin.SetNumeric", true, "Prompts and sets numeric input" },
- { "Skin.SetPath", true, "Prompts and sets a skin path" },
- { "Skin.Theme", true, "Control skin theme" },
- { "Skin.SetImage", true, "Prompts and sets a skin image" },
- { "Skin.SetLargeImage", true, "Prompts and sets a large skin images" },
- { "Skin.SetFile", true, "Prompts and sets a file" },
- { "Skin.SetAddon", true, "Prompts and set an addon" },
- { "Skin.SetBool", true, "Sets a skin setting on" },
- { "Skin.Reset", true, "Resets a skin setting to default" },
- { "Skin.ResetSettings", false, "Resets all skin settings" },
- { "Mute", false, "Mute the player" },
- { "SetVolume", true, "Set the current volume" },
- { "Dialog.Close", true, "Close a dialog" },
- { "System.LogOff", false, "Log off current user" },
- { "System.Exec", true, "Execute shell commands" },
- { "System.ExecWait", true, "Execute shell commands and freezes XBMC until shell is closed" },
- { "Resolution", true, "Change XBMC's Resolution" },
- { "SetFocus", true, "Change current focus to a different control id" },
- { "UpdateLibrary", true, "Update the selected library (music or video)" },
- { "CleanLibrary", true, "Clean the video/music library" },
- { "ExportLibrary", true, "Export the video/music library" },
- { "PageDown", true, "Send a page down event to the pagecontrol with given id" },
- { "PageUp", true, "Send a page up event to the pagecontrol with given id" },
- { "LastFM.Love", false, "Add the current playing last.fm radio track to the last.fm loved tracks" },
- { "LastFM.Ban", false, "Ban the current playing last.fm radio track" },
- { "Container.Refresh", false, "Refresh current listing" },
- { "Container.Update", false, "Update current listing. Send Container.Update(path,replace) to reset the path history" },
- { "Container.NextViewMode", false, "Move to the next view type (and refresh the listing)" },
- { "Container.PreviousViewMode", false, "Move to the previous view type (and refresh the listing)" },
- { "Container.SetViewMode", true, "Move to the view with the given id" },
- { "Container.NextSortMethod", false, "Change to the next sort method" },
- { "Container.PreviousSortMethod",false, "Change to the previous sort method" },
- { "Container.SetSortMethod", true, "Change to the specified sort method" },
- { "Container.SortDirection", false, "Toggle the sort direction" },
- { "Control.Move", true, "Tells the specified control to 'move' to another entry specified by offset" },
- { "Control.SetFocus", true, "Change current focus to a different control id" },
- { "Control.Message", true, "Send a given message to a control within a given window" },
- { "SendClick", true, "Send a click message from the given control to the given window" },
- { "LoadProfile", true, "Load the specified profile (note; if locks are active it won't work)" },
- { "SetProperty", true, "Sets a window property for the current focused window/dialog (key,value)" },
- { "ClearProperty", true, "Clears a window property for the current focused window/dialog (key,value)" },
- { "PlayWith", true, "Play the selected item with the specified core" },
- { "WakeOnLan", true, "Sends the wake-up packet to the broadcast address for the specified MAC address" },
- { "Addon.Default.OpenSettings", true, "Open a settings dialog for the default addon of the given type" },
- { "Addon.Default.Set", true, "Open a select dialog to allow choosing the default addon of the given type" },
- { "Addon.OpenSettings", true, "Open a settings dialog for the addon of the given id" },
- { "UpdateAddonRepos", false, "Check add-on repositories for updates" },
- { "UpdateLocalAddons", false, "Check for local add-on changes" },
- { "ToggleDPMS", false, "Toggle DPMS mode manually"},
- { "Weather.Refresh", false, "Force weather data refresh"},
- { "Weather.LocationNext", false, "Switch to next weather location"},
- { "Weather.LocationPrevious", false, "Switch to previous weather location"},
- { "Weather.LocationSet", true, "Switch to given weather location (parameter can be 1-3)"},
+ { "RunPlugin", true, true, "Run the specified plugin" },
+ { "RunAddon", true, true, "Run the specified plugin/script" },
+ { "Extract", true, true, "Extracts the specified archive" },
+ { "PlayMedia", false, true, "Play the specified media file (or playlist)" },
+ { "SlideShow", false, true, "Run a slideshow from the specified directory" },
+ { "RecursiveSlideShow", false, true, "Run a slideshow from the specified directory, including all subdirs" },
+ { "ReloadSkin", false, false, "Reload XBMC's skin" },
+ { "UnloadSkin", false, false, "Unload XBMC's skin" },
+ { "RefreshRSS", false, false, "Reload RSS feeds from RSSFeeds.xml"},
+ { "PlayerControl", false, true, "Control the music or video player" },
+ { "Playlist.PlayOffset", false, true, "Start playing from a particular offset in the playlist" },
+ { "Playlist.Clear", false, false, "Clear the current playlist" },
+ { "EjectTray", false, false, "Close or open the DVD tray" },
+ { "AlarmClock", true, true, "Prompt for a length of time and start an alarm clock" },
+ { "CancelAlarm", true, true, "Cancels an alarm" },
+ { "Action", false, true, "Executes an action for the active window (same as in keymap)" },
+ { "Notification", false, true, "Shows a notification on screen, specify header, then message, and optionally time in milliseconds and a icon." },
+ { "PlayDVD", false, false, "Plays the inserted CD or DVD media from the DVD-ROM Drive!" },
+ { "RipCD", false, false, "Rip the currently inserted audio CD"},
+ { "Skin.ToggleSetting", false, true, "Toggles a skin setting on or off" },
+ { "Skin.SetString", false, true, "Prompts and sets skin string" },
+ { "Skin.SetNumeric", false, true, "Prompts and sets numeric input" },
+ { "Skin.SetPath", false, true, "Prompts and sets a skin path" },
+ { "Skin.Theme", false, true, "Control skin theme" },
+ { "Skin.SetImage", false, true, "Prompts and sets a skin image" },
+ { "Skin.SetLargeImage", false, true, "Prompts and sets a large skin images" },
+ { "Skin.SetFile", false, true, "Prompts and sets a file" },
+ { "Skin.SetAddon", false, true, "Prompts and set an addon" },
+ { "Skin.SetBool", false, true, "Sets a skin setting on" },
+ { "Skin.Reset", false, true, "Resets a skin setting to default" },
+ { "Skin.ResetSettings", false, false, "Resets all skin settings" },
+ { "Mute", false, false, "Mute the player" },
+ { "SetVolume", false, true, "Set the current volume" },
+ { "Dialog.Close", false, true, "Close a dialog" },
+ { "System.LogOff", true, false, "Log off current user" },
+ { "System.Exec", true, true, "Execute shell commands" },
+ { "System.ExecWait", true, true, "Execute shell commands and freezes XBMC until shell is closed" },
+ { "Resolution", false, true, "Change XBMC's Resolution" },
+ { "SetFocus", true, true, "Change current focus to a different control id" },
+ { "UpdateLibrary", true, true, "Update the selected library (music or video)" },
+ { "CleanLibrary", true, true, "Clean the video/music library" },
+ { "ExportLibrary", true, true, "Export the video/music library" },
+ { "PageDown", false, true, "Send a page down event to the pagecontrol with given id" },
+ { "PageUp", false, true, "Send a page up event to the pagecontrol with given id" },
+ { "LastFM.Love", false, false, "Add the current playing last.fm radio track to the last.fm loved tracks" },
+ { "LastFM.Ban", false, false, "Ban the current playing last.fm radio track" },
+ { "Container.Refresh", false, false, "Refresh current listing" },
+ { "Container.Update", false, false, "Update current listing. Send Container.Update(path,replace) to reset the path history" },
+ { "Container.NextViewMode", false, false, "Move to the next view type (and refresh the listing)" },
+ { "Container.PreviousViewMode", false, false, "Move to the previous view type (and refresh the listing)" },
+ { "Container.SetViewMode", false, true, "Move to the view with the given id" },
+ { "Container.NextSortMethod", false, false, "Change to the next sort method" },
+ { "Container.PreviousSortMethod",false, false, "Change to the previous sort method" },
+ { "Container.SetSortMethod", false, true, "Change to the specified sort method" },
+ { "Container.SortDirection", false, false, "Toggle the sort direction" },
+ { "Control.Move", false, true, "Tells the specified control to 'move' to another entry specified by offset" },
+ { "Control.SetFocus", false, true, "Change current focus to a different control id" },
+ { "Control.Message", false, true, "Send a given message to a control within a given window" },
+ { "SendClick", false, true, "Send a click message from the given control to the given window" },
+ { "LoadProfile", true, true, "Load the specified profile (note; if locks are active it won't work)" },
+ { "SetProperty", false, true, "Sets a window property for the current focused window/dialog (key,value)" },
+ { "ClearProperty", false, true, "Clears a window property for the current focused window/dialog (key,value)" },
+ { "PlayWith", false, true, "Play the selected item with the specified core" },
+ { "WakeOnLan", true, true, "Sends the wake-up packet to the broadcast address for the specified MAC address" },
+ { "Addon.Default.OpenSettings", false, true, "Open a settings dialog for the default addon of the given type" },
+ { "Addon.Default.Set", false, true, "Open a select dialog to allow choosing the default addon of the given type" },
+ { "Addon.OpenSettings", false, true, "Open a settings dialog for the addon of the given id" },
+ { "UpdateAddonRepos", true, false, "Check add-on repositories for updates" },
+ { "UpdateLocalAddons", true, false, "Check for local add-on changes" },
+ { "ToggleDPMS", false, false, "Toggle DPMS mode manually"},
+ { "Weather.Refresh", false, false, "Force weather data refresh"},
+ { "Weather.LocationNext", false, false, "Switch to next weather location"},
+ { "Weather.LocationPrevious", false, false, "Switch to previous weather location"},
+ { "Weather.LocationSet", false, true, "Switch to given weather location (parameter can be 1-3)"},
#if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
- { "LIRC.Stop", false, "Removes XBMC as LIRC client" },
- { "LIRC.Start", false, "Adds XBMC as LIRC client" },
- { "LIRC.Send", true, "Sends a command to LIRC" },
+ { "LIRC.Stop", false, false, "Removes XBMC as LIRC client" },
+ { "LIRC.Start", false, false, "Adds XBMC as LIRC client" },
+ { "LIRC.Send", false, true, "Sends a command to LIRC" },
#endif
#ifdef HAS_LCD
- { "LCD.Suspend", false, "Suspends LCDproc" },
- { "LCD.Resume", false, "Resumes LCDproc" },
+ { "LCD.Suspend", false, false, "Suspends LCDproc" },
+ { "LCD.Resume", false, false, "Resumes LCDproc" },
#endif
- { "VideoLibrary.Search", false, "Brings up a search dialog which will search the library" },
+ { "VideoLibrary.Search", false, false, "Brings up a search dialog which will search the library" },
};
bool CBuiltins::HasCommand(const CStdString& execString)
@@ -215,7 +216,7 @@ bool CBuiltins::HasCommand(const CStdString& execString)
CUtil::SplitExecFunction(execString, function, parameters);
for (unsigned int i = 0; i < sizeof(commands)/sizeof(BUILT_IN); i++)
{
- if (function.CompareNoCase(commands[i].command) == 0 && (!commands[i].needsParameters || parameters.size()))
+ if (function.CompareNoCase(commands[i].command) == 0 && (!g_application.IsServerMode() || commands[i].availableInServerMode) && (!commands[i].needsParameters || parameters.size()))
return true;
}
return false;
@@ -456,7 +457,7 @@ int CBuiltins::Execute(const CStdString& execString)
{
PluginPtr plugin = boost::dynamic_pointer_cast<CPluginSource>(addon);
CStdString cmd;
- if (plugin && addon->Type() == ADDON_PLUGIN)
+ if (plugin && addon->Type() == ADDON_PLUGIN && !g_application.IsServerMode())
{
if (plugin->Provides(CPluginSource::VIDEO))
cmd.Format("ActivateWindow(Video,plugin://%s,return)",params[0]);
2  xbmc/settings/AdvancedSettings.cpp
View
@@ -131,6 +131,7 @@ void CAdvancedSettings::Initialize()
m_cddbAddress = "freedb.freedb.org";
m_handleMounting = g_application.IsStandAlone();
+ m_serverMode = g_application.IsServerMode();
m_fullScreenOnMovieStart = true;
m_cachePath = "special://temp/";
@@ -698,6 +699,7 @@ void CAdvancedSettings::ParseSettingsFile(const CStdString &file)
XMLUtils::GetBoolean(pRootElement, "handlemounting", m_handleMounting);
+ XMLUtils::GetBoolean(pRootElement, "servermode", m_serverMode);
#ifdef HAS_SDL
XMLUtils::GetBoolean(pRootElement, "fullscreen", m_startFullScreen);
1  xbmc/settings/AdvancedSettings.h
View
@@ -266,6 +266,7 @@ class CAdvancedSettings
int m_curlretries;
bool m_curlDisableIPV6;
+ bool m_serverMode;
bool m_fullScreen;
bool m_startFullScreen;
bool m_showExitButton; /* Ideal for appliances to hide a 'useless' button */
3  xbmc/settings/AppParamParser.cpp
View
@@ -94,6 +94,7 @@ void CAppParamParser::DisplayHelp()
printf(" -d <n>\t\tdelay <n> seconds before starting\n");
printf(" -fs\t\t\tRuns XBMC in full screen\n");
printf(" --standalone\t\tXBMC runs in a stand alone environment without a window \n");
+ printf(" -s or --server\t\tXBMC runs in a server mode i.e. without a gui \n");
printf("\t\t\tmanager and supporting applications. For example, that\n");
printf("\t\t\tenables network settings.\n");
printf(" -p or --portable\tXBMC will look for configurations in install folder instead of ~/.xbmc\n");
@@ -125,6 +126,8 @@ void CAppParamParser::ParseArg(const CStdString &arg)
DisplayHelp();
else if (arg == "-v" || arg == "--version")
DisplayVersion();
+ else if (arg == "-s" || arg == "--server")
+ g_application.SetServerMode(true);
else if (arg == "--standalone")
g_application.SetStandAlone(true);
else if (arg == "-p" || arg == "--portable")
Something went wrong with that request. Please try again.