2 * player.h -- GTK+ 2 melted gui
3 * Copyright (C) 2012 Maksym Veremeyenko <verem@m1stereo.tv>
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.
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.
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.
32 #include <gdk/gdkkeysyms.h>
35 #include <mvcp/mvcp.h>
36 #include <mvcp/mvcp_remote.h>
38 #if defined(__MINGW32__)
47 static char* status_to_text(mvcp_status status
)
49 switch(status
->status
)
51 case unit_offline
: return "offline"; break;
52 case unit_undefined
: return "undefined"; break;
53 case unit_not_loaded
: return "unloaded"; break;
54 case unit_stopped
: return "stopped"; break;
55 case unit_playing
: return "playing"; break;
56 case unit_paused
: return "paused"; break;
57 case unit_disconnected
: return "disconnect"; break;
58 case unit_unknown
: return "unknown"; break;
63 typedef struct player_handle_desc
70 static void player_update_status(player_t
* player
, mvcp_status_t
*status_prev
, mvcp_status_t
*status_curr
,
71 int *playlist_start_prev
)
74 char tc_cur
[32], tc_rem
[32], *state
, status
[32], *clip
;
76 if(status_curr
->status
== unit_disconnected
)
82 strcpy(status
, "OFFLINE");
86 int p
= status_curr
->start
+ (status_curr
->position
- status_curr
->in
);
88 frames2tc(p
, 25.0, tc_cur
);
89 frames2tc(status_curr
->dur
- p
, 25.0, tc_rem
);
90 clip
= strrchr(status_curr
->clip
, '/');
94 clip
= status_curr
->clip
;
95 state
= status_to_text(status_curr
);
96 strcpy(status
, "ONLINE");
99 ui_update_player(player
, tc_cur
, tc_rem
, state
, status
, clip
);
101 /* update remaining time of playlist's item */
102 pthread_mutex_lock(&player
->app
->playlist
.lock
);
103 pthread_mutex_lock(&player
->app
->players
.lock
);
104 if(player
->playlist_length
)
106 /* clear remain on "previous" item */
107 if((status_curr
->clip_index
!= status_prev
->clip_index
&& 1 != player
->playlist_length
) ||
108 (*playlist_start_prev
!= player
->playlist_start
))
111 idx
= playlist_item_index
/* find_index_of_playlist_item */(player
->app
, *playlist_start_prev
, status_prev
->clip_index
);
113 ui_playlist_draw_item_rem(player
->app
, idx
, tc_rem
);
116 /* update current item */
117 idx
= playlist_item_index
/* find_index_of_playlist_item */(player
->app
, player
->playlist_start
, status_curr
->clip_index
);
123 /* for play and cue calc new value */
124 if(/*status_curr->status == unit_stopped || */ status_curr
->status
== unit_playing
|| status_curr
->status
== unit_paused
)
125 frames2tc(status_curr
->out
- status_curr
->position
, 25.0, tc_rem
);
127 /* setup that value */
128 ui_playlist_draw_item_rem(player
->app
, idx
, tc_rem
);
131 pthread_mutex_unlock(&player
->app
->players
.lock
);
132 pthread_mutex_unlock(&player
->app
->playlist
.lock
);
135 static void* player_thread_proc(void* data
)
138 int playlist_start_prev
= 0;
139 mvcp_status_t status_curr
, status_prev
;
140 player_t
* player
= (player_t
*)data
;
141 player_handle_t
* handle
= player
->handle
;
142 mvcp_notifier notifier
= mvcp_get_notifier(handle
->status
);
144 g_warning("player_thread_proc: started (player=%d, unit=%d)\n", player
->idx
, player
->unit
);
146 // memset(&st_curr, 0, sizeof(OmPlrStatus));
147 // memset(&st_prev, 0, sizeof(OmPlrStatus));
149 /* endless reconnect loop */
150 for(; !player
->app
->f_exit
;)
152 r
= mvcp_connect(handle
->command
);
156 g_warning("player_thread_proc: failed to connect to server %s:%d (player=%d, unit=%d), r=%d\n",
157 player
->app
->players
.host
, player
->app
->players
.port
, player
->idx
, player
->unit
, r
);
158 #if defined(__MINGW32__)
166 g_warning("player_thread_proc: connected to server %s (player=%d, unit=%d)\n",
167 player
->app
->players
.host
, player
->idx
, player
->unit
);
169 /* status request loop */
170 for(r
= 0, f
= 0; !player
->app
->f_exit
&& !r
;)
174 /* wait for any event from notifier */
175 mvcp_notifier_wait(notifier
, &status_curr
);
177 /* get status for our unit */
178 if(player
->unit
!= status_curr
.unit
)
179 mvcp_notifier_get(notifier
, &status_curr
, player
->unit
);
181 /* notify about exit from loop and reconnect */
182 if(status_curr
.status
== unit_disconnected
)
188 /* do we need to update status */
189 c
= memcmp(&status_curr
, &status_prev
, sizeof(mvcp_status_t
));
193 /* call update func */
194 player_update_status(player
, &status_prev
, &status_curr
, &playlist_start_prev
);
195 playlist_start_prev
= player
->playlist_start
;
196 status_prev
= status_curr
;
201 pthread_mutex_lock(&player
->app
->players
.lock
);
202 // OmPlrClose((OmPlrHandle)player->handle);
203 pthread_mutex_unlock(&player
->app
->players
.lock
);
209 void player_run(instance_t
* app
, int idx
)
211 player_handle_t
* handle
= malloc(sizeof(player_handle_t
));
212 handle
->parser
= mvcp_parser_init_remote(app
->players
.host
, app
->players
.port
);
213 handle
->status
= mvcp_init(handle
->parser
);
214 handle
->command
= mvcp_init(handle
->parser
);
215 app
->players
.item
[idx
].handle
= handle
;
216 app
->players
.item
[idx
].thread
= g_thread_create(
217 player_thread_proc
, &app
->players
.item
[idx
], TRUE
, NULL
);
220 void player_stop(instance_t
* app
, int idx
)
222 player_handle_t
* handle
= app
->players
.item
[idx
].handle
;
223 g_thread_join(app
->players
.item
[idx
].thread
);
224 mvcp_close(handle
->status
);
225 mvcp_close(handle
->command
);
226 mvcp_parser_close(handle
->parser
);