Esempio n. 1
0
File: common.c Progetto: zandeez/hgd
/*
 * free a playlist's members but not the list itself
 */
void
hgd_free_playlist(struct hgd_playlist *list)
{
	unsigned int		i;

	for (i = 0; i < list->n_items; i ++) {
		hgd_free_playlist_item(list->items[i]);
		free(list->items[i]);
	}

	free(list->items);
}
Esempio n. 2
0
/*
 * respond to client what is currently playing.
 *
 * response:
 * ok|0				nothing playing
 * ok|1|id|filename|user	track is playing
 * err|...			failure
 */
int
hgd_cmd_now_playing(struct hgd_session *sess, char **args)
{
	struct hgd_playlist_item	 playing;
	char				*reply;
	int				 num_votes;

	(void) args; /* silence compiler */

	memset(&playing, 0, sizeof(playing));
	if (hgd_get_playing_item(&playing) == HGD_FAIL) {
		hgd_sock_send_line(sess->sock_fd, sess->ssl, "err|internal");
		hgd_free_playlist_item(&playing);
		return (HGD_FAIL);
	}

	if (playing.filename == NULL) {
		hgd_sock_send_line(sess->sock_fd, sess->ssl, "ok|0");
	} else {
		num_votes = hgd_get_num_votes();

		xasprintf(&reply, "ok|1|%d|%s|%s|%s|%s|"
		    "%s|%s|%d|%d|%d|%d|%d|%d", /* added in 0.5 */
		    playing.id, playing.filename + strlen(HGD_UNIQ_FILE_PFX),
		    playing.tags.artist, playing.tags.title, playing.user,
		    playing.tags.album, playing.tags.genre,
		    playing.tags.duration, playing.tags.bitrate,
		    playing.tags.samplerate, playing.tags.channels,
		    playing.tags.year, (req_votes - num_votes));
		hgd_sock_send_line(sess->sock_fd, sess->ssl, reply);

		free(reply);
	}

	hgd_free_playlist_item(&playing);

	return (HGD_OK);
}
Esempio n. 3
0
int
hgd_play_loop(void)
{
	int				 ret = HGD_OK;
	struct hgd_playlist_item	 track;

	/* forever play songs */
	DPRINTF(HGD_D_INFO, "Starting play loop");
	while ((!dying) && (!restarting)) {
		memset(&track, 0, sizeof(track));

		if (hgd_get_next_track(&track) == HGD_FAIL) {
			ret = HGD_FAIL;
			break;
		}

		if (track.filename != NULL) {
			DPRINTF(HGD_D_DEBUG, "next track is: '%s'",
			    track.filename);

			hgd_clear_votes();
			if (hgd_play_track(&track,
			    purge_finished_fs, purge_finished_db) != HGD_OK) {
				ret = HGD_FAIL;
				break;
			}
			hgd_clear_votes();
		} else {
			DPRINTF(HGD_D_DEBUG, "no tracks to play");
#ifdef HAVE_PYTHON
			hgd_execute_py_hook("nothing_to_play");
#endif
			sleep(1);
		}
		hgd_free_playlist_item(&track);
	}

	return (ret);
}
Esempio n. 4
0
int
hgd_cmd_vote_off(struct hgd_session *sess, char **args)
{
	struct hgd_playlist_item	 playing;
	char				*pid_path, pid_str[HGD_PID_STR_SZ];
	char				*scmd, id_str[HGD_ID_STR_SZ], *read;
	pid_t				 pid;
	FILE				*pid_file;
	int				 tid = -1, scmd_ret;
	struct flock			 fl;

	fl.l_type   = F_RDLCK;  /* F_RDLCK, F_WRLCK, F_UNLCK    */
	fl.l_whence = SEEK_SET; /* SEEK_SET, SEEK_CUR, SEEK_END */
	fl.l_start  = 0;        /* Offset from l_whence         */
	fl.l_len    = 0;        /* length, 0 = to EOF           */
	fl.l_pid    = getpid(); /* our PID                      */


	DPRINTF(HGD_D_INFO, "%s wants to kill track", sess->user->name);

	memset(&playing, 0, sizeof(playing));
	if (hgd_get_playing_item(&playing) == HGD_FAIL) {
		hgd_sock_send_line(sess->sock_fd, sess->ssl, "err|internal");
		return (HGD_FAIL);
	}

	/* is *anything* playing? */
	if (playing.filename == NULL) {
		DPRINTF(HGD_D_INFO, "No track is playing, can't vote off");
		hgd_sock_send_line(sess->sock_fd, sess->ssl,
		    "err|not_playing");
		return (HGD_FAIL);
	}

	/* is the file they are voting off playing? */
	if (args != NULL) { /* null if call from hgd_cmd_vote_off_noargs */
		tid = atoi(args[0]);
		if (playing.id != tid) {
			DPRINTF(HGD_D_INFO, "Track to voteoff isn't playing");
			hgd_sock_send_line(sess->sock_fd, sess->ssl,
			    "err|wrong_track");
			hgd_free_playlist_item(&playing);
			return (HGD_FAIL);
		}
	}
	hgd_free_playlist_item(&playing);

	/* insert vote */
	switch (hgd_insert_vote(sess->user->name)) {
	case HGD_OK:
		break; /* good */
	case 1:
		/* duplicate vote */
		DPRINTF(HGD_D_INFO, "User '%s' already voted",
		    sess->user->name);
		hgd_sock_send_line(sess->sock_fd, sess->ssl,
		    "err|duplicate_vote");
		return (HGD_OK);
		break;
	case HGD_FAIL:
	default:
		hgd_sock_send_line(sess->sock_fd, sess->ssl, "err|sql");
		return (HGD_FAIL);
	};

	/* play a sound on skipping? */
	if (vote_sound != NULL) {
		DPRINTF(HGD_D_DEBUG, "Play voteoff sound: '%s'", vote_sound);
		xasprintf(&scmd, "mplayer -really-quiet %s", vote_sound);
		scmd_ret = system(scmd);

		/* unreachable as mplayer doesn't return non-zero :\ */
		if (scmd_ret != 0) {
			DPRINTF(HGD_D_WARN,
			    "Vote-off noise failed to play (ret %d): %s",
			    scmd_ret, vote_sound);
		}

		free(scmd);
	}

	/* are we at the vote limit yet? */
	if (hgd_get_num_votes() < req_votes) {
		hgd_sock_send_line(sess->sock_fd, sess->ssl, "ok");
		return (HGD_OK);
	}

	DPRINTF(HGD_D_INFO, "Vote limit exceeded - kill track");

	/* kill mplayer then */
	/* XXX some of this needs to go in mplayer.c */
	xasprintf(&pid_path, "%s/%s", state_path, HGD_MPLAYER_PID_NAME);

	pid_file = fopen(pid_path, "r");
	if (pid_file == NULL) {
		DPRINTF(HGD_D_WARN,
		    "Can't find mplayer pid file: %s: %s", pid_path, SERROR);
		free(pid_path);
		return (HGD_FAIL);
	}

	if (fcntl(fileno(pid_file), F_SETLKW, &fl) == -1) {
		DPRINTF(HGD_D_ERROR, "failed to get lock on pid file");
		fclose(pid_file);
		return (HGD_FAIL);
	}

	free(pid_path);

	/* Read the pid from the pidfile */
	read = fgets(pid_str, HGD_PID_STR_SZ, pid_file);
	if (read == NULL) {
		if (!feof(pid_file)) {
			DPRINTF(HGD_D_WARN, "Can't find pid in pid file");
			fclose(pid_file);
			return (HGD_FAIL);
		}
	}

	/* Read the track id from the pid file */
	read = fgets(id_str, HGD_ID_STR_SZ, pid_file);
	if (read == NULL) {
		if (!feof(pid_file)) {
			DPRINTF(HGD_D_WARN, "Can't find pid in pid file");
			fclose(pid_file);
			return (HGD_FAIL);
		}
	}

	fl.l_type = F_UNLCK;
	fcntl(fileno(pid_file), F_SETLK, &fl);  /* F_GETLK, F_SETLK, F_SETLKW */

	fclose(pid_file);

	if (atoi(id_str) == playing.id) {
		pid = atoi(pid_str);
		DPRINTF(HGD_D_DEBUG, "Killing mplayer");
		if (kill(pid, SIGINT) < 0)
			DPRINTF(HGD_D_WARN, "Can't kill mplayer: %s", SERROR);

		/* Note: player daemon will empty the votes table */
		hgd_sock_send_line(sess->sock_fd, sess->ssl, "ok");
		return (HGD_OK);
	} else {
		DPRINTF(HGD_D_WARN,
		    "Hmm that was racey! wanted to kill %d but %s was playing",
		    playing.id, id_str);
		return(HGD_FAIL);
	}
}