5b3a77f59a21d9e314d6abd2caac9167597b7ec8
[melted_gui] / src / omnplay.cpp
1 /*
2 * omnplay.c -- GTK+ 2 omnplay
3 * Copyright (C) 2011 Maksym Veremeyenko <verem@m1stereo.tv>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software Foundation,
17 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19
20 #ifdef HAVE_CONFIG_H
21 # include <config.h>
22 #endif
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <gtk/gtk.h>
28 #include <gdk/gdkkeysyms.h>
29 #include <pthread.h>
30
31 #include "omnplay.h"
32 #include "ui.h"
33 #include "opts.h"
34
35 #include "omplrclnt.h"
36
37 static char* frames2tc( int f, float fps, char* buf )
38 {
39 int tc[4] = { 0, 0, 0, 0 };
40 float d;
41 int t;
42
43 if ( fps && f >= 0)
44 {
45 d = f / fps;
46 t = d;
47
48 tc[0] = (d - t) * fps;
49 tc[1] = t % 60; t /= 60;
50 tc[2] = t % 60; t /= 60;
51 tc[3] = t % 24;
52 }
53
54 sprintf(buf, "%.2d:%.2d:%.2d:%.2d", tc[3], tc[2], tc[1], tc[0]);
55
56 return buf;
57 }
58
59
60 static gboolean on_main_window_delete_event( GtkWidget *widget, GdkEvent *event, gpointer user_data )
61 {
62 gtk_exit(0);
63 return TRUE;
64 }
65
66 omnplay_instance_t* omnplay_create(int argc, char** argv)
67 {
68 int i, c;
69 omnplay_instance_t* app;
70
71 /* prepare application instance */
72 app = (omnplay_instance_t*)malloc(sizeof(omnplay_instance_t));
73 memset(app, 0, sizeof(omnplay_instance_t));
74
75 /* load parameters from command line */
76 if(!omnplay_opt(argc, argv, app) && app->players.count)
77 app->window = ui_omnplay(app);
78 else
79 omnplay_usage();
80
81 return app;
82 };
83
84 void omnplay_destroy(omnplay_instance_t* app)
85 {
86 free(app);
87 };
88
89 static void omnplay_update_status(omnplay_player_t* player, OmPlrStatus *prev , OmPlrStatus *curr)
90 {
91 char tc_cur[32], tc_rem[32], state[32], status[32];
92 const char *clip;
93
94 if(curr)
95 {
96 frames2tc(curr->pos - curr->minPos, 25.0, tc_cur);
97 frames2tc(curr->maxPos - curr->pos, 25.0, tc_rem);
98 strcpy(status, "ONLINE");
99 clip = curr->currClipName;
100
101 switch(curr->state)
102 {
103 case omPlrStateStopped: strcpy(state, "STOPPED"); break;
104 case omPlrStateCuePlay: strcpy(state, "CUE_PLAY"); break;
105 case omPlrStatePlay: strcpy(state, "PLAY"); break;
106 case omPlrStateCueRecord: strcpy(state, "CUE_RECORD"); break;
107 case omPlrStateRecord: strcpy(state, "RECORD"); break;
108 };
109 }
110 else
111 {
112 tc_cur[0] = 0;
113 tc_rem[0] = 0;
114 clip = "";
115 state[0] = 0;
116 strcpy(status, "OFFLINE");
117 };
118
119 gdk_threads_enter();
120 gtk_label_set_text(GTK_LABEL (player->label_tc_cur), tc_cur);
121 gtk_label_set_text(GTK_LABEL (player->label_tc_rem), tc_rem);
122 gtk_label_set_text(GTK_LABEL (player->label_state), state);
123 gtk_label_set_text(GTK_LABEL (player->label_status), status);
124 gtk_label_set_text(GTK_LABEL (player->label_clip), clip);
125 gdk_flush();
126 gdk_threads_leave();
127
128 memcpy(prev, curr, sizeof(OmPlrStatus));
129 };
130
131 static void* omnplay_thread_proc(void* data)
132 {
133 int r;
134 OmPlrStatus st_curr, st_prev;
135 omnplay_player_t* player = (omnplay_player_t*)data;
136
137 /* connect */
138 pthread_mutex_lock(&player->lock);
139 r = OmPlrOpen(player->host, player->name, (OmPlrHandle*)&player->handle);
140 pthread_mutex_unlock(&player->lock);
141 if(r)
142 {
143 fprintf(stderr, "ERROR: OmPlrOpen(%s, %s) failed with 0x%.8X\n",
144 player->host, player->name, r);
145
146 return (void*)r;
147 };
148
149 /* setup to do not reconnect */
150 pthread_mutex_lock(&player->lock);
151 OmPlrSetRetryOpen((OmPlrHandle)player->handle, 0);
152 pthread_mutex_unlock(&player->lock);
153
154 /* setup directory */
155 if(player->app->players.path[0])
156 {
157 pthread_mutex_lock(&player->lock);
158 // r = OmPlrClipSetDirectory((OmPlrHandle)player->handle, player->app->players.path);
159 pthread_mutex_unlock(&player->lock);
160
161 if(r)
162 {
163 fprintf(stderr, "ERROR: OmPlrClipSetDirectory(%s) failed with 0x%.8X\n",
164 player->app->players.path, r);
165
166 pthread_mutex_lock(&player->lock);
167 OmPlrClose((OmPlrHandle)player->handle);
168 pthread_mutex_unlock(&player->lock);
169
170 return (void*)r;
171 };
172 };
173
174 /* endless loop */
175 for(r = 0 ; !player->app->f_exit && !r;)
176 {
177 /* sleep */
178 usleep(100000);
179
180 /* get status */
181 pthread_mutex_lock(&player->lock);
182 st_curr.size = sizeof(OmPlrStatus);
183 r = OmPlrGetPlayerStatus((OmPlrHandle)player->handle, &st_curr);
184 pthread_mutex_unlock(&player->lock);
185
186 if(r)
187 fprintf(stderr, "ERROR: OmPlrGetPlayerStatus failed with 0x%.8X\n", r);
188 else
189 if(memcmp(&st_curr, &st_prev, sizeof(OmPlrStatus)))
190 omnplay_update_status(player, &st_prev , &st_curr);
191 };
192
193 pthread_mutex_lock(&player->lock);
194 OmPlrClose((OmPlrHandle)player->handle);
195 pthread_mutex_unlock(&player->lock);
196
197 return NULL;
198 };
199
200 void omnplay_init(omnplay_instance_t* app)
201 {
202 int i;
203
204 gtk_signal_connect( GTK_OBJECT( app->window ), "destroy",
205 GTK_SIGNAL_FUNC(on_main_window_delete_event), app);
206
207 for(i = 0; i < app->players.count; i++)
208 {
209 /* create lock */
210 pthread_mutex_init(&app->players.item[i].lock, NULL);
211
212 /* create a omneon status thread */
213 pthread_create(&app->players.item[i].thread, NULL,
214 omnplay_thread_proc, &app->players.item[i]);
215 };
216 };
217
218 void omnplay_release(omnplay_instance_t* app)
219 {
220 int i;
221 void* r;
222
223 app->f_exit = 1;
224
225 for(i = 0; i < app->players.count; i++)
226 {
227 /* create a omneon status thread */
228 pthread_join(app->players.item[i].thread, &r);
229
230 /* create lock */
231 pthread_mutex_destroy(&app->players.item[i].lock);
232
233 };
234 };