X-Git-Url: http://research.m1stereo.tv/gitweb?a=blobdiff_plain;f=src%2Fomnplay.cpp;h=c58a33fe966233d57b3250566783bc2b35fddd1b;hb=e5a5bba4049ac4793748e51921dce8b5c483855b;hp=5b3a77f59a21d9e314d6abd2caac9167597b7ec8;hpb=a8ef50e8b95436c3831b094ee3e731e12dd7c108;p=omnplay diff --git a/src/omnplay.cpp b/src/omnplay.cpp index 5b3a77f..c58a33f 100644 --- a/src/omnplay.cpp +++ b/src/omnplay.cpp @@ -17,6 +17,10 @@ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + #ifdef HAVE_CONFIG_H # include #endif @@ -31,32 +35,10 @@ #include "omnplay.h" #include "ui.h" #include "opts.h" +#include "timecode.h" #include "omplrclnt.h" -static char* frames2tc( int f, float fps, char* buf ) -{ - int tc[4] = { 0, 0, 0, 0 }; - float d; - int t; - - if ( fps && f >= 0) - { - d = f / fps; - t = d; - - tc[0] = (d - t) * fps; - tc[1] = t % 60; t /= 60; - tc[2] = t % 60; t /= 60; - tc[3] = t % 24; - } - - sprintf(buf, "%.2d:%.2d:%.2d:%.2d", tc[3], tc[2], tc[1], tc[0]); - - return buf; -} - - static gboolean on_main_window_delete_event( GtkWidget *widget, GdkEvent *event, gpointer user_data ) { gtk_exit(0); @@ -135,9 +117,9 @@ static void* omnplay_thread_proc(void* data) omnplay_player_t* player = (omnplay_player_t*)data; /* connect */ - pthread_mutex_lock(&player->lock); + pthread_mutex_lock(&player->app->players.lock); r = OmPlrOpen(player->host, player->name, (OmPlrHandle*)&player->handle); - pthread_mutex_unlock(&player->lock); + pthread_mutex_unlock(&player->app->players.lock); if(r) { fprintf(stderr, "ERROR: OmPlrOpen(%s, %s) failed with 0x%.8X\n", @@ -147,25 +129,25 @@ static void* omnplay_thread_proc(void* data) }; /* setup to do not reconnect */ - pthread_mutex_lock(&player->lock); + pthread_mutex_lock(&player->app->players.lock); OmPlrSetRetryOpen((OmPlrHandle)player->handle, 0); - pthread_mutex_unlock(&player->lock); + pthread_mutex_unlock(&player->app->players.lock); /* setup directory */ if(player->app->players.path[0]) { - pthread_mutex_lock(&player->lock); -// r = OmPlrClipSetDirectory((OmPlrHandle)player->handle, player->app->players.path); - pthread_mutex_unlock(&player->lock); + pthread_mutex_lock(&player->app->players.lock); + r = OmPlrClipSetDirectory((OmPlrHandle)player->handle, player->app->players.path); + pthread_mutex_unlock(&player->app->players.lock); if(r) { fprintf(stderr, "ERROR: OmPlrClipSetDirectory(%s) failed with 0x%.8X\n", player->app->players.path, r); - pthread_mutex_lock(&player->lock); + pthread_mutex_lock(&player->app->players.lock); OmPlrClose((OmPlrHandle)player->handle); - pthread_mutex_unlock(&player->lock); + pthread_mutex_unlock(&player->app->players.lock); return (void*)r; }; @@ -178,10 +160,10 @@ static void* omnplay_thread_proc(void* data) usleep(100000); /* get status */ - pthread_mutex_lock(&player->lock); + pthread_mutex_lock(&player->app->players.lock); st_curr.size = sizeof(OmPlrStatus); r = OmPlrGetPlayerStatus((OmPlrHandle)player->handle, &st_curr); - pthread_mutex_unlock(&player->lock); + pthread_mutex_unlock(&player->app->players.lock); if(r) fprintf(stderr, "ERROR: OmPlrGetPlayerStatus failed with 0x%.8X\n", r); @@ -190,29 +172,287 @@ static void* omnplay_thread_proc(void* data) omnplay_update_status(player, &st_prev , &st_curr); }; - pthread_mutex_lock(&player->lock); + pthread_mutex_lock(&player->app->players.lock); OmPlrClose((OmPlrHandle)player->handle); - pthread_mutex_unlock(&player->lock); + pthread_mutex_unlock(&player->app->players.lock); + + return NULL; +}; + +static int get_first_selected_item_playlist(omnplay_instance_t* app) +{ + int idx; + GtkTreeIter iter; + GtkTreeModel *model; + GtkTreeSelection *selection; + + selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(app->playlist_grid)); + if(selection && gtk_tree_selection_get_selected(selection, &model, &iter)) + { + gtk_tree_model_get(model, &iter, 7, &idx, -1); + return idx; + }; + return -1; +}; + +static int get_playlist_block(omnplay_instance_t* app, int idx, int* start_ptr, int* stop_ptr) +{ + int start, stop; + + for(start = idx; start >= 0; start--) + if(app->playlist.item[start].type & OMNPLAY_PLAYLIST_BLOCK_BEGIN) + break; + + for(stop = idx; stop < app->playlist.count; stop++) + if(app->playlist.item[stop].type & OMNPLAY_PLAYLIST_BLOCK_END) + break; + + fprintf(stderr, "get_playlist_block: range %d -> %d\n", start, stop); + + /* check block range */ + if(start >= 0 && stop < app->playlist.count) + { + *start_ptr = start; + *stop_ptr = stop; + return (stop - start + 1); + }; + + return -1; +}; + +static omnplay_player_t *get_player_at_pos(omnplay_instance_t* app, int pos) +{ + /* check player range */ + if(app->playlist.item[pos].player > -1 && app->playlist.item[pos].player < app->players.count) + return &app->players.item[app->playlist.item[pos].player]; return NULL; }; +static void omnplay_ctl(omnplay_instance_t* app, control_buttons_t button) +{ + int i, r; + int idx, start, stop; + omnplay_player_t *player; + + pthread_mutex_lock(&app->playlist.lock); + + idx = get_first_selected_item_playlist(app); + + if(idx < 0) + { + pthread_mutex_unlock(&app->playlist.lock); + return; + }; + + fprintf(stderr, "cue: selected item is %d\n", idx); + + if(get_playlist_block(app, idx, &start, &stop) < 0) + { + pthread_mutex_unlock(&app->playlist.lock); + return; + }; + + fprintf(stderr, "cue: range %d -> %d\n", start, stop); + + player = get_player_at_pos(app, start); + + if(!player) + { + pthread_mutex_unlock(&app->playlist.lock); + return; + }; + + pthread_mutex_lock(&app->players.lock); + + if(BUTTON_PLAYER_STOP == button || BUTTON_PLAYER_CUE == button) + { + /* stop */ + OmPlrStop((OmPlrHandle)player->handle); + + /* detach previous clips */ + player->playlist_start = -1; + player->playlist_count = -1; + OmPlrDetachAllClips((OmPlrHandle)player->handle); + }; + + if(BUTTON_PLAYER_CUE == button) + { + int o, c, p = 0; + + /* Attach clips to timeline */ + for(i = start, c = 0, o = 0; i <= stop; i++) + { + OmPlrClipInfo clip; + + /* get clip info */ + clip.maxMsTracks = 0; + clip.size = sizeof(clip); + r = OmPlrClipGetInfo((OmPlrHandle)player->handle, app->playlist.item[i].id, &clip); + + if(!r) + { + unsigned int l; + + fprintf(stderr, "OmPlrClipGetInfo(%s): firstFrame=%d, lastFrame=%d\n", + app->playlist.item[i].id, clip.firstFrame, clip.lastFrame); + + /* should we fix playlist clip timings */ + if(!( + app->playlist.item[i].in >= clip.firstFrame && + app->playlist.item[i].in + app->playlist.item[i].dur <= clip.lastFrame) || + !app->playlist.item[i].dur) + { + fprintf(stderr, "cue: item [%s] will be updated [%d;%d]->[%d;%d]\n", + app->playlist.item[i].id, + app->playlist.item[i].in, app->playlist.item[i].dur, + clip.firstFrame, clip.lastFrame - clip.firstFrame); + + app->playlist.item[i].in = clip.firstFrame; + app->playlist.item[i].dur = clip.lastFrame - clip.firstFrame; + omnplay_playlist_draw_item(app, i); + }; + + r = OmPlrAttach((OmPlrHandle)player->handle, + app->playlist.item[i].id, + app->playlist.item[i].in, + app->playlist.item[i].in + app->playlist.item[i].dur, + 0, omPlrShiftModeAfter, &l); + }; + + if(r) + { + fprintf(stderr, "cue: failed with %d, %s\n", r, OmPlrGetErrorString((OmPlrError)r)); + app->playlist.item[i].omn_idx = -1; + app->playlist.item[i].omn_offset = -1; + } + else + { + app->playlist.item[i].omn_idx = c; + app->playlist.item[i].omn_offset = o; + + /* save selected item offset */ + if(i == idx) p = o; + + c++; + o += app->playlist.item[i].dur; + }; + }; + + if(c) + { + OmPlrStatus hs; + + /* Set timeline min/max */ + OmPlrSetMinPosMin((OmPlrHandle)player->handle); + OmPlrSetMaxPosMax((OmPlrHandle)player->handle); + + /* Set timeline position */ + hs.minPos = 0; + hs.size = sizeof(OmPlrStatus); + OmPlrGetPlayerStatus((OmPlrHandle)player->handle, &hs); + OmPlrSetPos((OmPlrHandle)player->handle, hs.minPos + p); + + /* setup loop */ + if(app->playlist.item[start].type & OMNPLAY_PLAYLIST_BLOCK_LOOP) + OmPlrLoop((OmPlrHandle)player->handle, hs.minPos, hs.maxPos); + + /* Cue */ + OmPlrCuePlay((OmPlrHandle)player->handle, 0.0); + OmPlrPlay((OmPlrHandle)player->handle, 0.0); + + player->playlist_start = start; + player->playlist_count = stop - start + 1; + }; + }; + + if(BUTTON_PLAYER_PLAY == button) + { + /* play */ + OmPlrPlay((OmPlrHandle)player->handle, 1.0); + }; + + if(BUTTON_PLAYER_PAUSE == button) + /* pause */ + OmPlrPlay((OmPlrHandle)player->handle, 0.0); + + pthread_mutex_unlock(&app->players.lock); + + pthread_mutex_unlock(&app->playlist.lock); +}; + +static gboolean omnplay_button_click(omnplay_instance_t* app, control_buttons_t button) +{ + switch(button) + { + case BUTTON_PLAYLIST_ITEM_ADD: + case BUTTON_PLAYLIST_ITEM_DEL: + case BUTTON_PLAYLIST_ITEM_EDIT: + break; + case BUTTON_PLAYLIST_LOAD: + omnplay_playlist_load(app); + break; + case BUTTON_PLAYLIST_SAVE: + omnplay_playlist_save(app); + break; + case BUTTON_PLAYLIST_BLOCK_SINGLE: + case BUTTON_PLAYLIST_BLOCK_LOOP: + break; + case BUTTON_PLAYLIST_ITEM_UP: + case BUTTON_PLAYLIST_ITEM_DOWN: + break; + case BUTTON_PLAYER_CUE: + case BUTTON_PLAYER_PLAY: + case BUTTON_PLAYER_PAUSE: + case BUTTON_PLAYER_STOP: + omnplay_ctl(app, button); + break; + case BUTTON_LIBRARY_ADD: + case BUTTON_LIBRARY_REFRESH: + break; + }; + + return TRUE; +}; + +static gboolean on_button_click(GtkWidget *button, gpointer user_data) +{ + int i; + omnplay_instance_t* app = (omnplay_instance_t*)user_data; + + for(i = 1; i < BUTTON_LAST; i++) + if(app->buttons[i] == button) + return omnplay_button_click(app, (control_buttons_t)i); + + return FALSE; +}; + void omnplay_init(omnplay_instance_t* app) { int i; + pthread_mutexattr_t attr; + + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); gtk_signal_connect( GTK_OBJECT( app->window ), "destroy", GTK_SIGNAL_FUNC(on_main_window_delete_event), app); - for(i = 0; i < app->players.count; i++) - { - /* create lock */ - pthread_mutex_init(&app->players.item[i].lock, NULL); + /* create lock */ + pthread_mutex_init(&app->players.lock, &attr); - /* create a omneon status thread */ + /* create a omneon status thread */ + for(i = 0; i < app->players.count; i++) pthread_create(&app->players.item[i].thread, NULL, omnplay_thread_proc, &app->players.item[i]); - }; + + /* create lock */ + pthread_mutex_init(&app->playlist.lock, &attr); + + /* attach buttons click */ + for(i = 1; i < BUTTON_LAST; i++) + gtk_signal_connect(GTK_OBJECT(app->buttons[i]), "clicked", + GTK_SIGNAL_FUNC( on_button_click), app ); + }; void omnplay_release(omnplay_instance_t* app) @@ -223,12 +463,12 @@ void omnplay_release(omnplay_instance_t* app) app->f_exit = 1; for(i = 0; i < app->players.count; i++) - { /* create a omneon status thread */ pthread_join(app->players.item[i].thread, &r); - /* create lock */ - pthread_mutex_destroy(&app->players.item[i].lock); + /* destroy lock */ + pthread_mutex_destroy(&app->players.lock); - }; + /* destroy lock */ + pthread_mutex_destroy(&app->playlist.lock); };