Exemple #1
0
int mpd_put_outputs(char *buffer, int names)
{
    struct mpd_output *out;
    int nout;
    char *str, *strend;

    str = buffer;
    strend = buffer+MAX_SIZE;
    str += snprintf(str, strend-str, "{\"type\":\"%s\", \"data\":{",
            names ? "outputnames" : "outputs");

    mpd_send_outputs(mpd.conn);
    nout = 0;
    while ((out = mpd_recv_output(mpd.conn)) != NULL) {
        if (nout++)
            *str++ = ',';
        if (names)
            str += snprintf(str, strend - str, " \"%d\":\"%s\"",
                    mpd_output_get_id(out), mpd_output_get_name(out));
        else
            str += snprintf(str, strend-str, " \"%d\":%d",
                    mpd_output_get_id(out), mpd_output_get_enabled(out));
        mpd_output_free(out);
    }
    if (!mpd_response_finish(mpd.conn)) {
        fprintf(stderr, "MPD outputs: %s\n", mpd_connection_get_error_message(mpd.conn));
        mpd_connection_clear_error(mpd.conn);
        return 0;
    }
    str += snprintf(str, strend-str, " }}");
    return str-buffer;
}
Exemple #2
0
static gboolean
lmc_reconnect(G_GNUC_UNUSED gpointer data)
{
	const unsigned *version;

	g_mpd = mpd_connection_new(g_host, g_port, 0);
	if (mpd_connection_get_error(g_mpd) != MPD_ERROR_SUCCESS) {
		lmc_failure();
		return true;
	}

	idle_supported = mpd_connection_cmp_server_version(g_mpd, 0, 14, 0) >= 0;

	version = mpd_connection_get_server_version(g_mpd);
	char *name = connection_settings_name(g_mpd);
	g_message("connected to mpd %i.%i.%i at %s\n",
		  version[0], version[1], version[2],
		  name);
	g_free(name);

#if LIBMPDCLIENT_CHECK_VERSION(2,5,0)
	subscribed = mpd_run_subscribe(g_mpd, "mpdscribble");
	if (!subscribed && !mpd_connection_clear_error(g_mpd)) {
		lmc_failure();
		return true;
	}
#endif

	lmc_schedule_update();

	reconnect_source_id = 0;
	return false;
}
Exemple #3
0
void Connection::checkErrors() const
{
	mpd_error code = mpd_connection_get_error(m_connection.get());
	if (code != MPD_ERROR_SUCCESS)
	{
		std::string msg = mpd_connection_get_error_message(m_connection.get());
		if (code == MPD_ERROR_SERVER)
		{
			mpd_server_error server_code = mpd_connection_get_server_error(m_connection.get());
			bool clearable = mpd_connection_clear_error(m_connection.get());
			throw ServerError(server_code, msg, clearable);
		}
		else
		{
			bool clearable = mpd_connection_clear_error(m_connection.get());
			throw ClientError(code, msg, clearable);
		}
	}
}
Exemple #4
0
static gboolean
lmc_idle(G_GNUC_UNUSED GIOChannel *source,
	 G_GNUC_UNUSED GIOCondition condition,
	 G_GNUC_UNUSED gpointer data)
{
	bool success;
	enum mpd_idle idle;

	assert(idle_source_id != 0);
	assert(g_mpd != NULL);
	assert(mpd_connection_get_error(g_mpd) == MPD_ERROR_SUCCESS);

	idle_source_id = 0;

	idle = mpd_recv_idle(g_mpd, false);
	success = mpd_response_finish(g_mpd);

	if (!success && mpd_connection_get_error(g_mpd) == MPD_ERROR_SERVER &&
	    mpd_connection_get_server_error(g_mpd) == MPD_SERVER_ERROR_UNKNOWN_CMD &&
	    mpd_connection_clear_error(g_mpd)) {
		/* MPD does not recognize the "idle" command - disable
		   it for this connection */

		g_message("MPD does not support the 'idle' command - "
			  "falling back to polling\n");

		idle_supported = false;
		lmc_schedule_update();
		return false;
	}

	if (!success) {
		lmc_failure();
		lmc_schedule_reconnect();
		return false;
	}

#if LIBMPDCLIENT_CHECK_VERSION(2,5,0)
	if (subscribed && (idle & MPD_IDLE_MESSAGE) != 0 &&
	    !lmc_read_messages()) {
		lmc_failure();
		lmc_schedule_reconnect();
		return false;
	}
#endif

	if (idle & MPD_IDLE_PLAYER)
		/* there was a change: query MPD */
		lmc_schedule_update();
	else
		/* nothing interesting: re-enter idle */
		lmc_schedule_idle();

	return false;
}
Exemple #5
0
static void mpd_report_error(void)
{
	const gchar *error = mpd_connection_get_error_message(mpd.conn);
	g_warning("MPD error: %s", error);
	irc_say("MPD error: %s", error);
	if (mpd_connection_clear_error(mpd.conn)) {
		g_warning("Unable to recover, reconnecting");
		mpd_disconnect();
		mpd_schedule_reconnect();
	}
}
Exemple #6
0
static bool check_error(struct mpd_connection *client)
{
  if (mpd_connection_get_error(client) != MPD_ERROR_SUCCESS) {
    printf("Error: %s (Retry in 1 second...)\n",
           mpd_connection_get_error_message(client));
    if (!mpd_connection_clear_error(client)) {
      mpd_connection_free(client);
      sleep(1);
      return true;
    }
  }
  return (client == NULL);
}
Exemple #7
0
Fichier : lib.c Projet : qsn/mpdfs
bool check_error(struct mpd_connection *con, FILE *logfile, bool exit_on_failure)
{
	if (mpd_connection_get_error(con) != MPD_ERROR_SUCCESS) {
		if (logfile)
			fprintf(logfile, "MPD error: %s\n", mpd_connection_get_error_message(con));
		if (exit_on_failure || !mpd_connection_clear_error(con)) {
			mpd_connection_free(con);
			exit(EXIT_FAILURE);
		}

		return true;
	}

	return false;
}
Exemple #8
0
static bool
lmc_read_messages(void)
{
	assert(subscribed);

	if (!mpd_send_read_messages(g_mpd))
		return mpd_connection_clear_error(g_mpd);

	struct mpd_message *msg;
	while ((msg = mpd_recv_message(g_mpd)) != NULL) {
		const char *text = mpd_message_get_text(msg);
		if (strcmp(text, "love") == 0)
			love = true;
		else
			g_message("Unrecognized client-to-client message: '%s'",
				  text);

		mpd_message_free(msg);
	}

	return mpd_response_finish(g_mpd);
}
Exemple #9
0
bool
path_prepare(struct mpd_connection *conn)
{
	if (initialized)
		return true;

	initialized = true;

	if (mpd_connection_cmp_server_version(conn, 0, 17, 0) < 0)
		/* the "config" command was added in MPD 0.17.1 */
		return true;

	if (!mpd_send_command(conn, "config", NULL))
		return false;

	struct mpd_pair *pair = mpd_recv_pair_named(conn, "music_directory");
	if (pair != NULL) {
		music_directory = strdup(pair->value);
		mpd_return_pair(conn, pair);
	}

	return mpd_response_finish(conn) || mpd_connection_clear_error(conn);
}
Exemple #10
0
bool mpd_is_in_queue(const char *uri)
{
    bool res = false;
    struct mpd_entity *entity;
    struct mpd_connection *conn = mpd_connection_new(NULL, NULL, 3000);

    if (conn == NULL) {
        syslog(LOG_ERR, "%s - Out of memory.", __func__);
        goto DONE;
    }
    if (mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS) {
        syslog(LOG_ERR, "%s - MPD connection: %s\n", __func__,
                mpd_connection_get_error_message(conn));
        goto DONE;
    }
    if (!mpd_send_list_queue_meta(conn)) {
        syslog(LOG_ERR, "%s: %s", __func__, mpd_connection_get_error_message(conn));
        mpd_connection_clear_error(conn);
        goto DONE;
    }
    while((entity = mpd_recv_entity(conn)) != NULL) {
        const struct mpd_song *song;
        if(mpd_entity_get_type(entity) == MPD_ENTITY_TYPE_SONG && !res) {
            song = mpd_entity_get_song(entity);
            if (strcmp(mpd_song_get_uri(song), uri) == 0) {
                syslog(LOG_INFO, "%s: %s is already in the queue", __func__, uri);
                res = true;
            }
        }
        mpd_entity_free(entity);
    }

DONE:
    if(conn != NULL)
        mpd_connection_free(conn);
    return res;
}
Exemple #11
0
int callback_mpd(struct mg_connection *c)
{
    enum mpd_cmd_ids cmd_id = get_cmd_id(c->content);
    size_t n = 0;
    unsigned int uint_buf, uint_buf_2;
    int int_buf;
    char *p_charbuf = NULL, *token;

    if(cmd_id == -1)
        return MG_TRUE;

    if(mpd.conn_state != MPD_CONNECTED && cmd_id != MPD_API_SET_MPDHOST &&
        cmd_id != MPD_API_GET_MPDHOST && cmd_id != MPD_API_SET_MPDPASS &&
        cmd_id != MPD_API_GET_DIRBLEAPITOKEN)
        return MG_TRUE;

    switch(cmd_id)
    {
        case MPD_API_UPDATE_DB:
            mpd_run_update(mpd.conn, NULL);
            break;
        case MPD_API_SET_PAUSE:
            mpd_run_toggle_pause(mpd.conn);
            break;
        case MPD_API_SET_PREV:
            mpd_run_previous(mpd.conn);
            break;
        case MPD_API_SET_NEXT:
            mpd_run_next(mpd.conn);
            break;
        case MPD_API_SET_PLAY:
            mpd_run_play(mpd.conn);
            break;
        case MPD_API_SET_STOP:
            mpd_run_stop(mpd.conn);
            break;
        case MPD_API_RM_ALL:
            mpd_run_clear(mpd.conn);
            break;
        case MPD_API_RM_TRACK:
            if(sscanf(c->content, "MPD_API_RM_TRACK,%u", &uint_buf))
                mpd_run_delete_id(mpd.conn, uint_buf);
            break;
        case MPD_API_PLAY_TRACK:
            if(sscanf(c->content, "MPD_API_PLAY_TRACK,%u", &uint_buf))
                mpd_run_play_id(mpd.conn, uint_buf);
            break;
        case MPD_API_TOGGLE_RANDOM:
            if(sscanf(c->content, "MPD_API_TOGGLE_RANDOM,%u", &uint_buf))
                mpd_run_random(mpd.conn, uint_buf);
            break;
        case MPD_API_TOGGLE_REPEAT:
            if(sscanf(c->content, "MPD_API_TOGGLE_REPEAT,%u", &uint_buf))
                mpd_run_repeat(mpd.conn, uint_buf);
            break;
        case MPD_API_TOGGLE_CONSUME:
            if(sscanf(c->content, "MPD_API_TOGGLE_CONSUME,%u", &uint_buf))
                mpd_run_consume(mpd.conn, uint_buf);
            break;
        case MPD_API_TOGGLE_SINGLE:
            if(sscanf(c->content, "MPD_API_TOGGLE_SINGLE,%u", &uint_buf))
                mpd_run_single(mpd.conn, uint_buf);
            break;
        case MPD_API_TOGGLE_CROSSFADE:
            if(sscanf(c->content, "MPD_API_TOGGLE_CROSSFADE,%u", &uint_buf))
                mpd_run_crossfade(mpd.conn, uint_buf);
            break;
        case MPD_API_GET_OUTPUTS:
            mpd.buf_size = mpd_put_outputs(mpd.buf, 1);
            c->callback_param = NULL;
            mpd_notify_callback(c, MG_POLL);
            break;
        case MPD_API_TOGGLE_OUTPUT:
            if (sscanf(c->content, "MPD_API_TOGGLE_OUTPUT,%u,%u", &uint_buf, &uint_buf_2)) {
                if (uint_buf_2)
                    mpd_run_enable_output(mpd.conn, uint_buf);
                else
                    mpd_run_disable_output(mpd.conn, uint_buf);
            }
            break;
        case MPD_API_SET_VOLUME:
            if(sscanf(c->content, "MPD_API_SET_VOLUME,%ud", &uint_buf) && uint_buf <= 100)
                mpd_run_set_volume(mpd.conn, uint_buf);
            break;
        case MPD_API_SET_SEEK:
            if(sscanf(c->content, "MPD_API_SET_SEEK,%u,%u", &uint_buf, &uint_buf_2))
                mpd_run_seek_id(mpd.conn, uint_buf, uint_buf_2);
            break;
        case MPD_API_GET_QUEUE:
            if(sscanf(c->content, "MPD_API_GET_QUEUE,%u", &uint_buf))
                n = mpd_put_queue(mpd.buf, uint_buf);
            break;
        case MPD_API_GET_BROWSE:
            p_charbuf = strdup(c->content);
            if(strcmp(strtok(p_charbuf, ","), "MPD_API_GET_BROWSE"))
                goto out_browse;

            uint_buf = strtoul(strtok(NULL, ","), NULL, 10);
            if((token = strtok(NULL, ",")) == NULL)
                goto out_browse;

			free(p_charbuf);
            p_charbuf = strdup(c->content);
            n = mpd_put_browse(mpd.buf, get_arg2(p_charbuf), uint_buf);
out_browse:
			free(p_charbuf);
            break;
        case MPD_API_ADD_TRACK:
            p_charbuf = strdup(c->content);
            if(strcmp(strtok(p_charbuf, ","), "MPD_API_ADD_TRACK"))
                goto out_add_track;

            if((token = strtok(NULL, ",")) == NULL)
                goto out_add_track;

			free(p_charbuf);
            p_charbuf = strdup(c->content);
            mpd_run_add(mpd.conn, get_arg1(p_charbuf));
out_add_track:
            free(p_charbuf);
            break;
        case MPD_API_ADD_PLAY_TRACK:
            p_charbuf = strdup(c->content);
            if(strcmp(strtok(p_charbuf, ","), "MPD_API_ADD_PLAY_TRACK"))
                goto out_play_track;

            if((token = strtok(NULL, ",")) == NULL)
                goto out_play_track;

			free(p_charbuf);
            p_charbuf = strdup(c->content);
            int_buf = mpd_run_add_id(mpd.conn, get_arg1(p_charbuf));
            if(int_buf != -1)
                mpd_run_play_id(mpd.conn, int_buf);
out_play_track:
            free(p_charbuf);
            break;
        case MPD_API_ADD_PLAYLIST:
            p_charbuf = strdup(c->content);
            if(strcmp(strtok(p_charbuf, ","), "MPD_API_ADD_PLAYLIST"))
                goto out_playlist;

            if((token = strtok(NULL, ",")) == NULL)
                goto out_playlist;

			free(p_charbuf);
            p_charbuf = strdup(c->content);
            mpd_run_load(mpd.conn, get_arg1(p_charbuf));
out_playlist:
            free(p_charbuf);
            break;
        case MPD_API_SAVE_QUEUE:
            p_charbuf = strdup(c->content);
            if(strcmp(strtok(p_charbuf, ","), "MPD_API_SAVE_QUEUE"))
                goto out_save_queue;

            if((token = strtok(NULL, ",")) == NULL)
                goto out_save_queue;

			free(p_charbuf);
            p_charbuf = strdup(c->content);
            mpd_run_save(mpd.conn, get_arg1(p_charbuf));
out_save_queue:
            free(p_charbuf);
            break;
        case MPD_API_SEARCH:
            p_charbuf = strdup(c->content);
            if(strcmp(strtok(p_charbuf, ","), "MPD_API_SEARCH"))
				goto out_search;

            if((token = strtok(NULL, ",")) == NULL)
                goto out_search;

			free(p_charbuf);
            p_charbuf = strdup(c->content);
            n = mpd_search(mpd.buf, get_arg1(p_charbuf));
out_search:
            free(p_charbuf);
            break;
#ifdef WITH_MPD_HOST_CHANGE
        /* Commands allowed when disconnected from MPD server */
        case MPD_API_SET_MPDHOST:
            int_buf = 0;
            p_charbuf = strdup(c->content);
            if(strcmp(strtok(p_charbuf, ","), "MPD_API_SET_MPDHOST"))
                goto out_host_change;

            if((int_buf = strtol(strtok(NULL, ","), NULL, 10)) <= 0)
                goto out_host_change;

            if((token = strtok(NULL, ",")) == NULL)
                goto out_host_change;

            strncpy(mpd.host, token, sizeof(mpd.host));
            mpd.port = int_buf;
            mpd.conn_state = MPD_RECONNECT;
            free(p_charbuf);
            return MG_TRUE;
out_host_change:
            free(p_charbuf);
            break;
        case MPD_API_GET_MPDHOST:
            n = snprintf(mpd.buf, MAX_SIZE, "{\"type\":\"mpdhost\", \"data\": "
                "{\"host\" : \"%s\", \"port\": \"%d\", \"passwort_set\": %s}"
                "}", mpd.host, mpd.port, mpd.password ? "true" : "false");
            break;
        case MPD_API_GET_DIRBLEAPITOKEN:
            n = snprintf(mpd.buf, MAX_SIZE, "{\"type\":\"dirbleapitoken\", \""
                "data\": \"%s\"}", dirble_api_token);
            break;
        case MPD_API_SET_MPDPASS:
            p_charbuf = strdup(c->content);
            if(strcmp(strtok(p_charbuf, ","), "MPD_API_SET_MPDPASS"))
                goto out_set_pass;

            if((token = strtok(NULL, ",")) == NULL)
                goto out_set_pass;

            if(mpd.password)
                free(mpd.password);

            mpd.password = strdup(token);
            mpd.conn_state = MPD_RECONNECT;
            free(p_charbuf);
            return MG_TRUE;
out_set_pass:
            free(p_charbuf);
            break;
#endif
    }

    if(mpd.conn_state == MPD_CONNECTED && mpd_connection_get_error(mpd.conn) != MPD_ERROR_SUCCESS)
    {
        n = snprintf(mpd.buf, MAX_SIZE, "{\"type\":\"error\", \"data\": \"%s\"}", 
            mpd_connection_get_error_message(mpd.conn));

        /* Try to recover error */
        if (!mpd_connection_clear_error(mpd.conn))
            mpd.conn_state = MPD_FAILURE;
    }

    if(n > 0)
        mg_websocket_write(c, 1, mpd.buf, n);

    return MG_TRUE;
}
/* Execute the given command. In fact, it just will ask MPD to do it.
 * You will have to check the next "status" or "playlist" update (using the corresponding slot)
 * to know if the command has really been executed.
 */
