Switch to unified view

a/src/main.cxx b/src/main.cxx
...
...
49
using namespace UPnPP;
49
using namespace UPnPP;
50
50
51
static char *thisprog;
51
static char *thisprog;
52
52
53
static int op_flags;
53
static int op_flags;
54
#define OPT_MOINS 0x1
54
#define OPT_MOINS 0x1   
55
#define OPT_h     0x2
55
#define OPT_D     0x2   
56
#define OPT_p     0x4
56
#define OPT_O     0x4   
57
#define OPT_d     0x8
57
#define OPT_P     0x8   
58
#define OPT_D     0x10
58
#define OPT_c     0x10  
59
#define OPT_c     0x20
59
#define OPT_d     0x20  
60
#define OPT_l     0x40
60
#define OPT_f     0x40  
61
#define OPT_f     0x80
61
#define OPT_h     0x80  
62
#define OPT_i     0x100 
63
#define OPT_l     0x200 
64
#define OPT_m     0x400 
65
#define OPT_p     0x800 
62
#define OPT_q     0x100
66
#define OPT_q     0x1000
63
#define OPT_i     0x200
64
#define OPT_P     0x400
65
#define OPT_O     0x800
66
#define OPT_v     0x1000
67
#define OPT_v     0x2000
67
68
68
static const char usage[] = 
69
static const char usage[] = 
69
    "-c configfile \t configuration file to use\n"
70
    "-c configfile \t configuration file to use\n"
70
    "-h host    \t specify host MPD is running on\n"
71
    "-h host    \t specify host MPD is running on\n"
71
    "-p port     \t specify MPD port\n"
72
    "-p port     \t specify MPD port\n"
...
...
76
    "-q 0|1\t if set, we own the mpd queue, else avoid clearing it whenever we feel like it\n"
77
    "-q 0|1\t if set, we own the mpd queue, else avoid clearing it whenever we feel like it\n"
77
    "-i iface    \t specify network interface name to be used for UPnP\n"
78
    "-i iface    \t specify network interface name to be used for UPnP\n"
78
    "-P upport    \t specify port number to be used for UPnP\n"
79
    "-P upport    \t specify port number to be used for UPnP\n"
79
    "-O 0|1\t decide if we run and export the OpenHome services\n"
80
    "-O 0|1\t decide if we run and export the OpenHome services\n"
80
    "-v      \tprint version info\n"
81
    "-v      \tprint version info\n"
82
    "-m <0|1|2|3> media server mode "
83
    "(default, forked|only renderer|only media|combined)\n"
81
    "\n"
84
    "\n"
82
    ;
85
    ;
