예제 #1
0
파일: playlist.c 프로젝트: jonsafari/mocp
/* Remove items from playlist 'a' that are also present on playlist 'b'. */
void plist_remove_common_items (struct plist *a, struct plist *b)
{
	int i;

	assert (a != NULL);
	assert (b != NULL);

	for (i = 0; i < a->num; i += 1) {
		if (plist_find_fname(b, a->items[i].file) != -1)
			plist_delete (a, i);
	}
}
예제 #2
0
/* Move to the next file depending on the options set, the user
 * request and whether or not there are files in the queue. */
static void go_to_another_file ()
{
	int shuffle = options_get_int ("Shuffle");
	int go_next = (play_next || options_get_int("AutoNext"));
	int curr_playing_curr_pos;
	/* XXX: Shouldn't play_next be protected by mutex? */

	LOCK (curr_playing_mut);
	LOCK (plist_mut);

	/* If we move forward in the playlist and there are some songs in
	 * the queue, then play them. */
	if (plist_count(&queue) && go_next) {
		logit ("Playing file from queue");

		if (!before_queue_fname && curr_playing_fname)
			before_queue_fname = xstrdup (curr_playing_fname);

		curr_plist = &queue;
		curr_playing = plist_next (&queue, -1);

		server_queue_pop (queue.items[curr_playing].file);
		plist_delete (&queue, curr_playing);
	}
	else {
		/* If we just finished playing files from the queue and the
		 * appropriate option is set, continue with the file played
		 * before playing the queue. */
		if (before_queue_fname && options_get_int("QueueNextSongReturn")) {
			free (curr_playing_fname);
			curr_playing_fname = before_queue_fname;
			before_queue_fname = NULL;
		}

		if (shuffle) {
			curr_plist = &shuffled_plist;

			if (plist_count(&playlist)
					&& !plist_count(&shuffled_plist)) {
				plist_cat (&shuffled_plist, &playlist);
				plist_shuffle (&shuffled_plist);

				if (curr_playing_fname)
					plist_swap_first_fname (&shuffled_plist,
							curr_playing_fname);
			}
		}
		else
			curr_plist = &playlist;

		curr_playing_curr_pos = plist_find_fname (curr_plist,
				curr_playing_fname);

		/* If we came from the queue and the last file in
		 * queue wasn't in the playlist, we try to revert to
		 * the QueueNextSongReturn = 1 behaviour. */
		if (curr_playing_curr_pos == -1 && before_queue_fname) {
			curr_playing_curr_pos = plist_find_fname (curr_plist,
					before_queue_fname);
		}

		if (play_prev && plist_count(curr_plist)) {
			logit ("Playing previous...");

			if (curr_playing_curr_pos == -1
					|| started_playing_in_queue) {
				curr_playing = plist_prev (curr_plist, -1);
				started_playing_in_queue = 0;
			}
			else
				curr_playing = plist_prev (curr_plist,
						curr_playing_curr_pos);

			if (curr_playing == -1) {
				if (options_get_int("Repeat"))
					curr_playing = plist_last (curr_plist);
				logit ("Beginning of the list.");
			}
			else
				logit ("Previous item.");
		}
		else if (go_next && plist_count(curr_plist)) {
			logit ("Playing next...");

			if (curr_playing_curr_pos == -1
					|| started_playing_in_queue) {
				curr_playing = plist_next (curr_plist, -1);
				started_playing_in_queue = 0;
			}
			else
				curr_playing = plist_next (curr_plist,
						curr_playing_curr_pos);

			if (curr_playing == -1 && options_get_int("Repeat")) {
				if (shuffle) {
					plist_clear (&shuffled_plist);
					plist_cat (&shuffled_plist, &playlist);
					plist_shuffle (&shuffled_plist);
				}
				curr_playing = plist_next (curr_plist, -1);
				logit ("Going back to the first item.");
			}
			else if (curr_playing == -1)
				logit ("End of the list");
			else
				logit ("Next item");

		}
		else if (!options_get_int("Repeat")) {
			curr_playing = -1;
		}
		else
			debug ("Repeating file");

		if (before_queue_fname)
			free (before_queue_fname);
		before_queue_fname = NULL;
	}

	UNLOCK (plist_mut);
	UNLOCK (curr_playing_mut);
}
예제 #3
0
/* Load M3U file into plist.  Return the number of items read. */
static int plist_load_m3u (struct plist *plist, const char *fname,
		const char *cwd, const int load_serial)
{
	FILE *file;
	char *line;
	int last_added = -1;
	int after_extinf = 0;
	int added = 0;

	if (!(file = fopen(fname, "r"))) {
		error ("Can't open playlist file: %s",
				strerror(errno));
		return 0;
	}

	if (flock(fileno(file), LOCK_SH) == -1)
		logit ("Can't flock() the playlist file: %s", strerror(errno));

	while ((line = read_line(file))) {
		if (!strncmp(line, "#EXTINF:", sizeof("#EXTINF:")-1)) {
			char *comma;
			char *num_err;
			char time_text[10] = "";
			int time_sec;

			if (after_extinf) {
				error ("Broken M3U file: double "
						"#EXTINF.");
				free (line);
				plist_delete (plist, last_added);
				return added;
			}

			/* Find the comma */
			comma = strchr (line + (sizeof("#EXTINF:") - 1), ',');
			if (!comma) {
				error ("Broken M3U file: no comma "
						"in #EXTINF.");
				free (line);
				return added;
			}

			/* Get the time string */
			time_text[sizeof(time_text)-1] = 0;
			strncpy (time_text, line + sizeof("#EXTINF:") - 1,
					MIN(comma - line - (sizeof("#EXTINF:")
						- 1), sizeof(time_text)));
			if (time_text[sizeof(time_text)-1]) {
				error ("Broken M3U file: "
						"wrong time.");
				free (line);
				return added;
			}

			/* Extract the time */
			time_sec = strtol (time_text, &num_err, 10);
			if (*num_err) {
				error ("Broken M3U file: "
						"time is not a number.");
				free (line);
				return added;
			}

			after_extinf = 1;
			last_added = plist_add (plist, NULL);
			plist_set_title_tags (plist, last_added, comma + 1);

			if (*time_text)
				plist_set_item_time (plist, last_added,
						time_sec);
		}
		else if (line[0] != '#') {
			char path[2*PATH_MAX];

			strip_string (line);
			if (strlen(line) <= PATH_MAX) {
				make_path (path, sizeof(path), cwd, line);

				if (plist_find_fname(plist, path) == -1) {
					if (after_extinf)
						plist_set_file (plist,
								last_added,
								path);
					else
						plist_add (plist, path);
					added++;
				}
				else if (after_extinf)
					plist_delete (plist, last_added);
			}
			else if (after_extinf)
				plist_delete (plist, last_added);

			after_extinf = 0;
		}
		else if (load_serial && !strncmp(line, "#MOCSERIAL: ",
					sizeof("#MOCSERIAL: ") - 1)) {
			char *serial_str = line + sizeof("#MOCSERIAL: ") - 1;

			if (serial_str[0]) {
				char *err;
				long serial;

				serial = strtol (serial_str, &err, 0);
				if (!*err) {
					plist_set_serial (plist, serial);
					logit ("Got MOCSERIAL tag with serial %d",
							(int)serial);
				}
			}
		}
		free (line);
	}

	if (flock(fileno(file), LOCK_UN) == -1)
		logit ("Can't flock() (unlock) the playlist file: %s",
				strerror(errno));
	fclose (file);

	return added;
}
예제 #4
0
/* Load M3U file into plist.  Return the number of items read. */
static int plist_load_m3u (struct plist *plist, const char *fname,
		const char *cwd, const int load_serial)
{
	FILE *file;
	char *line = NULL;
	int last_added = -1;
	int after_extinf = 0;
	int added = 0;
	struct flock read_lock = {.l_type = F_RDLCK, .l_whence = SEEK_SET};

	file = fopen (fname, "r");
	if (!file) {
		error_errno ("Can't open playlist file", errno);
		return 0;
	}

	/* Lock gets released by fclose(). */
	if (fcntl (fileno (file), F_SETLKW, &read_lock) == -1)
		log_errno ("Can't lock the playlist file", errno);

	while ((line = read_line (file))) {
		if (!strncmp (line, "#EXTINF:", sizeof("#EXTINF:") - 1)) {
			char *comma, *num_err;
			char time_text[10] = "";
			int time_sec;

			if (after_extinf) {
				error ("Broken M3U file: double #EXTINF!");
				plist_delete (plist, last_added);
				goto err;
			}

			/* Find the comma */
			comma = strchr (line + (sizeof("#EXTINF:") - 1), ',');
			if (!comma) {
				error ("Broken M3U file: no comma in #EXTINF!");
				goto err;
			}

			/* Get the time string */
			time_text[sizeof(time_text) - 1] = 0;
			strncpy (time_text, line + sizeof("#EXTINF:") - 1,
			         MIN(comma - line - (sizeof("#EXTINF:") - 1),
			         sizeof(time_text)));
			if (time_text[sizeof(time_text) - 1]) {
				error ("Broken M3U file: wrong time!");
				goto err;
			}

			/* Extract the time. */
			time_sec = strtol (time_text, &num_err, 10);
			if (*num_err) {
				error ("Broken M3U file: time is not a number!");
				goto err;
			}

			after_extinf = 1;
			last_added = plist_add (plist, NULL);
			plist_set_title_tags (plist, last_added, comma + 1);

			if (*time_text)
				plist_set_item_time (plist, last_added, time_sec);
		}
		else if (line[0] != '#') {
			char path[2 * PATH_MAX];

			strip_string (line);
			if (strlen (line) <= PATH_MAX) {
				make_path (path, sizeof(path), cwd, line);

				if (plist_find_fname (plist, path) == -1) {
					if (after_extinf)
						plist_set_file (plist, last_added, path);
					else
						plist_add (plist, path);
					added += 1;
				}
				else if (after_extinf)
					plist_delete (plist, last_added);
			}
			else if (after_extinf)
				plist_delete (plist, last_added);

			after_extinf = 0;
		}
		else if (load_serial &&
		         !strncmp (line, "#MOCSERIAL: ", sizeof("#MOCSERIAL: ") - 1)) {
			char *serial_str = line + sizeof("#MOCSERIAL: ") - 1;

			if (serial_str[0]) {
				char *err;
				long serial;

				serial = strtol (serial_str, &err, 0);
				if (!*err) {
					plist_set_serial (plist, serial);
					logit ("Got MOCSERIAL tag with serial %ld", serial);
				}
			}
		}
		free (line);
	}

err:
	free (line);
	fclose (file);
	return added;
}