00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include <stdlib.h>
00031 #include <string.h>
00032
00033 #include <vlc/vlc.h>
00034
00035 #ifdef HAVE_UNISTD_H
00036 # include <unistd.h>
00037 #endif
00038
00039 #include <vlc/decoder.h>
00040 #include <vlc/input.h>
00041 #include <vlc/intf.h>
00042 #include <vlc/vout.h>
00043
00044 #include <vlc_osd.h>
00045
00046 #include "vlc_keys.h"
00047
00048 #include "browser_open.h"
00049 #include "history.h"
00050 #include "xstrcat.h"
00051 #include "xurl.h"
00052
00053 #undef CMML_INTF_USE_TIMED_URIS
00054
00055 #undef CMML_INTF_DEBUG
00056 #undef CMML_INTF_HISTORY_DEBUG
00057
00058
00059
00060
00061 struct intf_sys_t
00062 {
00063 decoder_t * p_cmml_decoder;
00064 input_thread_t * p_input;
00065
00066 vlc_bool_t b_key_pressed;
00067 };
00068
00069 struct navigation_history_t
00070 {
00071 int i_history_size;
00072 int i_last_item;
00073 };
00074
00075
00076
00077
00078 static int InitThread ( intf_thread_t * );
00079 static int MouseEvent ( vlc_object_t *, char const *,
00080 vlc_value_t, vlc_value_t, void * );
00081 static int KeyEvent ( vlc_object_t *, char const *,
00082 vlc_value_t, vlc_value_t, void * );
00083
00084 static void FollowAnchor ( intf_thread_t * );
00085 static void GoBack ( intf_thread_t * );
00086 static void GoForward ( intf_thread_t * );
00087
00088 static int FollowAnchorCallback ( vlc_object_t *, char const *,
00089 vlc_value_t, vlc_value_t, void * );
00090 static int GoBackCallback ( vlc_object_t *, char const *,
00091 vlc_value_t, vlc_value_t, void * );
00092 static int GoForwardCallback ( vlc_object_t *, char const *,
00093 vlc_value_t, vlc_value_t, void * );
00094
00095 static char *GetTimedURLFromPlaylistItem( intf_thread_t *, playlist_item_t * );
00096 static char *GetTimedURIFragmentForTime ( int );
00097 static int GetCurrentTimeInSeconds ( input_thread_t * );
00098 static int DisplayAnchor ( intf_thread_t *, vout_thread_t *,
00099 char *, char * );
00100 static int DisplayPendingAnchor ( intf_thread_t *, vout_thread_t * );
00101 static history_t * GetHistory ( playlist_t * );
00102 static void ReplacePlaylistItem ( playlist_t *, char * );
00103
00104
00105 static void RunIntf ( intf_thread_t *p_intf );
00106
00107
00108
00109
00110 int E_(OpenIntf) ( vlc_object_t *p_this )
00111 {
00112 intf_thread_t *p_intf = (intf_thread_t *)p_this;
00113
00114 p_intf->p_sys = malloc( sizeof( intf_sys_t ) );
00115 if( p_intf->p_sys == NULL )
00116 {
00117 return( 1 );
00118 };
00119
00120 p_intf->pf_run = RunIntf;
00121
00122 var_AddCallback( p_intf->p_vlc, "key-pressed", KeyEvent, p_intf );
00123
00124
00125
00126 var_Create( p_intf->p_vlc, "browse-go-back", VLC_VAR_VOID );
00127 var_AddCallback( p_intf->p_vlc, "browse-go-back",
00128 GoBackCallback, p_intf );
00129 var_Create( p_intf->p_vlc, "browse-go-forward", VLC_VAR_VOID );
00130 var_AddCallback( p_intf->p_vlc, "browse-go-forward",
00131 GoForwardCallback, p_intf );
00132 var_Create( p_intf->p_vlc, "browse-follow-anchor", VLC_VAR_VOID );
00133 var_AddCallback( p_intf->p_vlc, "browse-follow-anchor",
00134 FollowAnchorCallback, p_intf );
00135
00136 return( 0 );
00137 }
00138
00139
00140
00141
00142 void E_(CloseIntf) ( vlc_object_t *p_this )
00143 {
00144 intf_thread_t * p_intf = (intf_thread_t *)p_this;
00145 vout_thread_t * p_vout;
00146
00147 #ifdef CMML_INTF_DEBUG
00148 msg_Dbg( p_intf, "freeing CMML interface" );
00149 #endif
00150
00151
00152 p_vout = vlc_object_find( p_intf, VLC_OBJECT_VOUT, FIND_ANYWHERE );
00153 if( p_vout )
00154 {
00155
00156 spu_Control( p_vout->p_spu, SPU_CHANNEL_CLEAR, DEFAULT_CHAN );
00157 vlc_object_release( p_vout );
00158 }
00159
00160 var_DelCallback( p_intf->p_vlc, "key-pressed", KeyEvent, p_intf );
00161
00162 vlc_object_release( p_intf->p_sys->p_cmml_decoder );
00163
00164 free( p_intf->p_sys );
00165 }
00166
00167
00168
00169
00170
00171 static void RunIntf( intf_thread_t *p_intf )
00172 {
00173 vout_thread_t * p_vout = NULL;
00174
00175 if( InitThread( p_intf ) < 0 )
00176 {
00177 msg_Err( p_intf, "can't initialize CMML interface" );
00178 return;
00179 }
00180 #ifdef CMML_INTF_DEBUG
00181 msg_Dbg( p_intf, "CMML intf initialized" );
00182 #endif
00183
00184
00185 if( p_vout && p_vout->b_die )
00186 {
00187 var_DelCallback( p_vout, "mouse-clicked", MouseEvent, p_intf );
00188 vlc_object_release( p_vout );
00189 p_vout = NULL;
00190 }
00191
00192
00193 while( !p_intf->b_die )
00194 {
00195
00196
00197 if( p_vout == NULL )
00198 {
00199 p_vout = vlc_object_find( p_intf->p_sys->p_input,
00200 VLC_OBJECT_VOUT, FIND_CHILD );
00201 if( p_vout )
00202 {
00203 #ifdef CMML_INTF_DEBUG
00204 msg_Dbg( p_intf, "found vout thread" );
00205 #endif
00206 var_AddCallback( p_vout, "mouse-clicked", MouseEvent, p_intf );
00207 }
00208 }
00209
00210 vlc_mutex_lock( &p_intf->change_lock );
00211
00212
00213
00214
00215 if( p_intf->p_sys->b_key_pressed )
00216 {
00217 vlc_value_t val;
00218 int i, i_action = -1;
00219 struct hotkey *p_hotkeys = p_intf->p_vlc->p_hotkeys;
00220
00221
00222 var_Get( p_intf->p_vlc, "key-pressed", &val );
00223
00224
00225 p_intf->p_sys->b_key_pressed = VLC_FALSE;
00226
00227 #ifdef CMML_INTF_DEBUG
00228 msg_Dbg( p_intf, "Got a keypress: %d", val.i_int );
00229 #endif
00230
00231 for( i = 0; p_hotkeys[i].psz_action != NULL; i++ )
00232 {
00233 if( p_hotkeys[i].i_key == val.i_int )
00234 i_action = p_hotkeys[i].i_action;
00235 }
00236
00237
00238 if( i_action != -1 )
00239 {
00240 switch( i_action )
00241 {
00242 case ACTIONID_NAV_ACTIVATE:
00243 FollowAnchor( p_intf );
00244 break;
00245 case ACTIONID_HISTORY_BACK:
00246 GoBack( p_intf );
00247 break;
00248 case ACTIONID_HISTORY_FORWARD:
00249 GoForward( p_intf );
00250 break;
00251 default:
00252 break;
00253 }
00254 }
00255 }
00256
00257 vlc_mutex_unlock( &p_intf->change_lock );
00258
00259 (void) DisplayPendingAnchor( p_intf, p_vout );
00260
00261
00262 msleep( INTF_IDLE_SLEEP );
00263 }
00264
00265
00266
00267 if( p_vout )
00268 {
00269 var_DelCallback( p_vout, "mouse-clicked", MouseEvent, p_intf );
00270 vlc_object_release( p_vout );
00271 }
00272
00273 vlc_object_release( p_intf->p_sys->p_input );
00274 }
00275
00276
00277
00278
00279
00280 static int DisplayPendingAnchor( intf_thread_t *p_intf, vout_thread_t *p_vout )
00281 {
00282 decoder_t *p_cmml_decoder;
00283 char *psz_description = NULL;
00284 char *psz_url = NULL;
00285
00286 intf_thread_t *p_primary_intf;
00287 vlc_value_t val;
00288
00289 p_cmml_decoder = p_intf->p_sys->p_cmml_decoder;
00290 if( var_Get( p_cmml_decoder, "psz-current-anchor-description", &val )
00291 != VLC_SUCCESS )
00292 {
00293 return VLC_TRUE;
00294 }
00295
00296 if( !val.p_address )
00297 return VLC_TRUE;
00298
00299 psz_description = val.p_address;
00300
00301 if( var_Get( p_cmml_decoder, "psz-current-anchor-url", &val )
00302 == VLC_SUCCESS )
00303 {
00304 psz_url = val.p_address;
00305 }
00306
00307 if( p_vout != NULL )
00308 {
00309
00310 p_primary_intf = vlc_object_find( p_intf->p_vlc, VLC_OBJECT_INTF,
00311 FIND_CHILD );
00312
00313 if( p_primary_intf )
00314 {
00315 if( var_Get( p_primary_intf, "intf-displays-cmml-description", &val )
00316 == VLC_SUCCESS )
00317 {
00318 if( val.b_bool == VLC_TRUE )
00319 {
00320 vlc_object_release( p_primary_intf );
00321 return VLC_TRUE;
00322 }
00323 }
00324
00325 vlc_object_release( p_primary_intf );
00326 }
00327
00328
00329 if( DisplayAnchor( p_intf, p_vout, psz_description, psz_url )
00330 != VLC_SUCCESS )
00331 {
00332
00333 return VLC_FALSE;
00334 }
00335
00336
00337 val.p_address = NULL;
00338 if( var_Set( p_cmml_decoder, "psz-current-anchor-description", val )
00339 != VLC_SUCCESS )
00340 {
00341 msg_Dbg( p_intf,
00342 "reset of psz-current-anchor-description failed" );
00343 }
00344 free( psz_description );
00345 psz_url = NULL;
00346 }
00347
00348 return VLC_TRUE;
00349 }
00350
00351
00352
00353
00354
00355 static int InitThread( intf_thread_t * p_intf )
00356 {
00357
00358 if( !p_intf->b_die )
00359 {
00360 input_thread_t * p_input;
00361 decoder_t *p_cmml_decoder;
00362
00363 p_cmml_decoder = vlc_object_find( p_intf, VLC_OBJECT_DECODER, FIND_PARENT );
00364 p_input = vlc_object_find( p_intf, VLC_OBJECT_INPUT, FIND_PARENT );
00365
00366 #ifdef CMML_INTF_DEBUG
00367 msg_Dbg( p_intf, "cmml decoder at %p, input thread at %p",
00368 p_cmml_decoder, p_input );
00369 #endif
00370
00371
00372 if( p_input == NULL )
00373 {
00374 return VLC_EGENERIC;
00375 }
00376
00377 vlc_mutex_lock( &p_intf->change_lock );
00378
00379 p_intf->p_sys->p_input = p_input;
00380 p_intf->p_sys->p_cmml_decoder = p_cmml_decoder;
00381
00382 p_intf->p_sys->b_key_pressed = VLC_FALSE;
00383
00384 vlc_mutex_unlock( &p_intf->change_lock );
00385
00386 return VLC_SUCCESS;
00387 }
00388 else
00389 {
00390 return VLC_EGENERIC;
00391 }
00392 }
00393
00394
00395
00396
00397 static int MouseEvent( vlc_object_t *p_this, char const *psz_var,
00398 vlc_value_t oldval, vlc_value_t newval, void *p_data )
00399 {
00400
00401
00402 return VLC_SUCCESS;
00403 }
00404
00405
00406
00407
00408 static int KeyEvent( vlc_object_t *p_this, char const *psz_var,
00409 vlc_value_t oldval, vlc_value_t newval, void *p_data )
00410 {
00411 intf_thread_t *p_intf = (intf_thread_t *)p_data;
00412 vlc_mutex_lock( &p_intf->change_lock );
00413
00414 p_intf->p_sys->b_key_pressed = VLC_TRUE;
00415
00416 vlc_mutex_unlock( &p_intf->change_lock );
00417
00418 return VLC_SUCCESS;
00419 }
00420
00421
00422
00423
00424 static void FollowAnchor ( intf_thread_t *p_intf )
00425 {
00426 intf_sys_t *p_sys;
00427 decoder_t *p_cmml_decoder;
00428 char *psz_url = NULL;
00429 vlc_value_t val;
00430
00431 msg_Dbg( p_intf, "User followed anchor" );
00432
00433 p_sys = p_intf->p_sys;
00434 p_cmml_decoder = p_sys->p_cmml_decoder;
00435
00436 if( var_Get( p_cmml_decoder, "psz-current-anchor-url", &val ) ==
00437 VLC_SUCCESS )
00438 {
00439 if( val.p_address ) psz_url = val.p_address;
00440 }
00441
00442 #ifdef CMML_INTF_DEBUG
00443 msg_Dbg( p_intf, "Current URL is \"%s\"", psz_url );
00444 #endif
00445
00446 if( psz_url )
00447 {
00448 playlist_t *p_playlist;
00449 playlist_item_t *p_current_item;
00450 char *psz_uri_to_load;
00451 mtime_t i_seconds;
00452 vlc_value_t time;
00453
00454 p_playlist = (playlist_t *) vlc_object_find( p_intf,
00455 VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
00456 if ( !p_playlist )
00457 {
00458 msg_Warn( p_intf, "can't find playlist" );
00459 return;
00460 }
00461
00462
00463 p_current_item = p_playlist->pp_items[p_playlist->i_index];
00464 #ifdef CMML_INTF_DEBUG
00465 msg_Dbg( p_intf, "Current playlist item URL is \"%s\"",
00466 p_current_item->input.psz_uri );
00467 #endif
00468
00469 psz_uri_to_load = XURL_Concat( p_current_item->input.psz_uri,
00470 psz_url );
00471
00472 #ifdef CMML_INTF_DEBUG
00473 msg_Dbg( p_intf, "URL to load is \"%s\"", psz_uri_to_load );
00474 #endif
00475
00476 if( var_Get( p_intf->p_sys->p_input, "time", &time ) )
00477 {
00478 msg_Dbg( p_intf, "couldn't get time from current clip" );
00479 time.i_time = 0;
00480 }
00481 i_seconds = time.i_time / 1000000;
00482 #ifdef CMML_INTF_DEBUG
00483 msg_Dbg( p_intf, "Current time is \"%lld\"", i_seconds );
00484 #endif
00485
00486
00487
00488 if( strstr( psz_uri_to_load, ".anx" ) != NULL )
00489 {
00490 history_t *p_history = NULL;
00491 history_item_t *p_history_item = NULL;
00492 char *psz_timed_url;
00493
00494 p_history = GetHistory( p_playlist );
00495
00496
00497 psz_timed_url = GetTimedURLFromPlaylistItem( p_intf, p_current_item );
00498 p_history_item = historyItem_New( psz_timed_url, psz_timed_url );
00499 free( psz_timed_url );
00500
00501 if( !p_history_item )
00502 {
00503 msg_Warn( p_intf, "could not initialise history item" );
00504 }
00505 else
00506 {
00507 #ifdef CMML_INTF_DEBUG
00508 msg_Dbg( p_intf, "history pre-index %d", p_history->i_index );
00509 #endif
00510 history_PruneAndInsert( p_history, p_history_item );
00511 #ifdef CMML_INTF_DEBUG
00512 msg_Dbg( p_intf, "new history item at %p, uri is \"%s\"",
00513 p_history_item, p_history_item->psz_uri );
00514 msg_Dbg( p_intf, "history index now %d", p_history->i_index );
00515 #endif
00516 }
00517
00518
00519 free( psz_url );
00520 val.p_address = NULL;
00521 if( var_Set( p_cmml_decoder, "psz-current-anchor-url", val ) !=
00522 VLC_SUCCESS )
00523 {
00524 msg_Dbg( p_intf, "couldn't reset psz-current-anchor-url" );
00525 }
00526
00527 ReplacePlaylistItem( p_playlist, psz_uri_to_load );
00528 }
00529 else
00530 {
00531 #ifdef CMML_INTF_DEBUG
00532 msg_Dbg( p_intf, "calling browser_Open with \"%s\"", psz_url );
00533 #endif
00534 (void) browser_Open( psz_url );
00535 playlist_Control( p_playlist, PLAYLIST_PAUSE, 0 );
00536 }
00537
00538 free( psz_uri_to_load );
00539
00540 vlc_object_release( p_playlist );
00541 }
00542 }
00543
00544 static
00545 char *GetTimedURLFromPlaylistItem( intf_thread_t *p_intf,
00546 playlist_item_t *p_current_item )
00547 {
00548 #ifdef CMML_INTF_USE_TIMED_URIS
00549 char *psz_url = NULL;
00550 char *psz_return_value = NULL;
00551 char *psz_seconds = NULL;
00552 int i_seconds;
00553
00554 psz_url = XURL_GetWithoutFragment( p_current_item->input->psz_uri );
00555
00556
00557 if( XURL_IsFileURL( psz_url ) == VLC_TRUE )
00558 psz_url = xstrcat( psz_url, "#" );
00559 else
00560 psz_url = xstrcat( psz_url, "?" );
00561
00562
00563 i_seconds = GetCurrentTimeInSeconds( p_intf->p_sys->p_input ) - 2;
00564 psz_seconds = GetTimedURIFragmentForTime( i_seconds < 0 ? 0 : i_seconds );
00565 if( psz_seconds )
00566 {
00567 psz_url = xstrcat( psz_url, psz_seconds );
00568 free( psz_seconds );
00569 psz_return_value = psz_url;
00570 }
00571
00572 return psz_return_value;
00573 #else
00574 void *p;
00575
00576
00577 p = GetTimedURIFragmentForTime;
00578 p = GetCurrentTimeInSeconds;
00579
00580 return strdup( p_current_item->input.psz_uri );
00581 #endif
00582 }
00583
00584
00585
00586
00587
00588
00589
00590 static
00591 int GetCurrentTimeInSeconds( input_thread_t *p_input )
00592 {
00593 vlc_value_t time;
00594 mtime_t i_seconds;
00595
00596 var_Get( p_input, "time", &time );
00597 i_seconds = time.i_time / 1000000;
00598
00599 return i_seconds;
00600 }
00601
00602 static
00603 char *GetTimedURIFragmentForTime( int seconds )
00604 {
00605 char *psz_time;
00606
00607 asprintf( &psz_time, "%d", seconds );
00608
00609 return psz_time;
00610 }
00611
00612 static
00613 int GoBackCallback( vlc_object_t *p_this, char const *psz_var,
00614 vlc_value_t oldval, vlc_value_t newval, void *p_data )
00615 {
00616 intf_thread_t *p_intf = (intf_thread_t *) p_data;
00617 GoBack( p_intf );
00618 return VLC_SUCCESS;
00619 }
00620
00621 static
00622 int GoForwardCallback( vlc_object_t *p_this, char const *psz_var,
00623 vlc_value_t oldval, vlc_value_t newval, void *p_data )
00624 {
00625 intf_thread_t *p_intf = (intf_thread_t *) p_data;
00626 GoForward( p_intf );
00627 return VLC_SUCCESS;
00628 }
00629
00630 static
00631 int FollowAnchorCallback( vlc_object_t *p_this, char const *psz_var,
00632 vlc_value_t oldval, vlc_value_t newval,
00633 void *p_data )
00634 {
00635 intf_thread_t *p_intf = (intf_thread_t *) p_data;
00636 FollowAnchor( p_intf );
00637 return VLC_SUCCESS;
00638 }
00639
00640 static
00641 void GoBack( intf_thread_t *p_intf )
00642 {
00643 vlc_value_t history;
00644 history_t *p_history = NULL;
00645 history_item_t *p_history_item = NULL;
00646 history_item_t *p_new_history_item = NULL;
00647 playlist_t *p_playlist = NULL;
00648 char *psz_timed_url = NULL;
00649 playlist_item_t *p_current_item;
00650
00651 #ifdef CMML_INTF_DEBUG
00652 msg_Dbg( p_intf, "Going back in navigation history" );
00653 #endif
00654
00655
00656 p_playlist = (playlist_t *) vlc_object_find( p_intf,
00657 VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
00658 if ( !p_playlist )
00659 {
00660 msg_Warn( p_intf, "can't find playlist" );
00661 return;
00662 }
00663
00664
00665 if( var_Get( p_playlist, "navigation-history", &history ) != VLC_SUCCESS ||
00666 !history.p_address )
00667 {
00668
00669 msg_Warn( p_intf, "can't go back: no history exists yet" );
00670 vlc_object_release( p_playlist );
00671 return;
00672 }
00673
00674 p_history = history.p_address;
00675 #ifdef CMML_INTF_DEBUG
00676 msg_Dbg( p_intf, "back: nav history retrieved from %p", p_history );
00677 msg_Dbg( p_intf, "nav history index:%d, p_xarray:%p", p_history->i_index,
00678 p_history->p_xarray );
00679 #endif
00680
00681
00682 if( history_CanGoBack( p_history ) == VLC_FALSE )
00683 {
00684 msg_Warn( p_intf, "can't go back: already at beginning of history" );
00685 vlc_object_release( p_playlist );
00686 return;
00687 }
00688
00689 p_current_item = p_playlist->pp_items[p_playlist->i_index];
00690
00691
00692 psz_timed_url = GetTimedURLFromPlaylistItem( p_intf, p_current_item );
00693 p_new_history_item = historyItem_New( psz_timed_url, psz_timed_url );
00694 free( psz_timed_url );
00695
00696 if( !p_new_history_item )
00697 {
00698 #ifdef CMML_INTF_DEBUG
00699 msg_Dbg( p_intf, "back: could not initialise new history item" );
00700 #endif
00701 vlc_object_release( p_playlist );
00702 return;
00703 }
00704
00705
00706 (void) history_GoBackSavingCurrentItem( p_history, p_new_history_item );
00707 p_history_item = history_Item( p_history );
00708
00709 #ifdef CMML_INTF_DEBUG
00710 msg_Dbg( p_intf, "retrieving item from h index %d", p_history->i_index );
00711 msg_Dbg( p_intf, "got previous history item: %p", p_history_item );
00712 msg_Dbg( p_intf, "prev history item URL: \"%s\"", p_history_item->psz_uri );
00713 #endif
00714
00715 ReplacePlaylistItem( p_playlist, p_history_item->psz_uri );
00716 vlc_object_release( p_playlist );
00717 }
00718
00719 static
00720 void GoForward( intf_thread_t *p_intf )
00721 {
00722 vlc_value_t history;
00723 history_t *p_history = NULL;
00724 history_item_t *p_history_item = NULL;
00725 history_item_t *p_new_history_item = NULL;
00726 playlist_t *p_playlist = NULL;
00727 playlist_item_t *p_current_item;
00728
00729 #ifdef CMML_INTF_DEBUG
00730 msg_Dbg( p_intf, "Going forward in navigation history" );
00731 #endif
00732
00733
00734 p_playlist = (playlist_t *) vlc_object_find( p_intf,
00735 VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
00736 if ( !p_playlist )
00737 {
00738 msg_Warn( p_intf, "can't find playlist" );
00739 return;
00740 }
00741
00742
00743 if( var_Get( p_playlist, "navigation-history", &history ) != VLC_SUCCESS ||
00744 !history.p_address )
00745 {
00746
00747 msg_Warn( p_intf, "can't go back: no history exists yet" );
00748 vlc_object_release( p_playlist );
00749 return;
00750 }
00751
00752 p_history = history.p_address;
00753 #ifdef CMML_INTF_DEBUG
00754 msg_Dbg( p_intf, "forward: nav history retrieved from %p", p_history );
00755 msg_Dbg( p_intf, "nav history index:%d, p_xarray:%p", p_history->i_index,
00756 p_history->p_xarray );
00757 #endif
00758
00759
00760 if( history_CanGoForward( p_history ) == VLC_FALSE )
00761 {
00762 msg_Warn( p_intf, "can't go forward: already at end of history" );
00763 vlc_object_release( p_playlist );
00764 return;
00765 }
00766
00767
00768 p_new_history_item = malloc( sizeof(history_item_t) );
00769 if( !p_new_history_item )
00770 {
00771 #ifdef CMML_INTF_DEBUG
00772 msg_Dbg( p_intf, "forward: could not initialise new history item" );
00773 #endif
00774 vlc_object_release( p_playlist );
00775 return;
00776 }
00777 p_current_item = p_playlist->pp_items[p_playlist->i_index];
00778 p_new_history_item->psz_uri = GetTimedURLFromPlaylistItem( p_intf,
00779 p_current_item );
00780 p_new_history_item->psz_name = p_new_history_item->psz_uri;
00781
00782
00783 (void) history_GoForwardSavingCurrentItem( p_history, p_new_history_item );
00784 p_history_item = history_Item( p_history );
00785
00786 #ifdef CMML_INTF_DEBUG
00787 msg_Dbg( p_intf, "retrieving item from h index %d", p_history->i_index );
00788 msg_Dbg( p_intf, "got next history item: %p", p_history_item );
00789 msg_Dbg( p_intf, "next history item URL: \"%s\"", p_history_item->psz_uri );
00790 #endif
00791
00792 ReplacePlaylistItem( p_playlist, p_history_item->psz_uri );
00793 vlc_object_release( p_playlist );
00794 }
00795
00796 static void ReplacePlaylistItem( playlist_t *p_playlist, char *psz_uri )
00797 {
00798 playlist_Stop( p_playlist );
00799 (void) playlist_Add( p_playlist, psz_uri, psz_uri,
00800 PLAYLIST_REPLACE, p_playlist->i_index );
00801 playlist_Goto( p_playlist, p_playlist->i_index );
00802 }
00803
00804
00805
00806
00807 static int DisplayAnchor( intf_thread_t *p_intf,
00808 vout_thread_t *p_vout,
00809 char *psz_anchor_description,
00810 char *psz_anchor_url )
00811 {
00812 int i_margin_h, i_margin_v;
00813 mtime_t i_now;
00814
00815 i_margin_h = 0;
00816 i_margin_v = 10;
00817
00818 i_now = mdate();
00819
00820 if( p_vout )
00821 {
00822 text_style_t *p_style = NULL;
00823
00824 text_style_t blue_with_underline = default_text_style;
00825 blue_with_underline.b_underline = VLC_TRUE;
00826 blue_with_underline.i_color = 0x22ff22;
00827
00828 if( psz_anchor_url )
00829 {
00830
00831
00832 p_style = &blue_with_underline;
00833
00834 }
00835
00836
00837
00838
00839 if ( vout_ShowTextAbsolute( p_vout, DEFAULT_CHAN,
00840 psz_anchor_description, p_style, OSD_ALIGN_BOTTOM,
00841 i_margin_h, i_margin_v, i_now, 0 ) == VLC_SUCCESS )
00842 {
00843
00844 }
00845 else
00846 {
00847 return VLC_EGENERIC;
00848 }
00849
00850 }
00851 else
00852 {
00853 msg_Dbg( p_intf, "DisplayAnchor couldn't find a video output" );
00854 return VLC_EGENERIC;
00855 }
00856
00857 return VLC_SUCCESS;
00858 }
00859
00860 static history_t * GetHistory( playlist_t *p_playlist )
00861 {
00862 vlc_value_t val;
00863 history_t *p_history = NULL;
00864
00865 if( var_Get( p_playlist, "navigation-history", &val ) != VLC_SUCCESS )
00866 {
00867
00868 history_t *new_history = history_New();
00869 val.p_address = new_history;
00870 var_Create( p_playlist, "navigation-history",
00871 VLC_VAR_ADDRESS|VLC_VAR_DOINHERIT );
00872 if( var_Set( p_playlist, "navigation-history", val ) != VLC_SUCCESS )
00873 {
00874 msg_Warn( p_playlist, "could not initialise history" );
00875 }
00876 else
00877 {
00878 p_history = new_history;
00879 #ifdef CMML_INTF_HISTORY_DEBUG
00880 msg_Dbg( p_playlist, "nav history created at %p", new_history );
00881 msg_Dbg( p_playlist, "nav history index:%d, p_xarray:%p",
00882 p_history->i_index, p_history->p_xarray );
00883 #endif
00884 }
00885 }
00886 else
00887 {
00888 p_history = val.p_address;
00889 #ifdef CMML_INTF_HISTORY_DEBUG
00890 msg_Dbg( p_playlist, "nav history retrieved from %p", p_history );
00891 #endif
00892 }
00893
00894 return p_history;
00895 }
00896