#include <stdio.h>
#include <stdlib.h>
+#include <unistd.h>
#include <string.h>
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
#include <mvcp/mvcp_remote.h>
#include "player.h"
+#include "ui.h"
+#include "timecode.h"
-static void* player_thread_proc(void* data)
+static char* status_to_text(mvcp_status status)
{
- int r;
- int playlist_start_prev = 0;
-// OmPlrStatus st_curr, st_prev;
- player_t* player = (player_t*)data;
-
- g_warning("omnplay_thread_proc\n");
+ switch(status->status)
+ {
+ case unit_offline: return "offline"; break;
+ case unit_undefined: return "undefined"; break;
+ case unit_not_loaded: return "unloaded"; break;
+ case unit_stopped: return "stopped"; break;
+ case unit_playing: return "playing"; break;
+ case unit_paused: return "paused"; break;
+ case unit_disconnected: return "disconnect"; break;
+ case unit_unknown: return "unknown"; break;
+ }
+ return "unknown";
+}
+
+typedef struct player_handle_desc
+{
+ mvcp_parser parser;
+ mvcp conn;
+} player_handle_t;
-// memset(&st_curr, 0, sizeof(OmPlrStatus));
-// memset(&st_prev, 0, sizeof(OmPlrStatus));
+static void player_update_status(player_t* player, mvcp_status_t *status_prev , mvcp_status_t *status_curr,
+ int *playlist_start_prev)
+{
+ int idx;
+ char tc_cur[32], tc_rem[32], *state, status[32], *clip;
- /* connect */
- pthread_mutex_lock(&player->app->players.lock);
-// r = OmPlrOpen(player->host, player->name, (OmPlrHandle*)&player->handle);
- pthread_mutex_unlock(&player->app->players.lock);
- if(r)
+ if(status_curr->status == unit_disconnected)
{
-// g_warning("ERROR: OmPlrOpen(%s, %s) failed with 0x%.8X\n",
-// player->host, player->name, r);
+ tc_cur[0] = 0;
+ tc_rem[0] = 0;
+ clip = "";
+ state = "";
+ strcpy(status, "OFFLINE");
+ }
+ else
+ {
+ int p = status_curr->start + (status_curr->position - status_curr->in);
- return (void*)r;
+ frames2tc(p, 25.0, tc_cur);
+ frames2tc(status_curr->dur - p, 25.0, tc_rem);
+ clip = status_curr->clip;
+ state = status_to_text(status_curr);
+ strcpy(status, "ONLINE");
};
- /* setup to do not reconnect */
- pthread_mutex_lock(&player->app->players.lock);
-// OmPlrSetRetryOpen((OmPlrHandle)player->handle, 0);
- pthread_mutex_unlock(&player->app->players.lock);
+ ui_update_player(player, tc_cur, tc_rem, state, status, clip);
- /* setup directory */
-// if(player->app->players.path[0])
+ /* update remaining time of playlist's item */
+ pthread_mutex_lock(&player->app->playlist.lock);
+ pthread_mutex_lock(&player->app->players.lock);
+ if(player->playlist_length)
{
- pthread_mutex_lock(&player->app->players.lock);
-// r = OmPlrClipSetDirectory((OmPlrHandle)player->handle, player->app->players.path);
- pthread_mutex_unlock(&player->app->players.lock);
+ /* clear remain on "previous" item */
+ if((status_curr->clip_index != status_prev->clip_index && 1 != player->playlist_length) ||
+ (*playlist_start_prev != player->playlist_start))
+ {
+ tc_rem[0] = 0;
+ idx = playlist_item_index /* find_index_of_playlist_item */(player->app, *playlist_start_prev, status_prev->clip_index);
+ if(idx >= 0)
+ ui_playlist_draw_item_rem(player->app, idx, tc_rem);
+ };
- if(r)
+ /* update current item */
+ idx = playlist_item_index /* find_index_of_playlist_item */(player->app, player->playlist_start, status_curr->clip_index);
+ if(idx >= 0)
{
-// g_warning("ERROR: OmPlrClipSetDirectory(%s) failed with 0x%.8X\n",
-// player->app->players.path, r);
+ /* reset value */
+ tc_rem[0] = 0;
- pthread_mutex_lock(&player->app->players.lock);
-// OmPlrClose((OmPlrHandle)player->handle);
- pthread_mutex_unlock(&player->app->players.lock);
+ /* for play and cue calc new value */
+ if(status_curr->status == unit_stopped || status_curr->status == unit_playing || status_curr->status == unit_paused)
+ frames2tc(status_curr->out - status_curr->position, 25.0, tc_rem);
- return (void*)r;
+ /* setup that value */
+ ui_playlist_draw_item_rem(player->app, idx, tc_rem);
};
};
+ pthread_mutex_unlock(&player->app->players.lock);
+ pthread_mutex_unlock(&player->app->playlist.lock);
+};
- /* endless loop */
- for(r = 0 ; !player->app->f_exit && !r;)
- {
- /* sleep */
-#ifdef _WIN32
- Sleep(100);
-#else
- usleep(100000);
-#endif
+static void* player_thread_proc(void* data)
+{
+ int r, f;
+ int playlist_start_prev = 0;
+ mvcp_status_t status_curr, status_prev;
+ player_t* player = (player_t*)data;
+ player_handle_t* handle = player->handle;
+ mvcp_notifier notifier = mvcp_get_notifier(handle->conn);
- /* get status */
+ g_warning("player_thread_proc: started\n");
+
+// memset(&st_curr, 0, sizeof(OmPlrStatus));
+// memset(&st_prev, 0, sizeof(OmPlrStatus));
+
+ /* endless reconnect loop */
+ for(; !player->app->f_exit;)
+ {
+ /* connect */
pthread_mutex_lock(&player->app->players.lock);
-// st_curr.size = sizeof(OmPlrStatus);
-// r = OmPlrGetPlayerStatus((OmPlrHandle)player->handle, &st_curr);
- pthread_mutex_unlock(&player->app->players.lock);
+ if(mvcp_connect(handle->conn) == mvcp_ok)
+ {
+ g_warning("player_thread_proc: failed to connect to server\n");
+ sleep(1);
+ continue;
+ };
- if(r)
- g_warning("ERROR: OmPlrGetPlayerStatus failed with 0x%.8X\n", r);
- else
+ /* status request loop */
+ for(r = 0, f = 0; !player->app->f_exit && !r;)
{
-// omnplay_update_status(player, &st_prev , &st_curr, &playlist_start_prev);
-// playlist_start_prev = player->playlist_start;
-// memcmp(&st_curr, &st_prev, sizeof(OmPlrStatus));
+ /* wait for any event from notifier */
+ mvcp_notifier_wait(notifier, &status_curr);
+
+ /* get status for our unit */
+ if(player->unit != status_curr.unit)
+ mvcp_notifier_get(notifier, &status_curr, player->unit);
+
+ /* notify about exit from loop and reconnect */
+ if(status_curr.status == unit_disconnected)
+ r = 1;
+
+ /* do we need to update status */
+ if(!memcmp(&status_curr, &status_prev, sizeof(mvcp_status_t)) || !f)
+ {
+ };
+
+ f = 1;
+ player_update_status(player, &status_prev , &status_curr, &playlist_start_prev);
+ playlist_start_prev = player->playlist_start;
+ status_prev = status_curr;
};
};
void player_run(instance_t* app, int idx)
{
- mvcp_parser parser = mvcp_parser_init_remote(app->players.host, 5250);
- mvcp command = mvcp_init(parser);
-
+ player_handle_t* handle = malloc(sizeof(player_handle_t));
+ handle->parser = mvcp_parser_init_remote(app->players.host, 5250);
+ handle->conn = mvcp_init(handle->parser);
+ app->players.item[idx].handle = handle;
app->players.item[idx].thread = g_thread_create(
player_thread_proc, &app->players.item[idx], TRUE, NULL);
};
void player_stop(instance_t* app, int idx)
{
+ player_handle_t* handle = app->players.item[idx].handle;
g_thread_join(app->players.item[idx].thread);
+ mvcp_close(handle->conn);
+ mvcp_parser_close(handle->parser);
+ free(handle);
};
+/*
+ * playlist.h -- GTK+ 2 melted gui
+ * Copyright (C) 2012 Maksym Veremeyenko <verem@m1stereo.tv>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef PLAYLIST_H
+#define PLAYLIST_H
+
+#include "instance.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+/*
+ find local playlist index by given start search position value and remote playlist item index
+ used to associate remote item with local
+ */
+int playlist_item_index(instance_t* app, int start, int idx);
+
+#if 0
void omnplay_playlist_load(omnplay_instance_t* app);
void omnplay_playlist_save(omnplay_instance_t* app);
void omnplay_playlist_relink(omnplay_instance_t* app);
void omnplay_playlist_draw(omnplay_instance_t* app);
void omnplay_playlist_draw_item(omnplay_instance_t* app, int idx);
void omnplay_playlist_draw_item_rem(omnplay_instance_t* app, int idx, char* rem);
+#endif
+
+#ifdef __cplusplus
+};
+#endif /* __cplusplus */
+
+#endif /* PLAYLIST_H */
return r;
};
+
+/********************************************************************************/
+
+void ui_update_player(player_t* player, char *tc_cur, char *tc_rem, char *state, char *status, char *clip)
+{
+ /* update status in status page */
+ gdk_threads_enter();
+ gtk_label_set_text(GTK_LABEL (player->label_tc_cur), tc_cur);
+ gtk_label_set_text(GTK_LABEL (player->label_tc_rem), tc_rem);
+ gtk_label_set_text(GTK_LABEL (player->label_state), state);
+ gtk_label_set_text(GTK_LABEL (player->label_status), status);
+ gtk_label_set_text(GTK_LABEL (player->label_clip), clip);
+ gdk_flush();
+ gdk_threads_leave();
+};
+
+static gboolean ui_playlist_draw_item_rem_proc(
+ GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer user_data)
+{
+ int i;
+ void** args = (void**)user_data;
+ GtkListStore *list_store = (GtkListStore *)args[1];
+ int idx = (int)args[2];
+ char* rem = (char*)args[3];
+
+ gtk_tree_model_get(model, iter, 7, &i, -1);
+
+ if(i != idx) return FALSE;
+
+ gtk_list_store_set(list_store, iter, 0, rem, -1);
+
+ return TRUE;
+};
+
+void ui_playlist_draw_item_rem(instance_t* app, int idx, char* rem)
+{
+ void* item[4];
+ GtkListStore *list_store;
+
+ gdk_threads_enter();
+
+ list_store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(app->playlist_grid)));
+
+ item[0] = (void*)app;
+ item[1] = (void*)list_store;
+ item[2] = (void*)idx;
+ item[3] = (void*)rem;
+
+ gtk_tree_model_foreach(GTK_TREE_MODEL(list_store), ui_playlist_draw_item_rem_proc, item);
+
+ gdk_flush();
+ gdk_threads_leave();
+};