Пример #1
0
static void
mainloop_thread (void *ctx) {
    // this runs until DB_EV_TERMINATE is sent (blocks right here)
    player_mainloop ();

    // tell the gui thread to finish
    DB_plugin_t *gui = plug_get_gui ();
    if (gui) {
        gui->stop ();
    }
    return;
}
Пример #2
0
int
main (int argc, char *argv[]) {
#if PORTABLE
    strcpy (dbinstalldir, argv[0]);
    char *e = dbinstalldir + strlen (dbinstalldir);
    while (e >= dbinstalldir && *e != '/') {
        e--;
    }
    *e = 0;
#else
    strcpy (dbinstalldir, PREFIX);
#endif

#ifdef __linux__
    signal (SIGSEGV, sigsegv_handler);
#endif
    setlocale (LC_ALL, "");
    setlocale (LC_NUMERIC, "C");
#ifdef ENABLE_NLS
//    fprintf (stderr, "enabling gettext support: package=" PACKAGE ", dir=" LOCALEDIR "...\n");
#if PORTABLE
    char localedir[PATH_MAX];
    snprintf (localedir, sizeof (localedir), "%s/locale", dbinstalldir);
	bindtextdomain (PACKAGE, localedir);
#else
	bindtextdomain (PACKAGE, LOCALEDIR);
#endif
	bind_textdomain_codeset (PACKAGE, "UTF-8");
	textdomain (PACKAGE);
#endif

    int staticlink = 0;
    int portable = 0;
#if STATICLINK
    staticlink = 1;
#endif
#if PORTABLE
    portable = 1;
#endif

    fprintf (stderr, "starting deadbeef " VERSION "%s%s\n", staticlink ? " [static]" : "", portable ? " [portable]" : "");
    srand (time (NULL));
#ifdef __linux__
    prctl (PR_SET_NAME, "deadbeef-main", 0, 0, 0, 0);
#endif

#if PORTABLE_FULL
    if (snprintf (confdir, sizeof (confdir), "%s/config", dbinstalldir) > sizeof (confdir)) {
        fprintf (stderr, "fatal: too long install path %s\n", dbinstalldir);
        return -1;
    }

    strcpy (dbconfdir, confdir);
#else
    char *homedir = getenv ("HOME");
    if (!homedir) {
        fprintf (stderr, "unable to find home directory. stopping.\n");
        return -1;
    }

    char *xdg_conf_dir = getenv ("XDG_CONFIG_HOME");
    if (xdg_conf_dir) {
        if (snprintf (confdir, sizeof (confdir), "%s", xdg_conf_dir) > sizeof (confdir)) {
            fprintf (stderr, "fatal: XDG_CONFIG_HOME value is too long: %s\n", xdg_conf_dir);
            return -1;
        }
    }
    else {
        if (snprintf (confdir, sizeof (confdir), "%s/.config", homedir) > sizeof (confdir)) {
            fprintf (stderr, "fatal: HOME value is too long: %s\n", homedir);
            return -1;
        }
    }
    if (snprintf (dbconfdir, sizeof (dbconfdir), "%s/deadbeef", confdir) > sizeof (dbconfdir)) {
        fprintf (stderr, "fatal: out of memory while configuring\n");
        return -1;
    }
    mkdir (confdir, 0755);
#endif


#if PORTABLE
    if (snprintf (dbdocdir, sizeof (dbdocdir), "%s/doc", dbinstalldir) > sizeof (dbdocdir)) {
        fprintf (stderr, "fatal: too long install path %s\n", dbinstalldir);
        return -1;
    }
    if (snprintf (dbplugindir, sizeof (dbplugindir), "%s/plugins", dbinstalldir) > sizeof (dbplugindir)) {
        fprintf (stderr, "fatal: too long install path %s\n", dbinstalldir);
        return -1;
    }
    if (snprintf (dbpixmapdir, sizeof (dbpixmapdir), "%s/pixmaps", dbinstalldir) > sizeof (dbpixmapdir)) {
        fprintf (stderr, "fatal: too long install path %s\n", dbinstalldir);
        return -1;
    }
    mkdir (dbplugindir, 0755);
#else
    if (snprintf (dbdocdir, sizeof (dbdocdir), "%s", DOCDIR) > sizeof (dbdocdir)) {
        fprintf (stderr, "fatal: too long install path %s\n", dbinstalldir);
        return -1;
    }
    if (snprintf (dbplugindir, sizeof (dbplugindir), "%s/deadbeef", LIBDIR) > sizeof (dbplugindir)) {
        fprintf (stderr, "fatal: too long install path %s\n", dbinstalldir);
        return -1;
    }
    if (snprintf (dbpixmapdir, sizeof (dbpixmapdir), "%s/share/deadbeef/pixmaps", PREFIX) > sizeof (dbpixmapdir)) {
        fprintf (stderr, "fatal: too long install path %s\n", dbinstalldir);
        return -1;
    }
#endif

    for (int i = 1; i < argc; i++) {
        // help, version and nowplaying are executed with any filter
        if (!strcmp (argv[i], "--help") || !strcmp (argv[i], "-h")) {
            print_help ();
            return 0;
        }
        else if (!strcmp (argv[i], "--version")) {
            fprintf (stdout, "DeaDBeeF " VERSION " Copyright © 2009-2011 Alexey Yakovenko\n");
            return 0;
        }
        else if (!strcmp (argv[i], "--gui")) {
            strncpy (use_gui_plugin, argv[i], sizeof(use_gui_plugin) - 1);
            use_gui_plugin[sizeof(use_gui_plugin) - 1] = 0;
        }
    }

    trace ("installdir: %s\n", dbinstalldir);
    trace ("confdir: %s\n", confdir);
    trace ("docdir: %s\n", dbdocdir);
    trace ("plugindir: %s\n", dbplugindir);
    trace ("pixmapdir: %s\n", dbpixmapdir);

    mkdir (dbconfdir, 0755);

    int size = 0;
    char *cmdline = prepare_command_line (argc, argv, &size);

    // try to connect to remote player
    int s, len;
    struct sockaddr_un remote;

    if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
        perror("socket");
        exit(1);
    }

    memset (&remote, 0, sizeof (remote));
    remote.sun_family = AF_UNIX;
