예제 #1
0
static void
__int_xmms_cmd_remove (xmms_object_t *object, xmms_object_cmd_arg_t *arg)
{
	xmmsv_t *t;
	if (xmmsv_list_get_size (arg->args) != 1) {
		XMMS_DBG ("Wrong number of arguments to remove (%d)", xmmsv_list_get_size (arg->args));
		xmms_error_set (&arg->error, XMMS_ERROR_INVAL, "Wrong number of arguments to remove");
		return;
	}
	const char * argval0;

	if (!xmmsv_list_get (arg->args, 0, &t)) {
		XMMS_DBG ("Missing arg 0 in remove");
		xmms_error_set (&arg->error, XMMS_ERROR_INVAL, "Missing arg 0 in remove");
		return;
	}
	if (!xmmsv_get_string (t, &argval0)) {
		XMMS_DBG ("Error parsing arg 0 in remove");
		xmms_error_set (&arg->error, XMMS_ERROR_INVAL, "Error parsing arg 0 in remove");
		return;
	}

	xmms_bindata_client_remove ((xmms_bindata_t *) object, argval0, &arg->error);
	arg->retval = xmmsv_new_none ();
}
예제 #2
0
static void
xmms_output_volume_set (xmms_output_t *output, const gchar *channel,
                        guint volume, xmms_error_t *error)
{

	if (!output->plugin) {
		xmms_error_set (error, XMMS_ERROR_GENERIC,
		                "couldn't set volume, output plugin not loaded");
		return;
	}

	if (!xmms_output_plugin_method_volume_set_available (output->plugin)) {
		xmms_error_set (error, XMMS_ERROR_GENERIC,
		                "operation not supported");
		return;
	}

	if (volume > 100) {
		xmms_error_set (error, XMMS_ERROR_INVAL, "volume out of range");
		return;
	}

	if (!xmms_output_plugin_methods_volume_set (output->plugin, output, channel, volume)) {
		xmms_error_set (error, XMMS_ERROR_GENERIC,
		                "couldn't set volume");
	}
}
예제 #3
0
파일: playlist.c 프로젝트: dsheeler/xmms2
/**
 * Retrieve the position of the currently active xmms_medialib_entry_t
 *
 */
xmmsv_t *
xmms_playlist_client_current_pos (xmms_playlist_t *playlist, const gchar *plname,
                                  xmms_error_t *err)
{
	guint32 pos;
	xmmsv_coll_t *plcoll;
	xmmsv_t *dict;

	g_return_val_if_fail (playlist, 0);

	g_mutex_lock (playlist->mutex);

	plcoll = xmms_playlist_get_coll (playlist, plname, err);
	if (plcoll == NULL) {
		g_mutex_unlock (playlist->mutex);
		xmms_error_set (err, XMMS_ERROR_INVAL, "no such playlist");
		return 0;
	}

	pos = xmms_playlist_coll_get_currpos (plcoll);
	if (pos == -1) {
		xmms_error_set (err, XMMS_ERROR_GENERIC, "no current entry");
	}

	g_mutex_unlock (playlist->mutex);

	dict = xmms_playlist_current_pos_msg_new (playlist, pos, plname);

	return dict;
}
예제 #4
0
파일: playlist.c 프로젝트: dsheeler/xmms2
/**
 * Retrieve a copy of the name of the currently active playlist.
 *
 */
