Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Add new mythmediaserver program, using the modular protocol library, to

perform file serving duties. This runs in place of the currently
unsupported tunerless slave backend, in situations where one has content
stored on a machine for access over Storage Groups, but otherwise has no
tuners on the machine to run a proper backend.
  • Loading branch information...
commit 16d82a1e0e58249fb84e86a763575a27476f9736 1 parent 5e6340b
@wagnerrp wagnerrp authored
View
2  mythtv/libs/libmythprotoserver/requesthandler/fileserverhandler.cpp
@@ -231,8 +231,6 @@ bool FileServerHandler::HandleAnnounce(MythSocket *socket,
QUrl qurl = *(++it);
QString wantgroup = *(++it);
- VERBOSE(VB_FILE, "FIleServerHandler::HandleAnnounce: building checkfile list.");
-
QStringList checkfiles;
while (++it != slist.end())
checkfiles += *(it);
View
350 mythtv/programs/mythmediaserver/main.cpp
@@ -0,0 +1,350 @@
+
+#include <fcntl.h>
+#include <signal.h>
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <unistd.h>
+#include <cstdlib>
+#include <cstdio>
+
+#include <QCoreApplication>
+#include <QString>
+#include <QDir>
+
+#include "mythsocketmanager.h"
+#include "mythcontext.h"
+#include "exitcodes.h"
+#include "mythdbcon.h"
+#include "mythverbose.h"
+#include "mythversion.h"
+#include "mythsystemevent.h"
+#include "mythcommandlineparser.h"
+
+#include "requesthandler/basehandler.h"
+#include "requesthandler/fileserverhandler.h"
+
+#define LOC QString("MythMediaServer: ")
+#define LOC_WARN QString("MythMediaServer, Warning: ")
+#define LOC_ERR QString("MythMediaServer, Error: ")
+
+using namespace std;
+
+QString pidfile;
+QString logfile = "";
+
+static void cleanup(void)
+{
+ delete gContext;
+ gContext = NULL;
+
+ if (pidfile.size())
+ {
+ unlink(pidfile.toAscii().constData());
+ pidfile.clear();
+ }
+
+ signal(SIGHUP, SIG_DFL);
+}
+
+static int log_rotate(int report_error)
+{
+ int new_logfd = open(logfile.toLocal8Bit().constData(),
+ O_WRONLY|O_CREAT|O_APPEND|O_SYNC, 0664);
+ if (new_logfd < 0)
+ {
+ // If we can't open the new logfile, send data to /dev/null
+ if (report_error)
+ {
+ VERBOSE(VB_IMPORTANT, LOC_ERR +
+ QString("Cannot open logfile '%1'").arg(logfile));
+ return -1;
+ }
+ new_logfd = open("/dev/null", O_WRONLY);
+ if (new_logfd < 0)
+ {
+ // There's not much we can do, so punt.
+ return -1;
+ }
+ }
+ while (dup2(new_logfd, 1) < 0 && errno == EINTR) ;
+ while (dup2(new_logfd, 2) < 0 && errno == EINTR) ;
+ while (close(new_logfd) < 0 && errno == EINTR) ;
+ return 0;
+}
+
+static void log_rotate_handler(int)
+{
+ log_rotate(0);
+}
+
+namespace
+{
+ class CleanupGuard
+ {
+ public:
+ typedef void (*CleanupFunc)();
+
+ public:
+ CleanupGuard(CleanupFunc cleanFunction) :
+ m_cleanFunction(cleanFunction) {}
+
+ ~CleanupGuard()
+ {
+ m_cleanFunction();
+ }
+
+ private:
+ CleanupFunc m_cleanFunction;
+ };
+}
+
+int main(int argc, char *argv[])
+{
+ bool cmdline_err;
+ MythCommandLineParser cmdline(
+ kCLPOverrideSettingsFile |
+ kCLPOverrideSettings |
+ kCLPQueryVersion);
+
+ for (int argpos = 0; argpos < argc; ++argpos)
+ {
+ if (cmdline.PreParse(argc, argv, argpos, cmdline_err))
+ {
+ if (cmdline_err)
+ return GENERIC_EXIT_INVALID_CMDLINE;
+
+ if (cmdline.WantsToExit())
+ return GENERIC_EXIT_OK;
+ }
+ }
+
+ QCoreApplication a(argc, argv);
+ QMap<QString, QString> settingsOverride;
+ int argpos = 1;
+ bool daemonize = false;
+
+ QCoreApplication::setApplicationName(MYTH_APPNAME_MYTHJOBQUEUE);
+
+ QString filename;
+
+ while (argpos < a.argc())
+ {
+ if (!strcmp(a.argv()[argpos],"-v") ||
+ !strcmp(a.argv()[argpos],"--verbose"))
+ {
+ if (a.argc()-1 > argpos)
+ {
+ if (parse_verbose_arg(a.argv()[argpos+1]) ==
+ GENERIC_EXIT_INVALID_CMDLINE)
+ return GENERIC_EXIT_INVALID_CMDLINE;
+
+ ++argpos;
+ } else
+ {
+ cerr << "Missing argument to -v/--verbose option\n";
+ return GENERIC_EXIT_INVALID_CMDLINE;
+ }
+ }
+ else if (!strcmp(a.argv()[argpos],"-l") ||
+ !strcmp(a.argv()[argpos],"--logfile"))
+ {
+ if (a.argc() > argpos)
+ {
+ logfile = a.argv()[argpos+1];
+ if (logfile.startsWith("-"))
+ {
+ cerr << "Invalid or missing argument to -l/--logfile option\n";
+ return GENERIC_EXIT_INVALID_CMDLINE;
+ }
+ else
+ {
+ ++argpos;
+ }
+ }
+ }
+ else if (!strcmp(a.argv()[argpos],"-p") ||
+ !strcmp(a.argv()[argpos],"--pidfile"))
+ {
+ if (a.argc() > argpos)
+ {
+ pidfile = a.argv()[argpos+1];
+ if (pidfile.startsWith("-"))
+ {
+ cerr << "Invalid or missing argument to -p/--pidfile option\n";
+ return GENERIC_EXIT_INVALID_CMDLINE;
+ }
+ else
+ {
+ ++argpos;
+ }
+ }
+ }
+ else if (!strcmp(a.argv()[argpos],"-d") ||
+ !strcmp(a.argv()[argpos],"--daemon"))
+ {
+ daemonize = true;
+ }
+ else if (!strcmp(a.argv()[argpos],"-O") ||
+ !strcmp(a.argv()[argpos],"--override-setting"))
+ {
+ if ((a.argc() - 1) > argpos)
+ {
+ QString tmpArg = a.argv()[argpos+1];
+ if (tmpArg.startsWith("-"))
+ {
+ cerr << "Invalid or missing argument to "
+ "-O/--override-setting option\n";
+ return GENERIC_EXIT_INVALID_CMDLINE;
+ }
+
+ QStringList pairs = tmpArg.split(",");
+ for (int index = 0; index < pairs.size(); ++index)
+ {
+ QStringList tokens = pairs[index].split("=");
+ tokens[0].replace(QRegExp("^[\"']"), "");
+ tokens[0].replace(QRegExp("[\"']$"), "");
+ tokens[1].replace(QRegExp("^[\"']"), "");
+ tokens[1].replace(QRegExp("[\"']$"), "");
+ settingsOverride[tokens[0]] = tokens[1];
+ }
+ }
+ else
+ {
+ cerr << "Invalid or missing argument to -O/--override-setting "
+ "option\n";
+ return GENERIC_EXIT_INVALID_CMDLINE;
+ }
+
+ ++argpos;
+ }
+ else if (!strcmp(a.argv()[argpos],"-h") ||
+ !strcmp(a.argv()[argpos],"--help"))
+ {
+ cerr << "Valid Options are:" << endl <<
+ "-v or --verbose debug-level Use '-v help' for level info" << endl <<
+ "-l or --logfile filename Writes STDERR and STDOUT messages to filename" << endl <<
+ "-p or --pidfile filename Write PID of mythmediaserver to filename " << endl <<
+ "-d or --daemon Runs mythmediaserver as a daemon" << endl <<
+ endl;
+ return GENERIC_EXIT_INVALID_CMDLINE;
+ }
+ else if (cmdline.Parse(a.argc(), a.argv(), argpos, cmdline_err))
+ {
+ if (cmdline_err)
+ return GENERIC_EXIT_INVALID_CMDLINE;
+
+ if (cmdline.WantsToExit())
+ return GENERIC_EXIT_OK;
+ }
+ else
+ {
+ printf("illegal option: '%s' (use --help)\n", a.argv()[argpos]);
+ return GENERIC_EXIT_INVALID_CMDLINE;
+ }
+
+ ++argpos;
+ }
+
+ if (!logfile.isEmpty())
+ {
+ if (log_rotate(1) < 0)
+ {
+ VERBOSE(VB_IMPORTANT, LOC_WARN +
+ "Cannot open logfile; using stdout/stderr instead");
+ }
+ else
+ signal(SIGHUP, &log_rotate_handler);
+ }
+
+ CleanupGuard callCleanup(cleanup);
+
+ ofstream pidfs;
+ if (pidfile.size())
+ {
+ pidfs.open(pidfile.toAscii().constData());
+ if (!pidfs)
+ {
+ VERBOSE(VB_IMPORTANT, LOC_ERR +
+ "Could not open pid file" + ENO);
+ return GENERIC_EXIT_PERMISSIONS_ERROR;
+ }
+ }
+
+ if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
+ VERBOSE(VB_IMPORTANT, LOC_WARN + "Unable to ignore SIGPIPE");
+
+ if (daemonize && (daemon(0, 1) < 0))
+ {
+ VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to daemonize" + ENO);
+ return GENERIC_EXIT_DAEMONIZING_ERROR;
+ }
+
+ if (pidfs)
+ {
+ pidfs << getpid() << endl;
+ pidfs.close();
+ }
+
+ VERBOSE(VB_IMPORTANT, QString("%1 version: %2 [%3] www.mythtv.org")
+ .arg(MYTH_APPNAME_MYTHJOBQUEUE)
+ .arg(MYTH_SOURCE_PATH)
+ .arg(MYTH_SOURCE_VERSION));
+
+ gContext = new MythContext(MYTH_BINARY_VERSION);
+ if (!gContext->Init(false))
+ {
+ VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to init MythContext, exiting.");
+ return GENERIC_EXIT_NO_MYTHCONTEXT;
+ }
+
+ if (settingsOverride.size())
+ {
+ QMap<QString, QString>::iterator it;
+ for (it = settingsOverride.begin(); it != settingsOverride.end(); ++it)
+ {
+ VERBOSE(VB_IMPORTANT, QString("Setting '%1' being forced to '%2'")
+ .arg(it.key()).arg(*it));
+ gCoreContext->OverrideSettingForSession(it.key(), *it);
+ }
+ }
+
+ if (!gCoreContext->ConnectToMasterServer())
+ {
+ VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to connect to master server");
+ return GENERIC_EXIT_CONNECT_ERROR;
+ }
+
+ QString myip = gCoreContext->GetSetting("BackendServerIP");
+ int port = gCoreContext->GetNumSetting("BackendServerPort", 6543);
+ if (myip.isEmpty())
+ {
+ cerr << "No setting found for this machine's BackendServerIP.\n"
+ << "Please run setup on this machine and modify the first page\n"
+ << "of the general settings.\n";
+ return GENERIC_EXIT_SETUP_ERROR;
+ }
+
+ MythSocketManager *sockmanager = new MythSocketManager();
+ if (!sockmanager->Listen(port))
+ {
+ VERBOSE(VB_IMPORTANT, "Mediaserver exiting, failed to bind to listen port.");
+ delete sockmanager;
+ return GENERIC_EXIT_SOCKET_ERROR;
+ }
+
+ sockmanager->RegisterHandler(new BaseRequestHandler());
+ sockmanager->RegisterHandler(new FileServerHandler());
+
+ MythSystemEventHandler *sysEventHandler = new MythSystemEventHandler();
+
+ int exitCode = a.exec();
+
+ if (sysEventHandler)
+ delete sysEventHandler;
+
+ return exitCode ? exitCode : GENERIC_EXIT_OK;
+}
+
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
View
BIN  mythtv/programs/mythmediaserver/mythmediaserver
Binary file not shown
View
17 mythtv/programs/mythmediaserver/mythmediaserver.pro
@@ -0,0 +1,17 @@
+include ( ../../settings.pro )
+include ( ../../version.pro )
+include ( ../programs-libs.pro )
+
+QT += network sql
+
+TEMPLATE = app
+CONFIG += thread
+TARGET = mythmediaserver
+target.path = $${PREFIX}/bin
+INSTALLS = target
+
+QMAKE_CLEAN += $(TARGET)
+
+# Input
+
+SOURCES += main.cpp
View
6 mythtv/programs/programs-libs.pro
@@ -6,6 +6,7 @@ INCLUDEPATH += ../../libs/libmythdvdnav ../../libs/libmythbluray ../../libs/libm
INCLUDEPATH += ../../libs/libmythtv/mpeg
INCLUDEPATH += ../../libs/libmythtv/vbitext
INCLUDEPATH += ../../libs/libmythservicecontracts
+INCLUDEPATH += ../../libs/libmythprotoserver
LIBS += -L../../libs/libmyth -L../../libs/libmythtv
LIBS += -L../../external/FFmpeg/libavutil
@@ -17,6 +18,7 @@ LIBS += -L../../libs/libmythui
LIBS += -L../../libs/libmythupnp
LIBS += -L../../libs/libmythmetadata
LIBS += -L../../libs/libmythservicecontracts
+LIBS += -L../../libs/libmythprotoserver
LIBS += -lmythtv-$$LIBVERSION
LIBS += -lmythswscale
@@ -29,6 +31,7 @@ LIBS += -lmythui-$$LIBVERSION
LIBS += -lmyth-$$LIBVERSION
LIBS += -lmythmetadata-$$LIBVERSION
LIBS += -lmythservicecontracts-$$LIBVERSION
+LIBS += -lmythprotoserver-$$LIBVERSION
using_live:LIBS += -L../../libs/libmythlivemedia -lmythlivemedia-$$LIBVERSION
using_mheg:LIBS += -L../../libs/libmythfreemheg -lmythfreemheg-$$LIBVERSION
@@ -48,6 +51,7 @@ POST_TARGETDEPS += ../../external/FFmpeg/libswscale/$$avLibName(swscale)
POST_TARGETDEPS += ../../libs/libmythupnp/libmythupnp-$${MYTH_SHLIB_EXT}
POST_TARGETDEPS += ../../libs/libmythbase/libmythbase-$${MYTH_SHLIB_EXT}
POST_TARGETDEPS += ../../libs/libmythservicecontracts/libmythservicecontracts-$${MYTH_SHLIB_EXT}
+POST_TARGETDEPS += ../../libs/libmythprotoserver/libmythprotoserver-$${MYTH_SHLIB_EXT}
using_live: POST_TARGETDEPS += ../../libs/libmythlivemedia/libmythlivemedia-$${MYTH_SHLIB_EXT}
using_hdhomerun: POST_TARGETDEPS += ../../libs/libmythhdhomerun/libmythhdhomerun-$${MYTH_SHLIB_EXT}
@@ -57,7 +61,7 @@ DEPENDPATH += ../../libs/libmythtv/mpeg ../../libs/libmythtv/vbitext
DEPENDPATH += ../../external/FFmpeg
DEPENDPATH += ../../libs/libmythupnp ../../libs/libmythui
DEPENDPATH += ../../libs/libmythlivemedia ../../libmythbase ../../libmythhdhomerun
-DEPENDPATH +=../../libs/libmythservicecontracts
+DEPENDPATH +=../../libs/libmythservicecontracts ../../libs/libmythprotoserver
using_opengl:CONFIG += opengl
View
2  mythtv/programs/programs.pro
@@ -7,7 +7,7 @@ using_frontend {
SUBDIRS += mythavtest mythfrontend mythcommflag
SUBDIRS += mythmessage mythjobqueue mythlcdserver
SUBDIRS += mythwelcome mythshutdown
- SUBDIRS += mythpreviewgen
+ SUBDIRS += mythpreviewgen mythmediaserver
!mingw: SUBDIRS += mythtranscode/replex
}
Please sign in to comment.
Something went wrong with that request. Please try again.