Exemple #1
0
int upnp_append_variable(struct action_event *event,
			 int varnum, char *paramname)
{
	char *value;
	struct service *service = event->service;
	int retval = -1;

	ENTER();

	if (varnum >= service->variable_count) {
		upnp_set_error(event, UPNP_E_INTERNAL_ERROR,
			       "Internal Error - illegal variable number %d",
			       varnum);
		goto out;
	}

	ithread_mutex_lock(service->service_mutex);

	value = (char *) service->variable_values[varnum];
	if (value == NULL) {
		upnp_set_error(event, UPNP_E_INTERNAL_ERROR,
			       "Internal Error");
	} else {
		retval = upnp_add_response(event, paramname, value);
	}

	ithread_mutex_unlock(service->service_mutex);
out:
	LEAVE();
	return retval;
}
Exemple #2
0
DBG_STATIC int xpause(struct action_event *event)
{
	int rc = 0;

	if (upnp_obtain_instanceid(event, NULL))
	{
		upnp_set_error(event, UPNP_TRANSPORT_E_INVALID_IID, "ID non-zero invalid");
		return -1;
	}

	// Check MPD connection
	if (check_mpd_connection(TRUE) == STATUS_FAIL)
		return -1;

	ithread_mutex_lock(&transport_mutex);

	switch (transport_state)
	{
	case TRANSPORT_STOPPED:
		break;
	case TRANSPORT_PLAYING:
		if (output_pause())
		{
			upnp_set_error(event, UPNP_TRANSPORT_E_NO_CONTENTS, "Player Pause failed");
			rc = -1;
		}
		else
		{
			transport_state = TRANSPORT_PAUSED_PLAYBACK;
			transport_change_var(event, TRANSPORT_VAR_TRANSPORT_STATE, "PAUSED_PLAYBACK");
		}
		break;

	case TRANSPORT_PAUSED_PLAYBACK:
		if (output_play())
		{
			upnp_set_error(event, UPNP_TRANSPORT_E_NO_CONTENTS, "Player Start failed");
			rc = -1;
		}
		else
		{
			transport_state = TRANSPORT_PLAYING;
			transport_change_var(event, TRANSPORT_VAR_TRANSPORT_STATE, "PLAYING");
		}
		break;

	case TRANSPORT_TRANSITIONING:
	case TRANSPORT_NO_MEDIA_PRESENT:
		/* action not allowed in these states - error 701 */
		upnp_set_error(event, UPNP_TRANSPORT_E_TRANSITION_NA, "Transition not allowed");
		break;
	}

	ithread_mutex_unlock(&transport_mutex);

	return rc;
}
static int play(struct action_event *event)
{
	if (obtain_instanceid(event, NULL) < 0) {
		return -1;
	}

	int rc = 0;
	service_lock();
	switch (transport_state_) {
	// even if already playing, we must restart playback when Play
	// action is executed. Kinsky, for example, would not send Stop
	// when changing tracks and playback is already in progress -
	// it will just set new URI, and send Play command
	case TRANSPORT_PLAYING:
	case TRANSPORT_STOPPED:
		// If we were stopped before, we start a new song now. So just
		// set the time to zero now; otherwise we will see the old
		// value of the previous song until it updates some fractions
		// of a second later.
		replace_var(TRANSPORT_VAR_REL_TIME_POS, kZeroTime);

		/* >>> fall through */

	case TRANSPORT_PAUSED_PLAYBACK:
		if (output_play(&inform_play_transition_from_output)) {
			upnp_set_error(event, 704, "Playing failed");
			rc = -1;
		} else {
			change_transport_state(TRANSPORT_PLAYING);
			const char *av_uri = get_var(TRANSPORT_VAR_AV_URI);
			const char *av_meta = get_var(TRANSPORT_VAR_AV_URI_META);
			replace_current_uri_and_meta(av_uri, av_meta);
		}
		break;

	case TRANSPORT_NO_MEDIA_PRESENT:
	case TRANSPORT_TRANSITIONING:
	case TRANSPORT_PAUSED_RECORDING:
	case TRANSPORT_RECORDING:
		/* action not allowed in these states - error 701 */
		upnp_set_error(event, UPNP_TRANSPORT_E_TRANSITION_NA,
			       "Transition not allowed; allowed=%s",
			       get_var(TRANSPORT_VAR_CUR_TRANSPORT_ACTIONS));
		rc = -1;
		break;
	}
	service_unlock();

	return rc;
}
Exemple #4
0
DBG_STATIC int get_transport_info(struct action_event *event)
{
	int rc = -1;

	if (upnp_obtain_instanceid(event, NULL))
	{
		upnp_set_error(event, UPNP_TRANSPORT_E_INVALID_IID, "ID non-zero invalid");
		//return -1;
	}

	rc = upnp_append_variable(event, TRANSPORT_VAR_TRANSPORT_STATE, "CurrentTransportState");
	if (rc)
		goto out;

	rc = upnp_append_variable(event, TRANSPORT_VAR_TRANSPORT_STATUS, "CurrentTransportStatus");
	if (rc)
		goto out;

	rc = upnp_append_variable(event, TRANSPORT_VAR_TRANSPORT_PLAY_SPEED, "CurrentSpeed");
	if (rc)
		goto out;

out:
	return rc;
}
static int stop(struct action_event *event)
{
	if (obtain_instanceid(event, NULL) < 0) {
		return -1;
	}

	service_lock();
	switch (transport_state_) {
	case TRANSPORT_STOPPED:
		// nothing to change.
		break;
	case TRANSPORT_PLAYING:
	case TRANSPORT_TRANSITIONING:
	case TRANSPORT_PAUSED_RECORDING:
	case TRANSPORT_RECORDING:
	case TRANSPORT_PAUSED_PLAYBACK:
		output_stop();
		change_transport_state(TRANSPORT_STOPPED);
		break;

	case TRANSPORT_NO_MEDIA_PRESENT:
		/* action not allowed in these states - error 701 */
		upnp_set_error(event, UPNP_TRANSPORT_E_TRANSITION_NA,
			       "Transition not allowed; allowed=%s",
			       get_var(TRANSPORT_VAR_CUR_TRANSPORT_ACTIONS));

		break;
	}
	service_unlock();

	return 0;
}
Exemple #6
0
DBG_STATIC int set_avtransport_uri(struct action_event *event)
{
	char *value;
	int rc = 0;

	if (upnp_obtain_instanceid(event, NULL))
	{
		upnp_set_error(event, UPNP_TRANSPORT_E_INVALID_IID, "ID non-zero invalid");
		return -1;
	}

	value = upnp_get_string(event, "CurrentURI");
	if (value == NULL)
		return -1;

	ithread_mutex_lock(&transport_mutex);

	DBG_PRINT(DBG_LVL4, "%s: Set URI to '%s'\n", __FUNCTION__, value);

	// do the work
	output_set_uri(value);

	transport_set_var(TRANSPORT_VAR_AV_URI, value);

	free(value);

	value = upnp_get_string(event, "CurrentURIMetaData");
	if (value != NULL)
	{
		DBG_PRINT(DBG_LVL4, "%s: Set URI MetaData to '%s'\n", __FUNCTION__, value);

		// First set new value so we may extract some information about
		// the stream (Ex: track_duration)
		transport_set_var(TRANSPORT_VAR_AV_URI_META, value);
		free(value);

		// Locate duration attribute in 'res' element under 'item'
		value = (char *)transport_get_attr_metadata("duration");
		if (value)
		{
			transport_set_var(TRANSPORT_VAR_CUR_TRACK_DUR, value);
			free(value);
		}
	}
	else
	{
		rc = -1;
	}

	transport_state = TRANSPORT_STOPPED;
	transport_set_var(TRANSPORT_VAR_TRANSPORT_STATE, "STOPPED");

	transport_notify_lastchange(event, transport_get_state_lastchange());

	ithread_mutex_unlock(&transport_mutex);

	return rc;
}
static int play(struct action_event *event)
{
	int rc = 0;

	ENTER();

	if (obtain_instanceid(event, NULL)) {
		LEAVE();
		return -1;
	}

	service_lock();
	switch (transport_state_) {
	case TRANSPORT_PLAYING:
		// For clients that didn't get it.
		change_and_notify_transport(TRANSPORT_PLAYING);
		// Set TransportPlaySpeed to '1'
		break;
	case TRANSPORT_STOPPED:
	case TRANSPORT_PAUSED_PLAYBACK:
		if (output_play(&inform_done_playing)) {
			upnp_set_error(event, 704, "Playing failed");
			rc = -1;
		} else {
			change_and_notify_transport(TRANSPORT_PLAYING);
		}
		// Set TransportPlaySpeed to '1'
		break;

	case TRANSPORT_NO_MEDIA_PRESENT:
	case TRANSPORT_TRANSITIONING:
	case TRANSPORT_PAUSED_RECORDING:
	case TRANSPORT_RECORDING:
		/* action not allowed in these states - error 701 */
		upnp_set_error(event, UPNP_TRANSPORT_E_TRANSITION_NA,
			       "Transition not allowed");
		rc = -1;

		break;
	}
	service_unlock();

	LEAVE();
	return rc;
}
Exemple #8
0
DBG_STATIC int xprevious(struct action_event *event)
{
	if (upnp_obtain_instanceid(event, NULL))
	{
		upnp_set_error(event, UPNP_TRANSPORT_E_INVALID_IID, "ID non-zero invalid");
		return -1;
	}

	// Check MPD connection
	if (check_mpd_connection(TRUE) == STATUS_FAIL)
		return -1;

	if (output_prev())
	{
		upnp_set_error(event, UPNP_TRANSPORT_E_TRANSITION_NA, "Player Previous failed");
		return -1;
	}

	return 0;
}
Exemple #9
0
DBG_STATIC int get_position_info(struct action_event *event)
{
	int rc = -1;

	if (upnp_obtain_instanceid(event, NULL))
	{
		upnp_set_error(event, UPNP_TRANSPORT_E_INVALID_IID, "ID non-zero invalid");
		return -1;
	}

	ithread_mutex_lock(&transport_mutex);

	// Calls back into transport to set vars
	output_update_position();

	ithread_mutex_unlock(&transport_mutex);

	rc = upnp_append_variable(event, TRANSPORT_VAR_CUR_TRACK, "Track");
	if (rc)
		goto out;

	rc = upnp_append_variable(event, TRANSPORT_VAR_CUR_TRACK_DUR, "TrackDuration");
	if (rc)
		goto out;

	rc = upnp_append_variable(event, TRANSPORT_VAR_CUR_TRACK_META, "TrackMetaData");
	if (rc)
		goto out;

	rc = upnp_append_variable(event, TRANSPORT_VAR_CUR_TRACK_URI, "TrackURI");
	if (rc)
		goto out;

	rc = upnp_append_variable(event, TRANSPORT_VAR_REL_TIME_POS, "RelTime");
	if (rc)
		goto out;

	rc = upnp_append_variable(event, TRANSPORT_VAR_ABS_TIME_POS, "AbsTime");
	if (rc)
		goto out;

	rc = upnp_append_variable(event, TRANSPORT_VAR_REL_CTR_POS, "RelCount");
	if (rc)
		goto out;

	rc = upnp_append_variable(event, TRANSPORT_VAR_ABS_CTR_POS, "AbsCount");
	if (rc)
		goto out;

out:
	return rc;
}
Exemple #10
0
DBG_STATIC int xseek(struct action_event *event)
{
	char *value, *mode;
	int rc = 0;

	if (upnp_obtain_instanceid(event, NULL))
	{
		upnp_set_error(event, UPNP_TRANSPORT_E_INVALID_IID, "ID non-zero invalid");
		return -1;
	}


	mode = upnp_get_string(event, "Unit");
	if (mode == NULL)
		return -1;

	value = upnp_get_string(event, "Target");
	if (value == NULL)
	{
		free(mode);
		return -1;
	}

	// Check MPD connection
	if (check_mpd_connection(TRUE) == STATUS_FAIL)
		return -1;

	// Attempt to seek player (doesn't work for streams)
	rc = output_seekto(mode, value);
	free(mode);
	free(value);
	if (rc != 0)
	{
		upnp_set_error(event, UPNP_TRANSPORT_E_ILL_SEEKTARGET, "Player Seek failed");
		return -1;
	}

	return rc;
}
static int pause_stream(struct action_event *event)
{
	int rc = 0;
	ENTER();

	if (obtain_instanceid(event, NULL)) {
		LEAVE();
		return -1;
	}

	service_lock();
	switch (transport_state_) {
        case TRANSPORT_PAUSED_PLAYBACK:
		// For clients that didn't get it.
		change_and_notify_transport(TRANSPORT_PAUSED_PLAYBACK);
		break;

	case TRANSPORT_PLAYING:
		if (output_pause()) {
			upnp_set_error(event, 704, "Pause failed");
			rc = -1;
		} else {
			change_and_notify_transport(TRANSPORT_PAUSED_PLAYBACK);
		}
		// Set TransportPlaySpeed to '1'
		break;

        default:
		/* action not allowed in these states - error 701 */
		upnp_set_error(event, UPNP_TRANSPORT_E_TRANSITION_NA,
			       "Transition not allowed");
		rc = -1;
        }
	service_unlock();

	LEAVE();

	return rc;
}
Exemple #12
0
static int get_media_info(struct action_event *event)
{
	int rc = -1;

	if (upnp_obtain_instanceid(event, NULL))
	{
		upnp_set_error(event, UPNP_TRANSPORT_E_INVALID_IID, "ID non-zero invalid");
		return -1;
	}

	rc = upnp_append_variable(event, TRANSPORT_VAR_NR_TRACKS, "NrTracks");
	if (rc)
		goto out;

	rc = upnp_append_variable(event, TRANSPORT_VAR_CUR_MEDIA_DUR, "MediaDuration");
	if (rc)
		goto out;

	rc = upnp_append_variable(event, TRANSPORT_VAR_AV_URI, "CurrentURI");
	if (rc)
		goto out;

	rc = upnp_append_variable(event, TRANSPORT_VAR_AV_URI_META, "CurrentURIMetaData");
	if (rc)
		goto out;

	rc = upnp_append_variable(event, TRANSPORT_VAR_NEXT_AV_URI, "NextURI");
	if (rc)
		goto out;

	rc = upnp_append_variable(event, TRANSPORT_VAR_NEXT_AV_URI_META, "NextURIMetaData");
	if (rc)
		goto out;

	rc = upnp_append_variable(event, TRANSPORT_VAR_REC_MEDIA, "PlayMedium");
	if (rc)
		goto out;

	rc = upnp_append_variable(event, TRANSPORT_VAR_REC_MEDIUM, "RecordMedium");
	if (rc)
		goto out;

	rc = upnp_append_variable(event,
				  TRANSPORT_VAR_REC_MEDIUM_WR_STATUS,
				  "WriteStatus");
	if (rc)
		goto out;

out:
	return rc;
}
static int obtain_instanceid(struct action_event *event, int *instance)
{
	char *value = upnp_get_string(event, "InstanceID");
	if (value == NULL) {
		upnp_set_error(event, UPNP_SOAP_E_INVALID_ARGS,
			       "Missing InstanceID");
		return -1;
	}
	free(value);

	// TODO - parse value, and store in *instance, if instance!=NULL

	return 0;
}
Exemple #14
0
DBG_STATIC int get_device_caps(struct action_event *event)
{
	int rc = 0;

	if (upnp_obtain_instanceid(event, NULL))
	{
		upnp_set_error(event, UPNP_TRANSPORT_E_INVALID_IID, "ID non-zero invalid");
		return -1;
	}

	// *** TODO: Add some information

	return rc;
}
Exemple #15
0
DBG_STATIC int xplaymode(struct action_event *event)
{
	char *newmode;
	int rc = 0;

	if (upnp_obtain_instanceid(event, NULL))
	{
		upnp_set_error(event, UPNP_TRANSPORT_E_INVALID_IID, "ID non-zero invalid");
		return -1;
	}

	newmode = upnp_get_string(event, "NewPlayMode");
	DBG_PRINT(DBG_LVL4, "Set NewPlayMode: %s\n", newmode);

	// Check MPD connection
	if (check_mpd_connection(TRUE) == STATUS_FAIL)
		return -1;

	ithread_mutex_lock(&transport_mutex);

	rc = output_playmode(newmode);
	if (rc != 0)
	{
		free(newmode);
		upnp_set_error(event, UPNP_TRANSPORT_E_PLAYMODE_NS, "Set playmode failed");
		goto out;
	}

	transport_change_var(event, TRANSPORT_VAR_CUR_PLAY_MODE, newmode);
	free(newmode);

out:
	ithread_mutex_unlock(&transport_mutex);

	return rc;
}
Exemple #16
0
DBG_STATIC int get_transport_settings(struct action_event *event)
{
	int rc = -1;

	if (upnp_obtain_instanceid(event, NULL))
	{
		upnp_set_error(event, UPNP_TRANSPORT_E_INVALID_IID, "ID non-zero invalid");
		return -1;
	}

	rc = upnp_append_variable(event, TRANSPORT_VAR_CUR_PLAY_MODE, "CurrentPlayMode");
	if (rc)
		goto out;

	rc = upnp_append_variable(event, TRANSPORT_VAR_CUR_REC_QUAL_MODE, "CurrentRecordQualityMode");
	if (rc)
		goto out;

out:
	return rc;
}
int upnp_append_variable(struct action_event *event,
			 int varnum, const char *paramname)
{
	const char *value;
	struct service *service = event->service;
	int retval = -1;

	//ENTER();

	assert(event != NULL);
	assert(paramname != NULL);

	if (varnum >= service->variable_count) {
#ifdef HAVE_LIBUPNP
		upnp_set_error(event, UPNP_E_INTERNAL_ERROR,
			       "Internal Error - illegal variable number %d",
			       varnum);
#endif
		goto out;
	}

#ifdef HAVE_LIBUPNP
	ithread_mutex_lock(service->service_mutex);
#endif

#if 0
	fprintf(stderr, "\tHZ: %s = '%s'\n", service->variable_names[varnum],
		service->variable_values[varnum]);
#endif
	value = service->variable_values[varnum];
	assert(value != NULL);
	retval = upnp_add_response(event, paramname, value);

#ifdef HAVE_LIBUPNP
	ithread_mutex_unlock(service->service_mutex);
#endif
out:
	//LEAVE();
	return retval;
}
static int stop(struct action_event *event)
{
	ENTER();

	if (obtain_instanceid(event, NULL)) {
		return -1;
	}

	service_lock();
	switch (transport_state_) {
	case TRANSPORT_STOPPED:
		// For clients that didn't get it.
		change_and_notify_transport(TRANSPORT_STOPPED);
		break;
	case TRANSPORT_PLAYING:
	case TRANSPORT_TRANSITIONING:
	case TRANSPORT_PAUSED_RECORDING:
	case TRANSPORT_RECORDING:
	case TRANSPORT_PAUSED_PLAYBACK:
		output_stop();
		change_and_notify_transport(TRANSPORT_STOPPED);
		// Set TransportPlaySpeed to '1'
		break;

	case TRANSPORT_NO_MEDIA_PRESENT:
		/* action not allowed in these states - error 701 */
		upnp_set_error(event, UPNP_TRANSPORT_E_TRANSITION_NA,
			       "Transition not allowed");

		break;
	}
	service_unlock();

	LEAVE();

	return 0;
}
static int obtain_instanceid(struct action_event *event, int *instance)
{
	char *value;
	int rc = 0;
	
	ENTER();

	value = upnp_get_string(event, "InstanceID");
	if (value == NULL) {
#ifdef HAVE_LIBUPNP
		upnp_set_error(event, UPNP_SOAP_E_INVALID_ARGS,
			       "Missing InstanceID");
#endif
		return -1;
	}
	//printf("%s: InstanceID='%s'\n", __FUNCTION__, value);
	free(value);

	// TODO - parse value, and store in *instance, if instance!=NULL

	LEAVE();

	return rc;
}