|
a/src/main.cxx |
|
b/src/main.cxx |
|
... |
|
... |
42 |
#include "upmpd.hxx"
|
42 |
#include "upmpd.hxx"
|
43 |
#include "mediaserver.hxx"
|
43 |
#include "mediaserver.hxx"
|
44 |
#include "httpfs.hxx"
|
44 |
#include "httpfs.hxx"
|
45 |
#include "upmpdutils.hxx"
|
45 |
#include "upmpdutils.hxx"
|
46 |
#include "pathut.h"
|
46 |
#include "pathut.h"
|
|
|
47 |
#include "contentdirectory.hxx"
|
47 |
|
48 |
|
48 |
using namespace std;
|
49 |
using namespace std;
|
49 |
using namespace UPnPP;
|
50 |
using namespace UPnPP;
|
50 |
|
51 |
|
51 |
static char *thisprog;
|
52 |
static char *thisprog;
|
|
... |
|
... |
82 |
"-m <0|1|2|3> media server mode "
|
83 |
"-m <0|1|2|3> media server mode "
|
83 |
"(default, forked|only renderer|only media|combined)\n"
|
84 |
"(default, forked|only renderer|only media|combined)\n"
|
84 |
"\n"
|
85 |
"\n"
|
85 |
;
|
86 |
;
|
86 |
|
87 |
|
|
|
88 |
// We can implement a Media Server in addition to the Renderer, for
|
|
|
89 |
// accessing streaming services. This can happen in several modes. In
|
|
|
90 |
// all cases, the Media Server is only created if the configuration
|
|
|
91 |
// file does have parameters set for streaming services.
|
|
|
92 |
// All this complication is needed because libupnp does not support
|
|
|
93 |
// having several root devices in a single process, and because many
|
|
|
94 |
// control points are confused by embedded devices.
|
|
|
95 |
//
|
|
|
96 |
// - -m 0, default, Forked: this is for the main process, which will
|
|
|
97 |
// implement a Media Renderer device, and, if needed, fork/exec the
|
|
|
98 |
// Media Server (with option -m 2)
|
|
|
99 |
// - -m 1, RdrOnly: for the main instance: be a Renderer, do not start the
|
|
|
100 |
// Media Server even if the configuration indicates it is needed
|
|
|
101 |
// (this is not used in normal situations, just edit the config
|
|
|
102 |
// instead!)
|
|
|
103 |
// - -m 2, MSOnly Media Server only, this is for the process forked/execed
|
|
|
104 |
// by a main Renderer process.
|
|
|
105 |
// - -m 3, Combined: for the main process: implement the Media Server
|
|
|
106 |
// as an embedded device. This works just fine with, for example,
|
|
|
107 |
// upplay, but confuses most of the other Control Points.
|
87 |
enum MSMode {Forked, RdrOnly, MSOnly, Combined};
|
108 |
enum MSMode {Forked, RdrOnly, MSOnly, Combined};
|
88 |
|
109 |
|
89 |
static void
|
110 |
static void
|
90 |
versionInfo(FILE *fp)
|
111 |
versionInfo(FILE *fp)
|
91 |
{
|
112 |
{
|
|
... |
|
... |
361 |
|
382 |
|
362 |
g_config->get("scsenderpath", senderpath);
|
383 |
g_config->get("scsenderpath", senderpath);
|
363 |
if (g_config->get("scsendermpdport", value))
|
384 |
if (g_config->get("scsendermpdport", value))
|
364 |
sendermpdport = atoi(value.c_str());
|
385 |
sendermpdport = atoi(value.c_str());
|
365 |
|
386 |
|
366 |
// If a streaming service is enabled (only tidal for now), we
|
387 |
// If a streaming service is enabled, we need a Media
|
367 |
// need a Media Server. The way we implement it depends on the
|
388 |
// Server. We let a static ContentDirectory method decide this
|
368 |
// command line option:
|
389 |
// for us. The way we then implement it depends on the command
|
369 |
if (g_config->hasNameAnywhere("tidaluser") ||
|
390 |
// line option (see the enum comments near the top of the file):
|
370 |
g_config->hasNameAnywhere("qobuzuser")) {
|
391 |
enableMediaServer = ContentDirectory::mediaServerNeeded();
|
371 |
enableMediaServer = true;
|
392 |
if (enableMediaServer) {
|
372 |
switch (msmode) {
|
393 |
switch (msmode) {
|
373 |
case MSOnly:
|
394 |
case MSOnly:
|
374 |
inprocessms = true;
|
395 |
inprocessms = true;
|
375 |
msonly = true;
|
396 |
msonly = true;
|
376 |
break;
|
397 |
break;
|
|
... |
|
... |
385 |
msonly = false;
|
406 |
msonly = false;
|
386 |
break;
|
407 |
break;
|
387 |
}
|
408 |
}
|
388 |
}
|
409 |
}
|
389 |
}
|
410 |
}
|
|
|
411 |
|
390 |
if (Logger::getTheLog(logfilename) == 0) {
|
412 |
if (Logger::getTheLog(logfilename) == 0) {
|
391 |
cerr << "Can't initialize log" << endl;
|
413 |
cerr << "Can't initialize log" << endl;
|
392 |
return 1;
|
414 |
return 1;
|
393 |
}
|
415 |
}
|
394 |
Logger::getTheLog("")->setLogLevel(Logger::LogLevel(loglevel));
|
416 |
Logger::getTheLog("")->setLogLevel(Logger::LogLevel(loglevel));
|
|
... |
|
... |
424 |
if (cachedir.empty())
|
446 |
if (cachedir.empty())
|
425 |
cachedir = path_cat(path_tildexpand("~") , "/.cache/upmpdcli");
|
447 |
cachedir = path_cat(path_tildexpand("~") , "/.cache/upmpdcli");
|
426 |
}
|
448 |
}
|
427 |
|
449 |
|
428 |
string& mcfn = opts.cachefn;
|
450 |
string& mcfn = opts.cachefn;
|
|
|
451 |
// no cache access needed or desirable for a pure media renderer
|
429 |
if (ohmetapersist) {
|
452 |
if (!msonly && ohmetapersist) {
|
430 |
opts.cachefn = path_cat(cachedir, "/metacache");
|
453 |
opts.cachefn = path_cat(cachedir, "/metacache");
|
431 |
if (!path_makepath(cachedir, 0755)) {
|
454 |
if (!path_makepath(cachedir, 0755)) {
|
432 |
LOGERR("makepath("<< cachedir << ") : errno : " << errno << endl);
|
455 |
LOGERR("makepath("<< cachedir << ") : errno : " << errno << endl);
|
433 |
} else {
|
456 |
} else {
|
434 |
int fd;
|
457 |
int fd;
|
|
... |
|
... |
438 |
close(fd);
|
461 |
close(fd);
|
439 |
if (geteuid() == 0 && chown(mcfn.c_str(), runas, -1) != 0) {
|
462 |
if (geteuid() == 0 && chown(mcfn.c_str(), runas, -1) != 0) {
|
440 |
LOGERR("chown("<< mcfn << ") : errno : " << errno << endl);
|
463 |
LOGERR("chown("<< mcfn << ") : errno : " << errno << endl);
|
441 |
}
|
464 |
}
|
442 |
if (geteuid() == 0 && chown(cachedir.c_str(), runas, -1) != 0) {
|
465 |
if (geteuid() == 0 && chown(cachedir.c_str(), runas, -1) != 0) {
|
443 |
LOGERR("chown("<< cachedir << ") : errno : " << errno << endl);
|
466 |
LOGERR("chown("<< cachedir << ") : errno : " <<errno<< endl);
|
444 |
}
|
467 |
}
|
445 |
}
|
468 |
}
|
446 |
}
|
469 |
}
|
447 |
}
|
470 |
}
|
448 |
|
471 |
|