void Player::executeCmd(EMSPlayerCmd cmd)
{
    bool waitResponse = true; /* Wait the responase by default */
    bool error = false;

    if (conn == NULL)
    {
        return;
    }

    /* Dispatch execution depending on the action */
    switch (cmd.action)
    {
        case ACTION_ADD:
        {
            if(searchTrackInPlaylist(cmd.track) >= 0)
            {
                qDebug() << "Do not add track in the playlist as it already exist";
                return;
            }
            QString filename = getMPDFilename(cmd.track);
            mpd_send_add(conn, filename.toStdString().c_str());
            break;
        }
        case ACTION_DEL:
        {
            int pos = searchTrackInPlaylist(cmd.track);
            if (pos >= 0)
            {
                mpd_send_delete(conn, pos);
            }
            break;
        }
        case ACTION_DEL_ALL:
        {
            mpd_send_clear(conn);
            break;
        }
        case ACTION_PLAY_POS:
        {
            mutex.lock();
            int size = playlist.tracks.size();
            mutex.unlock();
            if (size <= 0 || cmd.uintValue >= (unsigned int)size)
            {
                qDebug() << "Asked to play a track after the end of the current playlist";
                error = true;
                break;
            }
            mpd_send_play_pos(conn, cmd.uintValue);
            break;
        }
        case ACTION_PLAY_TRACK:
        {
            int position = searchTrackInPlaylist(cmd.track);
            if (position < 0)
            {
                qDebug() << "Asked to play a track which is not in the current playlist";
                error = true;
                break;
            }
            mpd_send_play_pos(conn, position);
            break;
        }
        case ACTION_PLAY:
        {
            mpd_send_play(conn);
            break;
        }
        case ACTION_SEEK:
        {
            /* Get current position */
            int songId = getCurrentPos();
            if (songId >= 0)
            {
                mpd_send_seek_pos(conn, songId, cmd.uintValue);
            }
            break;
        }
        case ACTION_PAUSE:
        {
            mpd_send_pause(conn, true);
            break;
        }
        case ACTION_TOGGLE:
        {
            mpd_send_toggle_pause(conn);
            break;
        }
        case ACTION_STOP:
        {
            mpd_send_stop(conn);
            break;
        }
        case ACTION_NEXT:
        {
            mpd_send_next(conn);
            break;
        }
        case ACTION_PREV:
        {
            mpd_send_previous(conn);
            break;
        }
        case ACTION_REPEAT:
        {
            mutex.lock();
            bool repeatTmp = status.repeat;
            mutex.unlock();
            if (cmd.boolValue != repeatTmp)
            {
                mpd_send_repeat(conn, cmd.boolValue);
            }
            break;
        }
        case ACTION_RANDOM:
        {
            mutex.lock();
            bool randomTmp = status.random;
            mutex.unlock();
            if (cmd.boolValue != randomTmp)
            {
                mpd_send_random(conn, cmd.boolValue);
            }
            break;
        }
        case ACTION_ENABLE_OUTPUT:
        {
            if (cmd.uintValue >= 1)
            {
                mpd_send_enable_output(conn, cmd.uintValue-1);
            }
            break;
        }
        case ACTION_DISABLE_OUTPUT:
        {
            if (cmd.uintValue >= 1)
            {
                mpd_send_disable_output(conn, cmd.uintValue-1);
            }
            break;
        }
        default:
        {
            qCritical() << "Unhandled action in the current command.";
            waitResponse = false;
            break;
        }
    }

    if (waitResponse && !mpd_response_finish(conn))
    {
        error = true;
        qCritical() << "MPD could not execute the current command.";
        enum mpd_error errorMpd = mpd_connection_get_error(conn);
        if (errorMpd == MPD_ERROR_SERVER ||
            errorMpd == MPD_ERROR_ARGUMENT) /* Problem with the command */
        {
            QString errorMessage = QString::fromUtf8(mpd_connection_get_error_message(conn));
            qCritical() << "Command error : " << errorMessage;
            if (!mpd_connection_clear_error(conn))
            {
                qCritical() << "This error cannot be cleared, reconnecting...";
                connectToMpd();
            }

        }
        else if (errorMpd == MPD_ERROR_TIMEOUT ||
                 errorMpd == MPD_ERROR_RESOLVER ||
                 errorMpd == MPD_ERROR_MALFORMED ||
                 errorMpd == MPD_ERROR_CLOSED ) /* Assume there is a connection problem, try to reconnect... */
        {
            QString errorMessage = QString::fromUtf8(mpd_connection_get_error_message(conn));
            qCritical() << "Connexion error : " << errorMessage;
            qCritical() << "Reconnecting...";
            connectToMpd();
            mutex.lock();
            queue.push_front(cmd);
            mutex.unlock();
            cmdAvailable.release(1);
        }
    }

    /* Post-action depending on the command
     * Do the minimum here as the whole status will be
     * retrieve here. But for playlist ADD/DEL, we need to
     * store the EMSTrack structure.
     */
    if(!error)
    {
        switch (cmd.action)
        {
            case ACTION_ADD:
            {
                EMSPlaylist newPlaylist;
                mutex.lock();
                playlist.tracks.append(cmd.track);
                newPlaylist = playlist;
                mutex.unlock();
                emit playlistChanged(newPlaylist);
                break;
            }
            case ACTION_DEL:
            {
                int pos = searchTrackInPlaylist(cmd.track);
                if (pos >= 0)
                {
                    EMSPlaylist newPlaylist;
                    mutex.lock();
                    playlist.tracks.removeAt(pos);
                    newPlaylist = playlist;
                    mutex.unlock();
                    emit playlistChanged(newPlaylist);
                }
                break;
            }
            case ACTION_DEL_ALL:
            {
                EMSPlaylist newPlaylist;
                mutex.lock();
                playlist.tracks.clear();
                newPlaylist = playlist;
                mutex.unlock();
                emit playlistChanged(newPlaylist);
                break;
            }
            case ACTION_ENABLE_OUTPUT:
            {
                mutex.lock();
                for(int i=0; i<outputs.size(); i++)
                {
                    if (outputs.at(i).id_mpd == cmd.uintValue)
                    {
                        EMSSndCard card = outputs.at(i);
                        card.enabled = true;
                        outputs.replace(i, card);
                    }
                }
                emit outputsChanged(outputs);
                mutex.unlock();
                break;
            }
            case ACTION_DISABLE_OUTPUT:
            {
                mutex.lock();
                for(int i=0; i<outputs.size(); i++)
                {
                    if (outputs.at(i).id_mpd == cmd.uintValue)
                    {
                        EMSSndCard card = outputs.at(i);
                        card.enabled = false;
                        outputs.replace(i, card);
                    }
                }
                emit outputsChanged(outputs);
                mutex.unlock();
                break;
            }
            default:
                break;
        }
    }
}
Exemple #13
0
/* fetch a new db tree on root */
static int fetch_db_tree(DB_NODE **p_root,struct mpd_connection *conn)
{
    if (*p_root)
        return 1;

    /* create root */
    DB_NODE *root = (DB_NODE*)malloc(sizeof(DB_NODE));
    root->type = DB_DIRECTORY;
    /* use calloc for root->uri to ease free_db_tree() */
    root->uri = (char *)calloc(2,sizeof(char));
    strncpy(root->uri,"/",1);
    root->rating = 0;
    root->duration = 0;
    root->p = NULL;
    root->s = NULL;
    root->c = NULL;
    root->num_c = 0;

    /* set top node */
    DB_NODE *top = root;

	if (!mpd_send_list_all_meta(conn,"/")) {
        clear_or_exit_on_error(conn);
        return 1;
    }

    /* add nodes recursively */
    struct mpd_entity *entity;
	while ((entity = mpd_recv_entity(conn))) {

        DB_NODE *node = (DB_NODE*)malloc(sizeof(DB_NODE));

        const char *name = NULL;
        switch (mpd_entity_get_type(entity)) {
            case MPD_ENTITY_TYPE_DIRECTORY:
                node->type = DB_DIRECTORY;

                name = mpd_directory_get_path(mpd_entity_get_directory(entity));
                assert (name && strlen(name));
                node->uri = (char *)calloc(strlen(name)+1,sizeof(char));
                strncpy(node->uri,name,strlen(name));

                node->rating = 0;
                node->duration = 0;
                break;
            case MPD_ENTITY_TYPE_SONG:
                node->type = DB_SONG;

                name = mpd_song_get_uri(mpd_entity_get_song(entity));
                assert (name && strlen(name));
                node->uri = (char *)calloc(strlen(name)+1,sizeof(char));
                strncpy(node->uri,name,strlen(name));

                node->rating = 0;
                node->duration = mpd_song_get_duration(mpd_entity_get_song(entity));
                break;
            case MPD_ENTITY_TYPE_PLAYLIST:
                node->type = DB_PLAYLIST;

                name = mpd_playlist_get_path(mpd_entity_get_playlist(entity));
                assert (name && strlen(name));
                node->uri = (char *)calloc(strlen(name)+1,sizeof(char));
                strncpy(node->uri,name,strlen(name));

                node->rating = 0;
                node->duration = 0;
                break;
            case MPD_ENTITY_TYPE_UNKNOWN:
                break;
        }

        /* backtrace top until it's parent of node */
        while (top != root && !(strstr(node->uri,top->uri) && node->uri[strlen(top->uri)] == '/'))
            top = top->p;

        /* if current top already has chlidren */
        if (top->c) {
            DB_NODE *node2 = top->c;
            /* find the last child */
            while (node2->s)
                node2 = node2->s;
            node2->s = node;
            node->p = node2->p;
            node->p->num_c++;
        } else {
            top->c = node;
            node->p = top;
            node->p->num_c++;
        }
        /* no child, no next sibling */
        node->c = NULL;
        node->s = NULL;
        node->num_c = 0;

        /* update top node */
        if (node->type == DB_DIRECTORY)
            top = node;

		mpd_entity_free(entity);
	}
    if (mpd_connection_get_error(conn) == MPD_ERROR_SUCCESS)
        mpd_response_finish(conn);
    else if (!mpd_connection_clear_error(conn))
        exit_on_error(conn);

    *p_root = root;
    return 0;
}
Exemple #14
0
int callback_mpd(struct mg_connection *c)
{
    enum mpd_cmd_ids cmd_id = get_cmd_id(c->content);
    size_t n = 0;
    unsigned int uint_buf, uint_buf_2;
    int int_buf;
    char *p_charbuf = NULL;

    if(cmd_id == -1)
        return MG_CLIENT_CONTINUE;

    if(mpd.conn_state != MPD_CONNECTED && cmd_id != MPD_API_SET_MPDHOST &&
        cmd_id != MPD_API_GET_MPDHOST && cmd_id != MPD_API_SET_MPDPASS)
        return MG_CLIENT_CONTINUE;

    mpd_connection_set_timeout(mpd.conn, 10000);
    switch(cmd_id)
    {
        case MPD_API_UPDATE_DB:
            mpd_run_update(mpd.conn, NULL);
            break;
        case MPD_API_SET_PAUSE:
            mpd_run_toggle_pause(mpd.conn);
            break;
        case MPD_API_SET_PREV:
            mpd_run_previous(mpd.conn);
            break;
        case MPD_API_SET_NEXT:
            mpd_run_next(mpd.conn);
            break;
        case MPD_API_SET_PLAY:
            mpd_run_play(mpd.conn);
            break;
        case MPD_API_SET_STOP:
            mpd_run_stop(mpd.conn);
            break;
        case MPD_API_RM_ALL:
            mpd_run_clear(mpd.conn);
            break;
        case MPD_API_RM_TRACK:
            if(sscanf(c->content, "MPD_API_RM_TRACK,%u", &uint_buf))
                mpd_run_delete_id(mpd.conn, uint_buf);
            break;
        case MPD_API_PLAY_TRACK:
            if(sscanf(c->content, "MPD_API_PLAY_TRACK,%u", &uint_buf))
                mpd_run_play_id(mpd.conn, uint_buf);
            break;
        case MPD_API_TOGGLE_RANDOM:
            if(sscanf(c->content, "MPD_API_TOGGLE_RANDOM,%u", &uint_buf))
                mpd_run_random(mpd.conn, uint_buf);
            break;
        case MPD_API_TOGGLE_REPEAT:
            if(sscanf(c->content, "MPD_API_TOGGLE_REPEAT,%u", &uint_buf))
                mpd_run_repeat(mpd.conn, uint_buf);
            break;
        case MPD_API_TOGGLE_CONSUME:
            if(sscanf(c->content, "MPD_API_TOGGLE_CONSUME,%u", &uint_buf))
                mpd_run_consume(mpd.conn, uint_buf);
            break;
        case MPD_API_TOGGLE_SINGLE:
            if(sscanf(c->content, "MPD_API_TOGGLE_SINGLE,%u", &uint_buf))
                mpd_run_single(mpd.conn, uint_buf);
            break;
        case MPD_API_SET_VOLUME:
            if(sscanf(c->content, "MPD_API_SET_VOLUME,%ud", &uint_buf) && uint_buf <= 100)
                mpd_run_set_volume(mpd.conn, uint_buf);
            break;
        case MPD_API_SET_SEEK:
            if(sscanf(c->content, "MPD_API_SET_SEEK,%u,%u", &uint_buf, &uint_buf_2))
                mpd_run_seek_id(mpd.conn, uint_buf, uint_buf_2);
            break;
        case MPD_API_GET_QUEUE:
            if(sscanf(c->content, "MPD_API_GET_QUEUE,%u", &uint_buf))
                n = mpd_put_queue(mpd.buf, uint_buf);
            break;
        case MPD_API_GET_BROWSE:
            if(sscanf(c->content, "MPD_API_GET_BROWSE,%u,%m[^\t\n]", &uint_buf, &p_charbuf) && p_charbuf != NULL)
            {
                n = mpd_put_browse(mpd.buf, p_charbuf, uint_buf);
                free(p_charbuf);
            }
            break;
        case MPD_API_ADD_TRACK:
            if(sscanf(c->content, "MPD_API_ADD_TRACK,%m[^\t\n]", &p_charbuf) && p_charbuf != NULL)
            {
                mpd_run_add(mpd.conn, p_charbuf);
                free(p_charbuf);
            }
            break;
        case MPD_API_ADD_PLAY_TRACK:
            if(sscanf(c->content, "MPD_API_ADD_PLAY_TRACK,%m[^\t\n]", &p_charbuf) && p_charbuf != NULL)
            {
                int_buf = mpd_run_add_id(mpd.conn, p_charbuf);
                if(int_buf != -1)
                    mpd_run_play_id(mpd.conn, int_buf);
                free(p_charbuf);
            }
            break;
        case MPD_API_ADD_PLAYLIST:
            if(sscanf(c->content, "MPD_API_ADD_PLAYLIST,%m[^\t\n]", &p_charbuf) && p_charbuf != NULL)
            {
                mpd_run_load(mpd.conn, p_charbuf);
                free(p_charbuf);
            }
            break;
        case MPD_API_SEARCH:
            if(sscanf(c->content, "MPD_API_SEARCH,%m[^\t\n]", &p_charbuf) && p_charbuf != NULL)
            {
                n = mpd_search(mpd.buf, p_charbuf);
                free(p_charbuf);
            }
            break;
#ifdef WITH_MPD_HOST_CHANGE
        /* Commands allowed when disconnected from MPD server */
        case MPD_API_SET_MPDHOST:
            int_buf = 0;
            if(sscanf(c->content, "MPD_API_SET_MPDHOST,%d,%m[^\t\n ]", &int_buf, &p_charbuf) && 
                p_charbuf != NULL && int_buf > 0)
            {
                strncpy(mpd.host, p_charbuf, sizeof(mpd.host));
                free(p_charbuf);
                mpd.port = int_buf;
                mpd.conn_state = MPD_RECONNECT;
                return MG_CLIENT_CONTINUE;
            }
            break;
        case MPD_API_GET_MPDHOST:
            n = snprintf(mpd.buf, MAX_SIZE, "{\"type\":\"mpdhost\", \"data\": "
                "{\"host\" : \"%s\", \"port\": \"%d\", \"passwort_set\": %s}"
                "}", mpd.host, mpd.port, mpd.password ? "true" : "false");
            break;
        case MPD_API_SET_MPDPASS:
            if(sscanf(c->content, "MPD_API_SET_MPDPASS,%m[^\t\n ]", &p_charbuf))
            {
                if(mpd.password)
                    free(mpd.password);

                mpd.password = p_charbuf;
                mpd.conn_state = MPD_RECONNECT;
                return MG_CLIENT_CONTINUE;
            }
            break;
#endif
    }

    if(mpd.conn_state == MPD_CONNECTED && mpd_connection_get_error(mpd.conn) != MPD_ERROR_SUCCESS)
    {
        n = snprintf(mpd.buf, MAX_SIZE, "{\"type\":\"error\", \"data\": \"%s\"}", 
            mpd_connection_get_error_message(mpd.conn));

        /* Try to recover error */
        if (!mpd_connection_clear_error(mpd.conn))
            mpd.conn_state = MPD_FAILURE;
    }

    if(n > 0)
        mg_websocket_write(c, 1, mpd.buf, n);

    return MG_CLIENT_CONTINUE;
}
Exemple #15
0
/*
 * Clears any error
 */
void
Control::clearerror()
{
	mpd_connection_clear_error(conn->h());
}