pipeplayer/threads.c

191 lines
4.3 KiB
C

#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include "commands.h"
#include "playlist.h"
#include "player.h"
#include "log.h"
#include "threads.h"
#include "pipe.h"
#include "config.h"
#if NOTIFICATION == 1
#include "notify.h"
#endif
void
run_threads(struct mpg_player *player, struct playlist *playlist, char *pipe_path)
{
pthread_t thread_player = {0}, thread_handler = {0};
struct thread_arg arg = {
.player = player,
.playlist = playlist,
.pipe_path = pipe_path,
.thread_player = &thread_player
};
pthread_create(&thread_handler, NULL, input_thread, (void *)&arg);
pthread_join(thread_handler, NULL);
}
void *
play_thread(void *vargp)
{
struct thread_arg *arg = (struct thread_arg *)vargp;
struct playlist *playlist = arg->playlist;
struct mpg_player *player = arg->player;
char *current;
LOG_DEBUG("Starting player thread");
LOG_DEBUG("playlist->path = %s", playlist->path);
LOG_DEBUG("playlist->index = %lu", playlist->index);
LOG_DEBUG("playlist->length = %lu", playlist->length);
// Play after pause
if (playlist->need_cancel && !player->playing) {
LOG_DEBUG("Continue");
play(player);
// If paused again
if (!player->playing)
return 0;
playlist->index++;
}
playlist->need_cancel = true;
for (; playlist->index < playlist->length; playlist->index++) {
current = playlist->array[playlist->index];
prepare_to_play(player, current);
LOG_INFO("Playing %s", current);
#if NOTIFICATION == 1
notify(playlist->names_array[playlist->index]);
#endif
play(player);
// If paused
if (!player->playing)
return 0;
}
free_playlist(playlist);
playlist->need_cancel = false;
player->playing = false;
return 0;
}
void
_restart_playlist_thread(struct playlist *playlist, void *vargp)
{
struct thread_arg *arg = (struct thread_arg *)vargp;
pthread_t *thread_player = arg->thread_player;
LOG_DEBUG("Killing player thread");
if (playlist->need_cancel) {
pthread_cancel(*thread_player);
playlist->need_cancel = false;
}
pthread_create(thread_player, NULL, play_thread, vargp);
}
void *
input_thread(void *vargp)
{
size_t length;
char *command, **command_ptr = (char **) malloc(sizeof(char *));
bool run = true;
struct thread_arg *arg = (struct thread_arg *)vargp;
struct mpg_player *player = arg->player;
pthread_t *thread_player = arg->thread_player;
struct playlist *playlist = arg->playlist;
char *pipe_path = arg->pipe_path;
while (run) {
length = pipe_readline(command_ptr, pipe_path);
command = *command_ptr;
LOG_DEBUG("Command: %s", command);
switch (*command) {
case EXIT:
case EOF:
LOG_DEBUG("Case: EXIT | EOF");
if (playlist->need_cancel)
pthread_cancel(*arg->thread_player);
run = false;
break;
case LOAD:
LOG_DEBUG("Case: LOAD");
playlist->path = malloc(length);
strcpy(playlist->path, command + 1);
load_playlist(playlist);
_restart_playlist_thread(playlist, vargp);
break;
// Only when playlist is loaded
case CLEAR:
LOG_DEBUG("Case: CLEAR");
if (!playlist->need_cancel)
break;
free_playlist(playlist);
pthread_cancel(*thread_player);
playlist->need_cancel = false;
break;
case FORWARD:
LOG_DEBUG("Case: FORWARD");
if (!playlist->need_cancel)
break;
playlist->index = (playlist->index + 1) % playlist->length;
_restart_playlist_thread(playlist, vargp);
break;
case BACKWARD:
LOG_DEBUG("Case: BACKWARD");
if (!playlist->need_cancel)
break;
playlist->index = (playlist->index + playlist->length - 1) % playlist->length;
_restart_playlist_thread(playlist, vargp);
break;
case PAUSE:
LOG_DEBUG("Case: PAUSE");
if (!playlist->need_cancel)
break;
if (player->playing)
player->playing = false;
else
pthread_create(thread_player, NULL, play_thread, vargp);
break;
default:
fprintf(stderr, "Unknown command: %s\n", command);
}
// Clear command
if (command != NULL)
free(command);
}
// Clear command pointer
free(command_ptr);
return 0;
}