static gchar *
xmms_playlist_client_current_active (xmms_playlist_t *playlist, xmms_error_t *err)
{
	gchar *alias = NULL;
	xmmsv_coll_t *active_coll;

	g_return_val_if_fail (playlist, 0);

	g_mutex_lock (playlist->mutex);

	active_coll = xmms_playlist_get_coll (playlist, XMMS_ACTIVE_PLAYLIST, err);
	if (active_coll != NULL) {
		alias = xmms_collection_find_alias (playlist->colldag,
		                                    XMMS_COLLECTION_NSID_PLAYLISTS,
		                                    active_coll, XMMS_ACTIVE_PLAYLIST);
		if (alias == NULL) {
			xmms_error_set (err, XMMS_ERROR_GENERIC, "active playlist not referenced!");
		}
	} else {
		xmms_error_set (err, XMMS_ERROR_GENERIC, "no active playlist");
	}

	g_mutex_unlock (playlist->mutex);

	return alias;
}
예제 #5
0
static void
__int_xmms_cmd_add (xmms_object_t *object, xmms_object_cmd_arg_t *arg)
{
	xmmsv_t *t;
	if (xmmsv_list_get_size (arg->args) != 1) {
		XMMS_DBG ("Wrong number of arguments to add (%d)", xmmsv_list_get_size (arg->args));
		xmms_error_set (&arg->error, XMMS_ERROR_INVAL, "Wrong number of arguments to add");
		return;
	}
	GString * argval0;

	if (!xmmsv_list_get (arg->args, 0, &t)) {
		XMMS_DBG ("Missing arg 0 in add");
		xmms_error_set (&arg->error, XMMS_ERROR_INVAL, "Missing arg 0 in add");
		return;
	}
	if (!xmms_bin_to_gstring (t, &argval0)) {
		XMMS_DBG ("Error parsing arg 0 in add");
		xmms_error_set (&arg->error, XMMS_ERROR_INVAL, "Error parsing arg 0 in add");
		return;
	}

	gchar * retval = xmms_bindata_client_add ((xmms_bindata_t *) object, argval0, &arg->error);
	if (retval != NULL) {
		arg->retval = xmms_convert_and_kill_string (retval);
	}
}
예제 #6
0
파일: playlist.c 프로젝트: dsheeler/xmms2
static void
xmms_playlist_client_load (xmms_playlist_t *playlist, const gchar *name, xmms_error_t *err)
{
	xmmsv_coll_t *plcoll, *active_coll;

	if (strcmp (name, XMMS_ACTIVE_PLAYLIST) == 0) {
		xmms_error_set (err, XMMS_ERROR_INVAL, "invalid playlist to load");
		return;
	}

	active_coll = xmms_playlist_get_coll (playlist, XMMS_ACTIVE_PLAYLIST, err);
	if (active_coll == NULL) {
		xmms_error_set (err, XMMS_ERROR_GENERIC, "no active playlist");
		return;
	}

	plcoll = xmms_playlist_get_coll (playlist, name, err);
	if (plcoll == NULL) {
		xmms_error_set (err, XMMS_ERROR_NOENT, "no such playlist");
		return;
	}

	if (active_coll == plcoll) {
		XMMS_DBG ("Not loading %s playlist, already active!", name);
		return;
	}

	XMMS_DBG ("Loading new playlist! %s", name);
	xmms_collection_update_pointer (playlist->colldag, XMMS_ACTIVE_PLAYLIST,
	                                XMMS_COLLECTION_NSID_PLAYLISTS, plcoll);

	xmms_object_emit (XMMS_OBJECT (playlist),
	                  XMMS_IPC_SIGNAL_PLAYLIST_LOADED,
	                  xmmsv_new_string (name));
}
예제 #7
0
static xmms_fetch_spec_t *
xmms_fetch_spec_new_organize (xmmsv_t *fetch, xmms_fetch_info_t *info,
                              s4_sourcepref_t *prefs, xmms_error_t *err)
{
	xmms_fetch_spec_t *spec;
	xmmsv_dict_iter_t *it;
	s4_sourcepref_t *sp;
	xmmsv_t *org_data;
	gint org_idx;

	if (!xmmsv_dict_get (fetch, "data", &org_data)) {
		xmms_error_set (err, XMMS_ERROR_INVAL, "Required field 'data' not set in organize.");
		return NULL;
	}

	if (xmmsv_get_type (org_data) != XMMSV_TYPE_DICT) {
		xmms_error_set (err, XMMS_ERROR_INVAL, "Field 'data' in organize must be a dict.");
		return NULL;
	}

	sp = normalize_source_preferences (fetch, prefs, err);
	if (xmms_error_iserror (err)) {
		return NULL;
	}

	spec = g_new0 (xmms_fetch_spec_t, 1);
	spec->type = FETCH_ORGANIZE;

	spec->data.organize.count = xmmsv_dict_get_size (org_data);
	spec->data.organize.keys = g_new0 (const char *, spec->data.organize.count);
	spec->data.organize.data = g_new0 (xmms_fetch_spec_t *, spec->data.organize.count);

	org_idx = 0;
	xmmsv_get_dict_iter (org_data, &it);
	while (xmmsv_dict_iter_valid (it)) {
		xmms_fetch_spec_t *orgee;
		const gchar *str;
		xmmsv_t *entry;

		xmmsv_dict_iter_pair (it, &str, &entry);

		orgee = xmms_fetch_spec_new (entry, info, sp, err);
		if (xmms_error_iserror (err)) {
			xmms_fetch_spec_free (spec);
			spec = NULL;
			break;
		}

		spec->data.organize.keys[org_idx] = str;
		spec->data.organize.data[org_idx] = orgee;

		org_idx++;
		xmmsv_dict_iter_next (it);
	}
	xmmsv_dict_iter_explicit_destroy (it);

	s4_sourcepref_unref (sp);

	return spec;
}
예제 #8
0
static int32_t
xmms_visualization_client_set_properties (xmms_visualization_t *vis, int32_t id, xmmsv_t* prop, xmms_error_t *err)
{
	xmms_vis_client_t *c;
	xmmsv_dict_iter_t *it;
	const gchar *key, *valstr;
	xmmsv_t *value;

	x_fetch_client (id);

	if (!xmmsv_get_type (prop) == XMMSV_TYPE_DICT) {
		xmms_error_set (err, XMMS_ERROR_INVAL, "properties must be sent as a dict!");
	} else {
		/* record every pair */
		xmmsv_get_dict_iter (prop, &it);
		while (xmmsv_dict_iter_valid (it)) {
			if (!xmmsv_dict_iter_pair (it, &key, &value)) {
				xmms_error_set (err, XMMS_ERROR_INVAL, "key-value property pair could not be read!");
			} else if (!xmmsv_get_string (value, &valstr)) {
				xmms_error_set (err, XMMS_ERROR_INVAL, "property value could not be read!");
			} else if (!property_set (&c->prop, key, valstr)) {
				xmms_error_set (err, XMMS_ERROR_INVAL, "property could not be set!");
			}
			xmmsv_dict_iter_next (it);
		}
		/* TODO: propagate new format to xform! */
	}

	x_release_client ();

	return (++c->format);
}
예제 #9
0
static void
__int_xmms_cmd_rehash (xmms_object_t *object, xmms_object_cmd_arg_t *arg)
{
	xmmsv_t *t;
	if (xmmsv_list_get_size (arg->args) != 1) {
		XMMS_DBG ("Wrong number of arguments to rehash (%d)", xmmsv_list_get_size (arg->args));
		xmms_error_set (&arg->error, XMMS_ERROR_INVAL, "Wrong number of arguments to rehash");
		return;
	}
	gint32 argval0;

	if (!xmmsv_list_get (arg->args, 0, &t)) {
		XMMS_DBG ("Missing arg 0 in rehash");
		xmms_error_set (&arg->error, XMMS_ERROR_INVAL, "Missing arg 0 in rehash");
		return;
	}
	if (!xmmsv_get_int (t, &argval0)) {
		XMMS_DBG ("Error parsing arg 0 in rehash");
		xmms_error_set (&arg->error, XMMS_ERROR_INVAL, "Error parsing arg 0 in rehash");
		return;
	}

	xmms_medialib_client_rehash ((xmms_medialib_t *) object, argval0, &arg->error);
	arg->retval = xmmsv_new_none ();
}
예제 #10
0
파일: playlist.c 프로젝트: chrippa/xmms2
/**
 * Insert an entry at a given position in the playlist without
 * validating it.
 *
 * @internal
 */
