Project

General

Profile

main_v3.6jwt.cc

Jim Turner, March 06, 2015 20:07

 
1
/*
2
 * main.c
3
 * Copyright 2007-2013 William Pitcock and John Lindgren
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions are met:
7
 *
8
 * 1. Redistributions of source code must retain the above copyright notice,
9
 *    this list of conditions, and the following disclaimer.
10
 *
11
 * 2. Redistributions in binary form must reproduce the above copyright notice,
12
 *    this list of conditions, and the following disclaimer in the documentation
13
 *    provided with the distribution.
14
 *
15
 * This software is provided "as is" and without any warranty, express or
16
 * implied. In no event shall the authors be liable for any damages arising from
17
 * the use of this software.
18
 */
19

    
20
#include <stdio.h>
21
#include <stdlib.h>
22
#include <string.h>
23

    
24
#include <glib.h>  /* for g_get_current_dir, g_path_is_absolute */
25

    
26
#include <libaudcore/audstrings.h>
27
#include <libaudcore/drct.h>
28
#include <libaudcore/hook.h>
29
#include <libaudcore/i18n.h>
30
#include <libaudcore/interface.h>
31
#include <libaudcore/playlist.h>
32
#include <libaudcore/runtime.h>
33
#include <libaudcore/tuple.h>
34

    
35
#ifdef USE_DBUS
36
#include "aud-dbus.h"
37
#endif
38

    
39
#include "main.h"
40
#include "util.h"
41
bool jwt_norepeat = false;  /* JWT */
42
bool resetEqState;  /* JWT:SAVE PRE-CONFIGURED STATES IF WE OR CMD-LINES ALTER (MAKE ONE-SHOT ONLY) */
43
bool resetRepeatToOn;
44
int resetDefaultGain;
45

    
46
static struct {
47
    int help, version;
48
    int play, pause, play_pause, stop, fwd, rew;
49
    int enqueue, enqueue_to_temp;
50
    int mainwin, show_jump_box;
51
    int headless, quit_after_play;
52
    int verbose;
53
    int qt;
54
    int clearplaylist, newinstance, pauseismute, forcenoequalizer, forcenogainchg, deleteallplaylists;  /* JWT */
55
} options;
56

    
57
static Index<PlaylistAddItem> filenames;
58

    
59
static const struct {
60
    const char * long_arg;
61
    char short_arg;
62
    int * value;
63
    const char * desc;
64
} arg_map[] = {
65
    {"clear", 'c', & options.clearplaylist, N_("Clear Playlist")},
66
    {"delete", 'D', & options.deleteallplaylists, N_("DELETE all playlists!")},
67
    {"enqueue", 'e', & options.enqueue, N_("Add files to the playlist")},
68
    {"enqueue-to-temp", 'E', & options.enqueue_to_temp, N_("Add files to a temporary playlist")},
69
    {"fwd", 'f', & options.fwd, N_("Skip to next song")},
70
    {"no-gain", 'g', & options.forcenogainchg, N_("Force No Gain Adjustment")},
71
    {"help", 'h', & options.help, N_("Show command-line help")},
72
    {"headless", 'H', & options.headless, N_("Start without a graphical interface")},
73
    {"show-jump-box", 'j', & options.show_jump_box, N_("Display the jump-to-song window")},
74
    {"show-main-window", 'm', & options.mainwin, N_("Display the main window")},
75
    {"new", 'n', & options.newinstance, N_("New Instance")}, 
76
      /* {"output-plugin", 'o', & options.outputplugin, N_("Set Output Plugin to <plugin>(.so)")}, */
77
    {"play", 'p', & options.play, N_("Start playback")},
78
    {"pause-mute", 'P', & options.pauseismute, N_("Pause mutes instead of pausing")},
79
    {"quit-after-play", 'q', & options.quit_after_play, N_("Quit on playback stop")},
80
#if defined(USE_QT) && defined(USE_GTK)
81
    {"qt", 'Q', & options.qt, N_("Run in Qt mode")},
82
#endif
83
    {"rew", 'r', & options.rew, N_("Skip to previous song")},
84
    {"stop", 's', & options.stop, N_("Stop playback")},
85
    {"play-pause", 't', & options.play_pause, N_("Pause if playing, play otherwise")},
86
    {"pause", 'u', & options.pause, N_("Pause playback")},
87
    {"version", 'v', & options.version, N_("Show version")},
88
    {"verbose", 'V', & options.verbose, N_("Print debugging messages (may be used twice)")},
89
    {"no-equalizer", 'z', & options.forcenoequalizer, N_("Force Equalizer Off")},
90
};
91

    
92
static bool parse_options (int argc, char * * argv)
93
{
94
    char * cur = g_get_current_dir ();
95
    bool success = true;
96

    
97
#ifdef _WIN32
98
    Index<String> args = get_argv_utf8 ();
99

    
100
    for (int n = 1; n < args.len (); n ++)
101
    {
102
        const char * arg = args[n];
103
#else
104
    for (int n = 1; n < argc; n ++)
105
    {
106
        const char * arg = argv[n];
107
#endif
108

    
109
        if (!(strcmp (arg, "-")))  /* JWT:ARG IS "-", ACCEPT LIST OF FILES TO PLAY FROM STDIN */
110
        {
111
            char lnfromstdin[1000];
112
            String uri;
113

    
114
            while (fgets (lnfromstdin, 1000 , stdin) != NULL)
115
            {
116
                lnfromstdin[strlen(lnfromstdin)-1] = '\0';
117
                if (strlen(lnfromstdin) > 1 && lnfromstdin[0] != '#')       /* filter out the comments                */
118
                {
119
                    if (strstr (lnfromstdin, "://"))
120
                        uri = String (lnfromstdin);
121
                    else if (g_path_is_absolute (lnfromstdin))
122
                        uri = String (filename_to_uri (lnfromstdin));
123
                    else
124
                        uri = String (filename_to_uri (filename_build ({cur, lnfromstdin})));
125

    
126
                    if (uri)
127
                        filenames.append (uri);
128
                }
129
            }
130
        }
131
        else if (arg[0] != '-')  /* filename */
132
        {
133
            String uri;
134

    
135
            if (strstr (arg, "://"))
136
            {
137
                uri = String (arg);
138
                if (strstr (arg, "://-."))   /* JWT:FORCE REPEAT OFF IF STREAMING FROM stdin, SINCE IMPOSSIBLE TO REWIND! */
139
                    jwt_norepeat = true;
140
            }
141
            else if (g_path_is_absolute (arg))
142
                uri = String (filename_to_uri (arg));
143
            else
144
                uri = String (filename_to_uri (filename_build ({cur, arg})));
145

    
146
            if (uri)
147
                filenames.append (uri);
148
        }
149
        else if (arg[1] == '-')  /* long option */
150
        {
151
            bool found = false;
152

    
153
            for (auto & arg_info : arg_map)
154
            {
155
                if (! strcmp (arg + 2, arg_info.long_arg))
156
                {
157
                    (* arg_info.value) ++;
158
                    found = true;
159
                    break;
160
                }
161
            }
162

    
163
            if (! found)
164
            {
165
                fprintf (stderr, _("Unknown option: %s\n"), arg);
166
                success = false;
167
                goto OUT;
168
            }
169
        }
170
        else  /* short form */
171
        {
172
            for (int c = 1; arg[c]; c ++)
173
            {
174
                bool found = false;
175

    
176
                for (auto & arg_info : arg_map)
177
                {
178
                    if (arg[c] == arg_info.short_arg)
179
                    {
180
                        (* arg_info.value) ++;
181
                        found = true;
182
                        break;
183
                    }
184
                }
185

    
186
                if (! found)
187
                {
188
                    fprintf (stderr, _("Unknown option: -%c\n"), arg[c]);
189
                    success = false;
190
                    goto OUT;
191
                }
192
            }
193
        }
194
    }
195

    
196
    aud_set_headless_mode (options.headless);
197

    
198
    if (options.verbose >= 2)
199
        audlog::set_stderr_level (audlog::Debug);
200
    else if (options.verbose)
201
        audlog::set_stderr_level (audlog::Info);
202
    if (options.pauseismute) /* JWT: ADDED 20100205 "-P" COMMAND-LINE OPTION TO ALLOW MUTING OF OUTPUT ON PAUSE (INPUT CONTINUES)! */
203
        aud_set_pausemute_mode (true);
204
    else
205
        aud_set_pausemute_mode (false);
206
    if (options.qt)
207
        aud_set_mainloop_type (MainloopType::Qt);
208

    
209
OUT:
210
    g_free (cur);
211
    return success;
212
}
213

    
214
static void print_help (void)
215
{
216
    static const char pad[21] = "                    ";
217

    
218
    fprintf (stderr, _("Usage: audacious [OPTION] ... [FILE] ...\n\n"));
219

    
220
    for (auto & arg_info : arg_map)
221
        fprintf (stderr, "  -%c, --%s%.*s%s\n", arg_info.short_arg,
222
         arg_info.long_arg, (int) (20 - strlen (arg_info.long_arg)), pad,
223
         _(arg_info.desc));
224

    
225
    fprintf (stderr, "\n");
226
}
227

    
228
#ifdef USE_DBUS
229
static void do_remote (void)
230
{
231
    GDBusConnection * bus = nullptr;
232
    ObjAudacious * obj = nullptr;
233
    GError * error = nullptr;
234

    
235
#if ! GLIB_CHECK_VERSION (2, 36, 0)
236
    g_type_init ();
237
#endif
238

    
239
    /* check whether this is the first instance */
240
    if (options.newinstance || dbus_server_init () != StartupType::Client)
241
        return;
242

    
243
    if (! (bus = g_bus_get_sync (G_BUS_TYPE_SESSION, nullptr, & error)))
244
        goto ERR;
245

    
246
    if (! (obj = obj_audacious_proxy_new_sync (bus, (GDBusProxyFlags) 0,
247
     "org.atheme.audacious", "/org/atheme/audacious", nullptr, & error)))
248
        goto ERR;
249

    
250
    AUDINFO ("Connected to remote session.\n");
251

    
252
    /* if no command line options, then present running instance */
253
    if (! (filenames.len () || options.play || options.pause ||
254
     options.play_pause || options.stop || options.rew || options.fwd ||
255
     options.show_jump_box || options.mainwin))
256
        options.mainwin = true;
257

    
258
    if (filenames.len ())
259
    {
260
        Index<const char *> list;
261

    
262
        for (auto & item : filenames)
263
            list.append (item.filename);
264

    
265
        list.append (nullptr);
266

    
267
        if (options.enqueue_to_temp)
268
            obj_audacious_call_open_list_to_temp_sync (obj, list.begin (), nullptr, nullptr);
269
        else if (options.enqueue)
270
            obj_audacious_call_add_list_sync (obj, list.begin (), nullptr, nullptr);
271
        else
272
            obj_audacious_call_open_list_sync (obj, list.begin (), nullptr, nullptr);
273
    }
274

    
275
    if (options.play)
276
        obj_audacious_call_play_sync (obj, nullptr, nullptr);
277
    if (options.pause)
278
        obj_audacious_call_pause_sync (obj, nullptr, nullptr);
279
    if (options.play_pause)
280
        obj_audacious_call_play_pause_sync (obj, nullptr, nullptr);
281
    if (options.stop)
282
        obj_audacious_call_stop_sync (obj, nullptr, nullptr);
283
    if (options.rew)
284
        obj_audacious_call_reverse_sync (obj, nullptr, nullptr);
285
    if (options.fwd)
286
        obj_audacious_call_advance_sync (obj, nullptr, nullptr);
287
    if (options.show_jump_box)
288
        obj_audacious_call_show_jtf_box_sync (obj, true, nullptr, nullptr);
289
    if (options.mainwin)
290
        obj_audacious_call_show_main_win_sync (obj, true, nullptr, nullptr);
291

    
292
    g_object_unref (obj);
293

    
294
    exit (EXIT_SUCCESS);
295

    
296
ERR:
297
    if (error)
298
    {
299
        AUDERR ("D-Bus error: %s\n", error->message);
300
        g_error_free (error);
301
    }
302
}
303
#endif
304

    
305
static void do_commands (void)
306
{
307
    bool resume = aud_get_bool (nullptr, "resume_playback_on_startup");
308

    
309
        if (options.deleteallplaylists)  /* JWT */
310
        {
311
                const char *playlist_dir = aud_get_path(AudPath::PlaylistDir);
312
                if (strstr(playlist_dir, "config")) {   /* PRECENT POTENTIAL ACCIDENTAL DELETE AGONY IF playlist WAS SOMEHOW EMPTY!!! */
313
                        AUDINFO("-D:DELETING ALL PLAYLISTS (DIR=%s)!", playlist_dir);
314
                        int i;
315
                        int playlist_count = aud_playlist_count();
316
                        for (i=playlist_count;i>=0;i--)
317
                        {
318
                                aud_playlist_delete(i);
319
                        }
320
                }
321
        }
322
    else if (options.clearplaylist)   /* JWT */
323
    {
324
        int playlist_count = aud_playlist_count();
325
        if (playlist_count > 0)
326
            aud_playlist_delete(playlist_count-1);
327
    }
328
    if (filenames.len ())
329
    {
330
        if (options.enqueue_to_temp)
331
        {
332
            aud_drct_pl_open_temp_list (std::move (filenames));
333
            resume = false;
334
        }
335
        else if (options.enqueue)
336
            aud_drct_pl_add_list (std::move (filenames), -1);
337
        else
338
        {
339
            aud_drct_pl_open_list (std::move (filenames));
340
            resume = false;
341
        }
342
    }
343

    
344
    if (resume)
345
        aud_resume ();
346

    
347
    if (options.play_pause)
348
    {
349
        if (! aud_drct_get_playing ())
350
            aud_drct_play ();
351
        else if (aud_drct_get_paused ())
352
            aud_drct_pause ();
353
    }
354
    if (options.play)  aud_drct_play ();   /* JWT - DOESN'T SEEM TO WORK?! */
355
    if (options.pause)  aud_drct_pause ();   /* JWT - DOESN'T SEEM TO WORK?! */
356

    
357
    if (options.show_jump_box && ! options.headless)
358
        aud_ui_show_jump_to_song ();
359
    if (options.mainwin && ! options.headless)
360
        aud_ui_show (true);
361
    if (options.forcenoequalizer)
362
    {
363
        resetEqState = aud_get_bool (nullptr, "equalizer_active");
364
        aud_set_bool (nullptr, "equalizer_active", false);
365
    }
366
    if (jwt_norepeat)
367
    {
368
        resetRepeatToOn = aud_get_bool (nullptr, "repeat");
369
        aud_set_bool (nullptr, "repeat", false);
370
    }
371
    if (options.forcenogainchg)
372
    {
373
        resetDefaultGain = aud_get_int (nullptr, "default_gain");
374
        aud_set_int (nullptr, "default_gain", 0);
375
    }
376
}
377

    
378
static void main_cleanup (void)
379
{
380
    filenames.clear ();
381
    aud_cleanup_paths ();
382
        
383
    aud_leak_check ();
384
}
385

    
386
static bool check_should_quit (void)
387
{
388
    return options.quit_after_play && ! aud_drct_get_playing () &&
389
     ! aud_playlist_add_in_progress (-1);
390
}
391

    
392
static void maybe_quit (void)
393
{
394
    if (check_should_quit ())
395
        aud_quit ();
396
}
397

    
398
int main (int argc, char * * argv)
399
{
400
    atexit (main_cleanup);
401

    
402
#ifdef HAVE_SIGWAIT
403
    signals_init_one ();
404
#endif
405

    
406
    aud_init_paths ();
407
    aud_init_i18n ();
408

    
409
    if (! parse_options (argc, argv))
410
    {
411
        print_help ();
412
        return EXIT_FAILURE;
413
    }
414

    
415
    if (options.help)
416
    {
417
        print_help ();
418
        return EXIT_SUCCESS;
419
    }
420

    
421
    if (options.version)
422
    {
423
        printf ("%s %s (%s)\n", _("Audacious"), VERSION, BUILDSTAMP);
424
        return EXIT_SUCCESS;
425
    }
426

    
427
#if USE_DBUS
428
    do_remote (); /* may exit */
429
#endif
430

    
431
    AUDINFO ("No remote session; starting up.\n");
432

    
433
#ifdef HAVE_SIGWAIT
434
    signals_init_two ();
435
#endif
436

    
437
    aud_init ();
438
    if (options.deleteallplaylists)  /* JWT */
439
    {
440
        const char *playlist_dir = aud_get_path(AudPath::PlaylistDir);
441
        if (strstr (playlist_dir, "config")) {   /* PRECENT POTENTIAL ACCIDENTAL DELETE AGONY IF playlist WAS SOMEHOW EMPTY!!! */
442
        AUDINFO("-D:DELETING ALL PLAYLISTS (DIR=%s)!", playlist_dir);
443
        int i;
444
        int playlist_count = aud_playlist_count();
445
        for (i=playlist_count;i>=0;i--)
446
        {
447
            aud_playlist_delete(i);
448
        }
449
    }
450
}
451

    
452
    do_commands ();
453

    
454
    if (check_should_quit ())
455
        goto QUIT;
456

    
457
    hook_associate ("playback stop", (HookFunction) maybe_quit, nullptr);
458
    hook_associate ("playlist add complete", (HookFunction) maybe_quit, nullptr);
459
    hook_associate ("quit", (HookFunction) aud_quit, nullptr);
460

    
461
    aud_run ();
462

    
463
    hook_dissociate ("playback stop", (HookFunction) maybe_quit);
464
    hook_dissociate ("playlist add complete", (HookFunction) maybe_quit);
465
    hook_dissociate ("quit", (HookFunction) aud_quit);
466

    
467
QUIT:
468
#ifdef USE_DBUS
469
    dbus_server_cleanup ();
470
#endif
471

    
472
    if (options.forcenoequalizer)
473
        aud_set_bool (nullptr, "equalizer_active", resetEqState);
474
    if (jwt_norepeat) {
475
        aud_set_bool (nullptr, "repeat", resetRepeatToOn);
476

    
477
    } if (options.forcenogainchg)
478
        aud_set_int (nullptr, "default_gain", resetDefaultGain);
479

    
480
    aud_cleanup ();
481

    
482
    return EXIT_SUCCESS;
483
}