#if USE_ABSTRACT_NAME
    memcpy (remote.sun_path, server_id, sizeof (server_id));
    len = offsetof(struct sockaddr_un, sun_path) + sizeof (server_id)-1;
#else
    char *socketdirenv = getenv ("DDB_SOCKET_DIR");
    snprintf (remote.sun_path, sizeof (remote.sun_path), "%s/socket", socketdirenv ? socketdirenv : dbconfdir);
    len = offsetof(struct sockaddr_un, sun_path) + strlen (remote.sun_path);
#endif
    if (connect(s, (struct sockaddr *)&remote, len) == 0) {
        // pass args to remote and exit
        if (send(s, cmdline, size, 0) == -1) {
            perror ("send");
            exit (-1);
        }
        // end of message
        shutdown(s, SHUT_WR);

        int sz = -1;
        char *out = read_entire_message(s, &sz);
        if (sz == -1) {
            fprintf (stderr, "failed to pass args to remote!\n");
            exit (-1);
        }
        else {
            // check if that's nowplaying response
            const char np[] = "nowplaying ";
            const char err[] = "error ";
            if (!strncmp (out, np, sizeof (np)-1)) {
                const char *prn = &out[sizeof (np)-1];
                fwrite (prn, 1, strlen (prn), stdout);
            }
            else if (!strncmp (out, err, sizeof (err)-1)) {
                const char *prn = &out[sizeof (err)-1];
                fwrite (prn, 1, strlen (prn), stderr);
            }
            else if (sz > 0 && out[0]) {
                fprintf (stderr, "%s\n", out);
            }
        }
        close (s);
        exit (0);
    }
//    else {
//        perror ("INFO: failed to connect to existing session:");
//    }
    close(s);

    // become a server
    if (server_start () < 0) {
        exit (-1);
    }

    // hack: report nowplaying
    if (!strcmp (cmdline, "--nowplaying")) {
        char nothing[] = "nothing";
        fwrite (nothing, 1, sizeof (nothing)-1, stdout);
        return 0;
    }

    pl_init ();
    conf_init ();
    conf_load (); // required by some plugins at startup

    if (use_gui_plugin[0]) {
        conf_set_str ("gui_plugin", use_gui_plugin);
    }

    conf_set_str ("deadbeef_version", VERSION);

    volume_set_db (conf_get_float ("playback.volume", 0)); // volume need to be initialized before plugins start
    messagepump_init (); // required to push messages while handling commandline
    if (plug_load_all ()) { // required to add files to playlist from commandline
        exit (-1);
    }
    pl_load_all ();
    plt_set_curr_idx (conf_get_int ("playlist.current", 0));

    // execute server commands in local context
    int noloadpl = 0;
    if (argc > 1) {
        int res = server_exec_command_line (cmdline, size, NULL, 0);
        // some of the server commands ran on 1st instance should terminate it
        if (res == 2) {
            noloadpl = 1;
        }
        else if (res > 0) {
            exit (0);
        }
        else if (res < 0) {
            exit (-1);
        }
    }

    free (cmdline);

#if 0
    signal (SIGTERM, sigterm_handler);
    atexit (atexit_handler); // helps to save in simple cases
#endif

    // start all subsystems
    messagepump_push (DB_EV_PLAYLISTCHANGED, 0, 0, 0);

    streamer_init ();

    plug_connect_all ();

    if (!noloadpl) {
        restore_resume_state ();
    }

    server_tid = thread_start (server_loop, NULL);
    // this runs in main thread (blocks right here)
    player_mainloop ();

    // terminate server and wait for completion
    if (server_tid) {
        server_terminate = 1;
        thread_join (server_tid);
        server_tid = 0;
    }

    // save config
    pl_save_all ();
    conf_save ();

    // delete legacy session file
    {
        char sessfile[1024]; // $HOME/.config/deadbeef/session
        if (snprintf (sessfile, sizeof (sessfile), "%s/deadbeef/session", confdir) < sizeof (sessfile)) {
            unlink (sessfile);
        }
    }

    // stop receiving messages from outside
    server_close ();

    // plugins might still hood references to playitems,
    // and query configuration in background
    // so unload everything 1st before final cleanup
    plug_disconnect_all ();
    plug_unload_all ();

    // at this point we can simply do exit(0), but let's clean up for debugging
    pl_free (); // may access conf_*
    conf_free ();
    messagepump_free ();
    plug_cleanup ();

    fprintf (stderr, "hej-hej!\n");
    return 0;
}