void
xmms_playlist_insert_entry (xmms_playlist_t *playlist, const gchar *plname,
                            guint32 pos, xmms_medialib_entry_t file,
                            xmms_error_t *err)
{
    xmms_medialib_session_t *session;
    xmmsv_t *dict;
    gint currpos;
    gint len;
    xmmsv_coll_t *plcoll;
    gboolean valid;

    g_mutex_lock (playlist->mutex);

    do {
        session = xmms_medialib_session_begin_ro (playlist->medialib);
        valid = xmms_medialib_check_id (session, file);
    } while (!xmms_medialib_session_commit (session));

    if (!valid) {
        g_mutex_unlock (playlist->mutex);
        xmms_error_set (err, XMMS_ERROR_NOENT,
                        "That is not a valid medialib id!");
        return;
    }


    plcoll = xmms_playlist_get_coll (playlist, plname, err);
    if (plcoll == NULL) {
        /* FIXME: happens ? */
        g_mutex_unlock (playlist->mutex);
        return;
    }

    len = xmms_playlist_coll_get_size (plcoll);
    if (pos > len) {
        xmms_error_set (err, XMMS_ERROR_GENERIC,
                        "Could not insert entry outside of playlist!");
        g_mutex_unlock (playlist->mutex);
        return;
    }
    xmmsv_coll_idlist_insert (plcoll, pos, file);

    /** propagate the MID ! */
    dict = xmms_playlist_changed_msg_new (playlist, XMMS_PLAYLIST_CHANGED_INSERT, file, plname);
    xmmsv_dict_set_int (dict, "position", pos);
    xmms_playlist_changed_msg_send (playlist, dict);

    /** update position once client is familiar with the new item. */
    currpos = xmms_playlist_coll_get_currpos (plcoll);
    if (pos <= currpos) {
        currpos++;
        xmms_collection_set_int_attr (plcoll, "position", currpos);
        XMMS_PLAYLIST_CURRPOS_MSG (currpos, plname);
    }

    g_mutex_unlock (playlist->mutex);
}
예제 #11
0
static gint
xmms_mpc_read (xmms_xform_t *xform, xmms_sample_t *buffer,
               gint len, xmms_error_t *err)
{
    MPC_SAMPLE_FORMAT internal[MPC_DECODER_BUFFER_LENGTH];
    xmms_mpc_data_t *data;
    mpc_uint32_t ret;
    guint size;

    data = xmms_xform_private_data_get (xform);

    size = MIN (data->buffer->len, len);

#ifdef HAVE_MPCDEC_OLD
    if (size <= 0) {
        ret = mpc_decoder_decode (&data->decoder, internal, NULL, NULL);
        if (ret == -1) {
            xmms_error_set (err, XMMS_ERROR_GENERIC, "Musepack decoder failed");
            return -1;
        }

        ret *= xmms_sample_size_get (XMMS_SAMPLE_FORMAT_FLOAT);
        ret *= data->info.channels;

        g_string_append_len (data->buffer, (gchar *) internal, ret);
    }
#else
    if (size <= 0) {
        mpc_frame_info frame;

        frame.buffer = internal;
        do {
            ret = mpc_demux_decode (data->demux, &frame);
        } while (frame.bits != -1 && frame.samples == 0);

        if (frame.bits == -1 && ret != MPC_STATUS_OK) {
            xmms_error_set (err, XMMS_ERROR_GENERIC, "Musepack decoder failed");
            return -1;
        }
        ret = frame.samples;

        ret *= xmms_sample_size_get (XMMS_SAMPLE_FORMAT_FLOAT);
        ret *= data->info.channels;

        g_string_append_len (data->buffer, (gchar *) internal, ret);
    }
#endif

    /* Update the current size of available data */
    size = MIN (data->buffer->len, len);

    memcpy (buffer, data->buffer->str, size);
    g_string_erase (data->buffer, 0, size);

    return size;
}
예제 #12
0
static xmmsv_t *
normalize_metadata_fields (xmmsv_t *fetch, xmms_error_t *err)
{
	gpointer SENTINEL = GINT_TO_POINTER (0x31337);
	GHashTable *table;

	xmmsv_list_iter_t *it;
	xmmsv_t *fields;

	if (!xmmsv_dict_get (fetch, "fields", &fields)) {
		/* No fields means that we should fetch all fields */
		return NULL;
	}

	if (xmmsv_get_type (fields) != XMMSV_TYPE_LIST) {
		const gchar *message = "'fields' must be a list of strings.";
		xmms_error_set (err, XMMS_ERROR_INVAL, message);
		return NULL;
	}

	if (xmmsv_list_get_size (fields) < 1) {
		/* No fields means that we should fetch all fields */
		return NULL;
	}

	table = g_hash_table_new (g_str_hash, g_str_equal);

	xmmsv_get_list_iter (fields, &it);
	while (xmmsv_list_iter_valid (it)) {
		const gchar *value = NULL;

		if (!xmmsv_list_iter_entry_string (it, &value)) {
			const gchar *message = "'fields' entries must be of string type.";
			xmms_error_set (err, XMMS_ERROR_INVAL, message);
			g_hash_table_unref (table);
			return NULL;
		}

		if (g_hash_table_lookup (table, (gpointer) value) == SENTINEL) {
			const gchar *message = "'fields' entries must be unique.";
			xmms_error_set (err, XMMS_ERROR_INVAL, message);
			g_hash_table_unref (table);
			return NULL;
		}

		g_hash_table_insert (table, (gpointer) value, SENTINEL);

		xmmsv_list_iter_next (it);
	}

	g_hash_table_unref (table);

	return fields;
}
예제 #13
0
static void
__int_xmms_cmd_set_property_int (xmms_object_t *object, xmms_object_cmd_arg_t *arg)
{
	xmmsv_t *t;
	if (xmmsv_list_get_size (arg->args) != 4) {
		XMMS_DBG ("Wrong number of arguments to set_property_int (%d)", xmmsv_list_get_size (arg->args));
		xmms_error_set (&arg->error, XMMS_ERROR_INVAL, "Wrong number of arguments to set_property_int");
		return;
	}
	gint32 argval0;
	const char * argval1;
	const char * argval2;
	gint32 argval3;

	if (!xmmsv_list_get (arg->args, 0, &t)) {
		XMMS_DBG ("Missing arg 0 in set_property_int");
		xmms_error_set (&arg->error, XMMS_ERROR_INVAL, "Missing arg 0 in set_property_int");
		return;
	}
	if (!xmmsv_get_int (t, &argval0)) {
		XMMS_DBG ("Error parsing arg 0 in set_property_int");
		xmms_error_set (&arg->error, XMMS_ERROR_INVAL, "Error parsing arg 0 in set_property_int");
		return;
	}
	if (!xmmsv_list_get (arg->args, 1, &t)) {
		XMMS_DBG ("Missing arg 1 in set_property_int");
		xmms_error_set (&arg->error, XMMS_ERROR_INVAL, "Missing arg 1 in set_property_int");
		return;
	}
	if (!xmmsv_get_string (t, &argval1)) {
		XMMS_DBG ("Error parsing arg 1 in set_property_int");
		xmms_error_set (&arg->error, XMMS_ERROR_INVAL, "Error parsing arg 1 in set_property_int");
		return;
	}
	if (!xmmsv_list_get (arg->args, 2, &t)) {
		XMMS_DBG ("Missing arg 2 in set_property_int");
		xmms_error_set (&arg->error, XMMS_ERROR_INVAL, "Missing arg 2 in set_property_int");
		return;
	}
	if (!xmmsv_get_string (t, &argval2)) {
		XMMS_DBG ("Error parsing arg 2 in set_property_int");
		xmms_error_set (&arg->error, XMMS_ERROR_INVAL, "Error parsing arg 2 in set_property_int");
		return;
	}
	if (!xmmsv_list_get (arg->args, 3, &t)) {
		XMMS_DBG ("Missing arg 3 in set_property_int");
		xmms_error_set (&arg->error, XMMS_ERROR_INVAL, "Missing arg 3 in set_property_int");
		return;
	}
	if (!xmmsv_get_int (t, &argval3)) {
		XMMS_DBG ("Error parsing arg 3 in set_property_int");
		xmms_error_set (&arg->error, XMMS_ERROR_INVAL, "Error parsing arg 3 in set_property_int");
		return;
	}

	xmms_medialib_client_set_property_int ((xmms_medialib_t *) object, argval0, argval1, argval2, argval3, &arg->error);
	arg->retval = xmmsv_new_none ();
}
예제 #14
0
static gint64
xmms_wave_seek (xmms_xform_t *xform, gint64 samples,
                xmms_xform_seek_mode_t whence, xmms_error_t *error)
{
	xmms_wave_data_t *data;
	gint64 offset;
	gint64 ret;

	g_return_val_if_fail (xform, -1);
	g_return_val_if_fail (samples >= 0, -1);
	g_return_val_if_fail (whence == XMMS_XFORM_SEEK_SET, -1);

	data = xmms_xform_private_data_get (xform);
	g_return_val_if_fail (data, -1);

	/* in mp3 mode, the samples argument actually indicates bytes..
	 * thus we've set up bits_per_sample to 8 and channels to 1 to get
	 * expected behaviour. */

	offset = data->header_size;
	offset += samples * (data->bits_per_sample / 8) * data->channels;

	if (offset < data->header_size) {
		xmms_error_set (error, XMMS_ERROR_INVAL,
		                "Trying to seek before start of stream");
		return -1;
	}

	if (offset > data->header_size + data->bytes_total) {
		xmms_error_set (error, XMMS_ERROR_INVAL,
		                "Trying to seek past end of stream");
		return -1;
	}

	ret = xmms_xform_seek (xform, offset, whence, error);

	if (ret == -1) {
		return -1;
	}

	if (ret != offset) {
		XMMS_DBG ("xmms_xform_seek didn't return expected offset "
		          "(%" G_GINT64_FORMAT " != %" G_GINT64_FORMAT ")",
		          ret, offset);
	}

	ret -= data->header_size;

	ret /= (data->bits_per_sample / 8) * data->channels;

	return ret;
}
예제 #15
0
static gboolean
xmms_xspf_browse (xmms_xform_t *xform, const gchar *url, xmms_error_t *error)
{
	int ret;
	char buf[4096];
	xmlParserCtxtPtr ctx;
	xmlDocPtr doc;

	g_return_val_if_fail (xform, FALSE);

	xmms_error_reset (error);

	ctx = xmlCreatePushParserCtxt (NULL, NULL, buf, 0, NULL);

	if (!ctx) {
		xmms_error_set (error, XMMS_ERROR_OOM, "Could not allocate xml parser");
		return FALSE;
	}

	while ((ret = xmms_xform_read (xform, buf, sizeof (buf), error)) > 0) {
		if ((xmlParseChunk (ctx, buf, ret, 0)) != 0) {
			break;
		}
	}

	if (ret < 0) {
		xmms_error_set (error, XMMS_ERROR_GENERIC,
		                "failed to read data from previous xform");
		xmlFreeParserCtxt (ctx);
		return FALSE;
	}

	xmlParseChunk (ctx, buf, 0, 1);

	if (ctx->lastError.message) {
		xmms_error_set (error, XMMS_ERROR_INVAL, ctx->lastError.message);
		xmlFreeParserCtxt (ctx);
		return FALSE;
	}

	doc = ctx->myDoc;

	if (!xmms_xspf_browse_add_entries (xform, doc, error)) {
		xmlFreeParserCtxt (ctx);
		return FALSE;
	}

	xmms_error_reset (error);
	xmlFreeParserCtxt (ctx);

	return TRUE;
}
예제 #16
0
static GTree *
xmms_output_volume_get (xmms_output_t *output, xmms_error_t *error)
{
	GTree *ret;
	xmms_volume_map_t map;

	if (!output->plugin) {
		xmms_error_set (error, XMMS_ERROR_GENERIC,
		                "couldn't get volume, output plugin not loaded");
		return NULL;
	}

	if (!xmms_output_plugin_method_volume_get_available (output->plugin)) {
		xmms_error_set (error, XMMS_ERROR_GENERIC,
		                "operation not supported");
		return NULL;
	}

	xmms_error_set (error, XMMS_ERROR_GENERIC,
	                "couldn't get volume");

	xmms_volume_map_init (&map);

	/* ask the plugin how much channels it would like to set */
	if (!xmms_output_plugin_method_volume_get (output->plugin, output,
	                                           NULL, NULL, &map.num_channels)) {
		return NULL;
	}

	/* check for sane values */
	g_return_val_if_fail (map.num_channels > 0, NULL);
	g_return_val_if_fail (map.num_channels <= VOLUME_MAX_CHANNELS, NULL);

	map.names = g_new (const gchar *, map.num_channels);
	map.values = g_new (guint, map.num_channels);

	map.status = xmms_output_plugin_method_volume_get (output->plugin, output,
	                                                   map.names, map.values,
	                                                   &map.num_channels);

	if (!map.status || !map.num_channels) {
		return NULL; /* error is set (-> no leak) */
	}

	ret = xmms_volume_map_to_dict (&map);

	/* success! */
	xmms_error_reset (error);

	return ret;
}
예제 #17
0
static gboolean
xmms_rss_browse (xmms_xform_t *xform, const gchar *url, xmms_error_t *error)
{
	int ret;
	char buffer[1024];
	xmlSAXHandler handler;
	xmlParserCtxtPtr ctx;
	xmms_rss_data_t data;

	g_return_val_if_fail (xform, FALSE);

	memset (&handler, 0, sizeof (handler));
	memset (&data, 0, sizeof (data));

	handler.startElement = (startElementSAXFunc) xmms_rss_start_element;
	handler.error = (errorSAXFunc) xmms_rss_error;
	handler.fatalError = (fatalErrorSAXFunc) xmms_rss_error;

	data.xform = xform;
	data.error = error;
	data.parse_failure = FALSE;

	xmms_error_reset (error);

	ctx = xmlCreatePushParserCtxt (&handler, &data, buffer, 0, NULL);
	if (!ctx) {
		xmms_error_set (error, XMMS_ERROR_OOM,
		                "Could not allocate xml parser");
		return FALSE;
	}

	while ((ret = xmms_xform_read (xform, buffer, sizeof (buffer), error)) > 0) {
		xmlParseChunk (ctx, buffer, ret, 0);
	}

	if (ret < 0) {
		xmms_error_set (error, XMMS_ERROR_GENERIC, "xmms_xform_read failed");
		return FALSE;
	}

	if (data.parse_failure)
		return FALSE;

	xmlParseChunk (ctx, buffer, 0, 1);

	xmms_error_reset (error);
	xmlFreeParserCtxt (ctx);

	return TRUE;
}
예제 #18
0
/**
 * Sanitize the 'get' property of a 'metadata' fetch specification.
 */