86
87
enum MSMode {Forked, RdrOnly, MSOnly, Combined};
83
88
84
static void
89
static void
85
versionInfo(FILE *fp)
90
versionInfo(FILE *fp)
86
{
91
{
87
    fprintf(fp, "Upmpdcli %s %s\n",
92
    fprintf(fp, "Upmpdcli %s %s\n",
...
...
160
        }
165
        }
161
}
166
}
162
167
163
int main(int argc, char *argv[])
168
int main(int argc, char *argv[])
164
{
169
{
170
    vector<string> savedargs;
171
    for (int i = 0; i < argc; i++) {
172
        savedargs.push_back(argv[i]);
173
    }
174
    
165
    // Path for the sc2mpd command, or empty
175
    // Path for the sc2mpd command, or empty
166
    string sc2mpdpath;
176
    string sc2mpdpath;
167
177
168
    // Sender mode: path for the command creating the mpd and mpd2sc
178
    // Sender mode: path for the command creating the mpd and mpd2sc
169
    // processes, and port for the auxiliary mpd.
179
    // processes, and port for the auxiliary mpd.
...
...
188
    string iconpath(DATADIR "/icon.png");
198
    string iconpath(DATADIR "/icon.png");
189
    string presentationhtml(DATADIR "/presentation.html");
199
    string presentationhtml(DATADIR "/presentation.html");
190
    string iface;
200
    string iface;
191
    unsigned short upport = 0;
201
    unsigned short upport = 0;
192
    string upnpip;
202
    string upnpip;
193
203
    int msm = 0;
204
    bool inprocessms = false;
205
    bool msonly = false;
206
    
194
    const char *cp;
207
    const char *cp;
195
    if ((cp = getenv("UPMPD_HOST")))
208
    if ((cp = getenv("UPMPD_HOST")))
196
        mpdhost = cp;
209
        mpdhost = cp;
197
    if ((cp = getenv("UPMPD_PORT")))
210
    if ((cp = getenv("UPMPD_PORT")))
198
        mpdport = atoi(cp);
211
        mpdport = atoi(cp);
...
...
224
                mpdhost = *(++argv); argc--; goto b1;
237
                mpdhost = *(++argv); argc--; goto b1;
225
            case 'i':   op_flags |= OPT_i; if (argc < 2)  Usage();
238
            case 'i':   op_flags |= OPT_i; if (argc < 2)  Usage();
226
                iface = *(++argv); argc--; goto b1;
239
                iface = *(++argv); argc--; goto b1;
227
            case 'l':   op_flags |= OPT_l; if (argc < 2)  Usage();
240
            case 'l':   op_flags |= OPT_l; if (argc < 2)  Usage();
228
                loglevel = atoi(*(++argv)); argc--; goto b1;
241
                loglevel = atoi(*(++argv)); argc--; goto b1;
242
            case 'm':   op_flags |= OPT_m; if (argc < 2)  Usage();
243
                msm = atoi(*(++argv)); argc--; goto b1;
229
            case 'O': {
244
            case 'O': {
230
                op_flags |= OPT_O; 
245
                op_flags |= OPT_O; 
231
                if (argc < 2)  Usage();
246
                if (argc < 2)  Usage();
232
                const char *cp =  *(++argv);
247
                const char *cp =  *(++argv);
233
                if (*cp == '1' || *cp == 't' || *cp == 'T' || *cp == 'y' || 
248
                if (*cp == '1' || *cp == 't' || *cp == 'T' || *cp == 'y' || 
...
...
245
            default: Usage();   break;
260
            default: Usage();   break;
246
            }
261
            }
247
    b1: argc--; argv++;
262
    b1: argc--; argv++;
248
    }
263
    }
249
264
250
    if (argc != 0)
265
    if (argc != 0 || msm < 0 || msm > 3) {
251
        Usage();
266
        Usage();
252
267
    }
268
    MSMode msmode = MSMode(msm);
269
    
253
    UpMpd::Options opts;
270
    UpMpd::Options opts;
254
271
255
    string cachedir;
272
    string cachedir;
256
    if (!g_configfilename.empty()) {
273
    if (!g_configfilename.empty()) {
257
        g_config = new ConfSimple(g_configfilename.c_str(), 1, true);
274
        g_config = new ConfSimple(g_configfilename.c_str(), 1, true);
...
...
344
361
345
        g_config->get("scsenderpath", senderpath);
362
        g_config->get("scsenderpath", senderpath);
346
        if (g_config->get("scsendermpdport", value))
363
        if (g_config->get("scsendermpdport", value))
347
            sendermpdport = atoi(value.c_str());
364
            sendermpdport = atoi(value.c_str());
348
365
366
        // If a streaming service is enabled (only tidal for now), we
367
        // need a Media Server. The way we implement it depends on the
368
        // command line option:
349
        if (g_config->hasNameAnywhere("tidaluser")) {
369
        if (g_config->hasNameAnywhere("tidaluser")) {
350
            enableMediaServer = true;
370
            enableMediaServer = true;
371
            switch (msmode) {
372
            case MSOnly:
373
                inprocessms = true;
374
                msonly = true;
375
                break;
376
            case Combined:
377
                inprocessms = true;
378
                msonly = false;
379
                break;
380
            case RdrOnly:
381
            case Forked:
382
            default:
383
                inprocessms = false;
384
                msonly = false;
385
                break;
386
            }
351
        }
387
        }
352
    }
388
    }
353
    if (Logger::getTheLog(logfilename) == 0) {
389
    if (Logger::getTheLog(logfilename) == 0) {
354
        cerr << "Can't initialize log" << endl;
390
        cerr << "Can't initialize log" << endl;
355
        return 1;
391
        return 1;
...
...
548
    }
584
    }
549
585
550
    // Create unique ID
586
    // Create unique ID
551
    string UUID = LibUPnP::makeDevUUID(friendlyname, hwaddr);
587
    string UUID = LibUPnP::makeDevUUID(friendlyname, hwaddr);
552
588
589
    // If running as mediaserver only, make sure we don't conflict
590
    // with a possible renderer
591
    if (msonly) {
592
        pidfilename = pidfilename + "-ms";
593
    }
594
553
    // Initialize the data we serve through HTTP (device and service
595
    // Initialize the data we serve through HTTP (device and service
554
    // descriptions, icons, presentation page, etc.)
596
    // descriptions, icons, presentation page, etc.)
555
    unordered_map<string, VDirContent> files;
597
    unordered_map<string, VDirContent> files;
556
    if (!initHttpFs(files, g_datadir, UUID, friendlyname, enableAV, enableOH,
598
    if (!initHttpFs(files, g_datadir, UUID, friendlyname, enableAV, enableOH,
557
                    !senderpath.empty(), enableL16, enableMediaServer, 
599
                    !senderpath.empty(), enableL16, inprocessms,
558
                    iconpath, presentationhtml)) {
600
                    msonly, iconpath, presentationhtml)) {
559
        exit(1);
601
        exit(1);
560
    }
602
    }
561
603
562
    if (ownqueue)
604
    if (ownqueue)
563
        opts.options |= UpMpd::upmpdOwnQueue;
605
        opts.options |= UpMpd::upmpdOwnQueue;
...
...
577
619
578
    if (!enableAV)
620
    if (!enableAV)
579
        opts.options |= UpMpd::upmpdNoAV;
621
        opts.options |= UpMpd::upmpdNoAV;
580
622
581
    // Initialize the UPnP root device object. 
623
    // Initialize the UPnP root device object. 
582
    UpMpd device(string("uuid:") + UUID, friendlyname, ohProductDesc,
624
    UpMpd *mediarenderer = nullptr;
583
                 files, mpdclip, opts);
625
    if (!msonly) {
584
    dev = &device;
626
        mediarenderer = new UpMpd(string("uuid:") + UUID, friendlyname,
627
                                  ohProductDesc, files, mpdclip, opts);
628
    }
585
629
586
    MediaServer *devmedia = nullptr;
630
    MediaServer *mediaserver = nullptr;
587
    if (enableMediaServer) {
631
    unordered_map<string, VDirContent> emptyfiles =
632
        unordered_map<string, VDirContent>();
633
    unordered_map<string, VDirContent> *msfiles = &emptyfiles;
634
    vector<string> args{"-m", "2"};
635
    ExecCmd cmd;
636
    
637
    if (inprocessms) {
638
        if (op_flags & OPT_m) {
639
            msfiles = &files;
640
        }
588
    // Create the Media Server embedded device object. There needs
641
    // Create the Media Server embedded device object. There needs
589
    // be no reference to the root object because there can be
642
    // be no reference to the root object because there can be
590
    // only one (libupnp restriction)
643
    // only one (libupnp restriction)
591
    devmedia = new MediaServer(string("uuid:") + uuidMediaServer(UUID),
644
    mediaserver = new MediaServer(string("uuid:") + uuidMediaServer(UUID),
592
                 friendlyNameMediaServer(friendlyname));
645
                                      friendlyNameMediaServer(friendlyname),
646
                                      *msfiles);
647
    } else if (enableMediaServer) {
648
        // Fork process for media server, replacing whatever -m option
649
        // was given with -m 2 (ms only)
650
        string cmdpath(savedargs[0]);
651
        for (unsigned int i = 1; i < savedargs.size(); i++) {
652
            string sa(savedargs[i]);
653
            if (sa[sa.length()-1] == 'm') {
654
                sa = sa.substr(0, sa.length()-1);
655
                if (int(i) == argc -1)
656
                    Usage();
657
                i++;
658
            }
659
            if (!sa.empty() && sa.compare("-")) {
660
                args.push_back(sa);
661
            }
593
    }
662
        }
663
        cmd.startExec(cmdpath, args, false, false);
664
    }
594
    UPMPD_UNUSED(devmedia);
665
    UPMPD_UNUSED(mediaserver);
595
    
666
    
596
    // And forever generate state change events.
667
    // And forever generate state change events.
597
    LOGDEB("Entering event loop" << endl);
668
    LOGDEB("Entering event loop" << endl);
598
    setupsigs();
669
    setupsigs();
599
    device.eventloop();
670
    if (msonly) {
671
        dev = mediaserver;
672
        LOGDEB("Media server event loop" << endl);
673
        mediaserver->eventloop();
674
    } else {
675
        LOGDEB("Renderer event loop" << endl);
676
        dev = mediarenderer;
677
        mediarenderer->eventloop();
678
    }
600
    LOGDEB("Event loop returned" << endl);
679
    LOGDEB("Event loop returned" << endl);
601
602
    return 0;
680
    return 0;
603
}
681
}