static xmmsv_t *
normalize_metadata_get (xmmsv_t *fetch, xmms_error_t *err)
{
	xmmsv_list_iter_t *it;
	xmmsv_t *get, *list;
	guint32 values;

	if (!xmmsv_dict_get (fetch, "get", &get) ||
	    xmmsv_get_type (get) != XMMSV_TYPE_LIST ||
	    xmmsv_list_get_size (get) < 1) {
		const gchar *message = "'get' must be a non-empty list of strings.";
		xmms_error_set (err, XMMS_ERROR_INVAL, message);
		return NULL;
	}

	list = xmmsv_new_list ();
	values = 0;

	/* Scan for duplicates or invalid values */
	xmmsv_get_list_iter (get, &it);
	while (xmmsv_list_iter_valid (it)) {
		const gchar *value = NULL;
		guint32 get_as_int, mask;

		xmmsv_list_iter_entry_string (it, &value);

		if (!metadata_value_from_string (value, &get_as_int)) {
			const gchar *message = "'get' entries must be 'id', 'field', 'value' or 'source'.";
			xmms_error_set (err, XMMS_ERROR_INVAL, message);
			xmmsv_unref (list);
			return NULL;
		}

		mask = 1 << (get_as_int + 1);
		if (values & mask) {
			const gchar *message = "'get' entries must be unique.";
			xmms_error_set (err, XMMS_ERROR_INVAL, message);
			xmmsv_unref (list);
			return NULL;
		}

		values |= mask;

		xmmsv_list_append_int (list, get_as_int);
		xmmsv_list_iter_next (it);
	}

	return list;
}
예제 #19
0
static s4_sourcepref_t *
normalize_source_preferences (xmmsv_t *fetch, s4_sourcepref_t *prefs, xmms_error_t *err)
{
	s4_sourcepref_t *sp;
	xmmsv_list_iter_t *it;
	const char **strv;
	const gchar *str;
	xmmsv_t *list;
	gint length, idx;

	if (!xmmsv_dict_get (fetch, "source-preference", &list)) {
		return s4_sourcepref_ref (prefs);
	}

	if (xmmsv_get_type (list) != XMMSV_TYPE_LIST) {
		const gchar *message = "'source-preference' must be a list of strings.";
		xmms_error_set (err, XMMS_ERROR_INVAL, message);
		return NULL;
	}

	length = xmmsv_list_get_size (list);
	if (length == 0) {
		return s4_sourcepref_ref (prefs);
	}

	strv = g_new0 (const char *, length + 1);

	idx = 0;

	xmmsv_get_list_iter (list, &it);
	while (xmmsv_list_iter_valid (it)) {
		if (!xmmsv_list_iter_entry_string (it, &str)) {
			const gchar *message = "'source-preference' must be a list of strings.";
			xmms_error_set (err, XMMS_ERROR_INVAL, message);
			g_free (strv);
			return NULL;
		}

		strv[idx++] = str;

		xmmsv_list_iter_next (it);
	}

	sp = s4_sourcepref_create (strv);
	g_free (strv);

	return sp;
}
예제 #20
0
/**
 * Extract hostname, port and command from an url.
 * daap://hostname:port/command
 */
static gboolean
get_data_from_url (const gchar *url, gchar **host, guint *port, gchar **cmd, xmms_error_t *err)
{
	const gchar *port_ptr, *cmd_ptr, *end_ptr, *stripped;

	stripped = url + sizeof (gchar) * strlen ("daap://");

	end_ptr = stripped + sizeof (gchar) * strlen (stripped);

	if (stripped == end_ptr) {
		xmms_error_set (err, XMMS_ERROR_INVAL, "Empty URL");
		return FALSE;
	}

	port_ptr = strstr (stripped, ":");
	if (port && port_ptr && (port_ptr + 1) != end_ptr) {
		*port = strtol (port_ptr + 1, (gchar **) NULL, 10);
		if (*port == 0) {
			*port = DEFAULT_DAAP_PORT;
		}
	} else if (port) {
		*port = DEFAULT_DAAP_PORT;
	}

	cmd_ptr = strstr (stripped, "/");
	if (cmd && cmd_ptr && (cmd_ptr + 1) != end_ptr) {
		*cmd = g_strdup (cmd_ptr);
	} else if (cmd) {
		/* cmd wanted but not found */
		xmms_error_set (err, XMMS_ERROR_INVAL, "No file requested");
	} else if (!cmd && cmd_ptr && (cmd_ptr + 1) != end_ptr) {
		/* cmd not wanted but found */
		xmms_error_set (err, XMMS_ERROR_NOENT, "No such directory");
		return FALSE;
	}

	if (host) {
		if (port_ptr) {
			*host = g_strndup (stripped, port_ptr - stripped);
		} else if (cmd_ptr) {
			*host = g_strndup (stripped, cmd_ptr - stripped);
		} else {
			*host = g_strdup (stripped);
		}
	}

	return TRUE;
}
예제 #21
0
guint
daap_command_login (gchar *host, gint port, guint request_id, xmms_error_t *err) {
	xmms_daap_conn_t *conn;
	cc_data_t *cc_data;

	guint session_id = 0;

	conn = daap_conn_new (host, port);

	if (!conn) {
		xmms_error_set (err, XMMS_ERROR_GENERIC,
		                "Connection to server failed! "
		                "Please make sure the url is of the form:\n"
		                "daap://ip[:port]/[song]");
		return 0;
	}

	cc_data = daap_request_data (conn->chan, "/login", host, request_id);
	if (cc_data) {
		session_id = cc_data->session_id;
		cc_data_free (cc_data);
	}

	daap_conn_free (conn);

	return session_id;
}
예제 #22
0
int32_t
init_shm (xmms_visualization_t *vis, int32_t id, int32_t shmid, xmms_error_t *err)
{
	xmms_error_set (err, XMMS_ERROR_NO_SAUSAGE,
	                "Shared Memory not supported by this platform!");
	return -1;
}
예제 #23
0
static gint64
xmms_samba_seek (xmms_xform_t *xform, gint64 offset,
                 xmms_xform_seek_mode_t whence, xmms_error_t *error)
{
	xmms_samba_data_t *data;
	gint w = 0;
	off_t res;

	g_return_val_if_fail (xform, -1);
	data = xmms_xform_private_data_get (xform);
	g_return_val_if_fail (data, -1);

	switch (whence) {
		case XMMS_XFORM_SEEK_SET:
			w = SEEK_SET;
			break;
		case XMMS_XFORM_SEEK_END:
			w = SEEK_END;
			break;
		case XMMS_XFORM_SEEK_CUR:
			w = SEEK_CUR;
			break;
	}

	G_LOCK (mutex);
	res = smbc_lseek (data->fd, offset, w);
	G_UNLOCK (mutex);

	if (res == -1) {
		xmms_error_set (error, XMMS_ERROR_INVAL, "Couldn't seek");
	}

	return res;
}
예제 #24
0
파일: gvfs.c 프로젝트: kfihihc/xmms2-devel
static gboolean
xmms_gvfs_browse (xmms_xform_t *xform, const gchar *url, xmms_error_t *error)
{
    GError *err = NULL;
    GFile *file;
    GFileInfo *info;
    GFileEnumerator *enumerator;

    /* Same hack as in _init */
    if (!g_ascii_strncasecmp (url, "file://", 7)) {
        file = g_file_new_for_path (url+7);
    } else {
        file = g_file_new_for_uri (url);
    }
    enumerator = g_file_enumerate_children (file,
                                            G_FILE_ATTRIBUTE_STANDARD_NAME ","
                                            G_FILE_ATTRIBUTE_STANDARD_TYPE ","
                                            G_FILE_ATTRIBUTE_STANDARD_SIZE,
                                            G_FILE_QUERY_INFO_NONE,
                                            NULL,
                                            &err);

    g_object_unref (file);

    if (!enumerator) {
        xmms_error_set (error, XMMS_ERROR_GENERIC, err->message);
        return FALSE;
    }

    while ((info = g_file_enumerator_next_file (enumerator, NULL, NULL))) {
        guint32 child_type, flags = 0;
        guint64 child_size;
        const gchar *child_name;

        child_name = g_file_info_get_attribute_byte_string (info,
                     G_FILE_ATTRIBUTE_STANDARD_NAME);
        child_type = g_file_info_get_attribute_uint32 (info,
                     G_FILE_ATTRIBUTE_STANDARD_TYPE);
        child_size = g_file_info_get_attribute_uint64 (info,
                     G_FILE_ATTRIBUTE_STANDARD_SIZE);

        if (child_type & G_FILE_TYPE_DIRECTORY) {
            flags |= XMMS_XFORM_BROWSE_FLAG_DIR;
        }

        xmms_xform_browse_add_entry (xform, child_name, flags);

        if (~child_type & G_FILE_TYPE_DIRECTORY) {
            xmms_xform_browse_add_entry_property_int (xform,
                    XMMS_MEDIALIB_ENTRY_PROPERTY_SIZE,
                    child_size);
        }

        g_object_unref (info);
    }

    g_file_enumerator_close (enumerator, NULL, NULL);

    return TRUE;
}
예제 #25
0
파일: daap_cmd.c 프로젝트: chrippa/xmms2
guint
daap_command_login (gchar *host, gint port, guint request_id, xmms_error_t *err) {
	GIOChannel *chan;
	cc_data_t *cc_data;

	guint session_id = 0;

	chan = daap_open_connection (host, port);
	if (!chan) {
		xmms_error_set (err, XMMS_ERROR_GENERIC,
		                "Connection to server failed! "
		                "Please make sure the url is of the form:\n"
		                "daap://ip[:port]/[song]");
		return 0;
	}

	cc_data = daap_request_data (chan, "/login", host, request_id);
	if (cc_data) {
		session_id = cc_data->session_id;
		cc_data_free (cc_data);
	}

	g_io_channel_shutdown (chan, TRUE, NULL);
	g_io_channel_unref (chan);

	return session_id;
}
예제 #26
0
파일: gvfs.c 프로젝트: kfihihc/xmms2-devel
static gint64
xmms_gvfs_seek (xmms_xform_t *xform, gint64 offset,
                xmms_xform_seek_mode_t whence, xmms_error_t *error)
{
    GSeekType type;
    GError *err = NULL;
    xmms_gvfs_data_t *data = xmms_xform_private_data_get (xform);

    g_return_val_if_fail (data, -1);
    g_return_val_if_fail (!g_input_stream_is_closed (data->handle), -1);

    switch (whence) {
    case XMMS_XFORM_SEEK_CUR:
        type = G_SEEK_CUR;
        break;
    case XMMS_XFORM_SEEK_SET:
        type = G_SEEK_SET;
        break;
    case XMMS_XFORM_SEEK_END:
        type = G_SEEK_END;
        break;
    }

    if (g_seekable_seek (G_SEEKABLE (data->handle), offset, type, NULL, &err)) {
        return g_seekable_tell (G_SEEKABLE (data->handle));
    }

    xmms_error_set (error, XMMS_ERROR_GENERIC, err->message);
    return -1;
}
예제 #27
0
파일: playlist.c 프로젝트: dsheeler/xmms2
static gboolean
xmms_playlist_remove_unlocked (xmms_playlist_t *playlist, const gchar *plname,
                               xmmsv_coll_t *plcoll, guint pos, xmms_error_t *err)
{
	gint currpos;
	xmmsv_t *dict;

	g_return_val_if_fail (playlist, FALSE);

	currpos = xmms_playlist_coll_get_currpos (plcoll);

	if (!xmmsv_coll_idlist_remove (plcoll, pos)) {
		if (err) xmms_error_set (err, XMMS_ERROR_NOENT, "Entry was not in list!");
		return FALSE;
	}

	dict = xmms_playlist_changed_msg_new (playlist, XMMS_PLAYLIST_CHANGED_REMOVE, 0, plname);
	xmmsv_dict_set_int (dict, "position", pos);
	xmms_playlist_changed_msg_send (playlist, dict);

	/* decrease current position if removed entry was before or if it's
	 * the current entry, but only if current position is a valid entry.
	 */
	if (currpos != -1 && pos <= currpos) {
		currpos = MAX (0, currpos - 1);
		xmms_collection_set_int_attr (plcoll, "position", currpos);
		XMMS_PLAYLIST_CURRPOS_MSG (currpos, plname);
	}

	return TRUE;
}
예제 #28
0
static void
xmms_medialib_client_remove_property (xmms_medialib_t *medialib,
                                      xmms_medialib_entry_t entry,
                                      const gchar *source, const gchar *key,
                                      xmms_error_t *error)
{
	xmms_medialib_session_t *session;

	do {
		session = xmms_medialib_session_begin (medialib);
		if (g_ascii_strcasecmp (source, "server") == 0) {
			xmms_error_set (error, XMMS_ERROR_GENERIC, "Can't remove properties set by the server!");
		} else if (xmms_medialib_check_id (session, entry)) {
			xmms_medialib_property_remove (session, entry, source, key, error);
		} else {
			xmms_error_set (error, XMMS_ERROR_NOENT, "No such entry");
		}
	} while (!xmms_medialib_session_commit (session));
}
예제 #29
0
파일: main.c 프로젝트: dreamerc/xmms2
/**
 * @internal Function to respond to the 'hello' sent from clients on connect
 */
static void
xmms_main_client_hello (xmms_object_t *object, gint protocolver, const gchar *client, xmms_error_t *error)
{
	if (protocolver != XMMS_IPC_PROTOCOL_VERSION) {
		xmms_log_info ("Client '%s' with bad protocol version (%d, not %d) connected", client, protocolver, XMMS_IPC_PROTOCOL_VERSION);
		xmms_error_set (error, XMMS_ERROR_INVAL, "Bad protocol version");
		return;
	}
	XMMS_DBG ("Client '%s' connected", client);
}
예제 #30
-1
파일: mpg123.c 프로젝트: vdust/xmms2-devel
static gint
xmms_mpg123_read (xmms_xform_t *xform, xmms_sample_t *buf, gint len,
                  xmms_error_t *err)
{
	xmms_mpg123_data_t *data;
	int result = MPG123_OK;
	size_t read = 0;

	data = xmms_xform_private_data_get (xform);
	g_return_val_if_fail (data, -1);

	while (read == 0) {
		gint ret = 0;

		if (result == MPG123_NEED_MORE) {
			ret = xmms_xform_read (xform, data->buf, BUFSIZE, err);
			if (ret < 0) {
				return ret;
			} else if (ret == 0) {
				data->eof_found = TRUE;
			}
		}

		result = mpg123_decode (data->decoder, data->buf, (size_t) ret,
		                        buf, len, &read);

		if (result == MPG123_NEED_MORE && data->eof_found) {
			/* We need more data, but there's none available
			 * so libmpg123 apparently missed an EOF */
			result = MPG123_DONE;
			break;
		} else if (result != MPG123_OK && result != MPG123_NEED_MORE) {
			/* This is some uncommon result like EOF, handle outside
			 * the loop */
			break;
		}
	}

	if (result == MPG123_DONE) {
		/* This is just normal EOF reported from libmpg123 */
		XMMS_DBG ("Got EOF while decoding stream");
		return 0;
	} else if (result == MPG123_NEW_FORMAT) {
		/* FIXME: When we can handle format changes, modify this */
		xmms_error_set (err,
		                XMMS_ERROR_GENERIC,
		                "The output format changed, XMMS2 can't handle that");
		return -1;
	} else if (result == MPG123_ERR) {
		xmms_error_set (err,
		                XMMS_ERROR_GENERIC,
		                mpg123_strerror (data->decoder));
		return -1;
	}

	return (gint) read;
}