void SeekSlider::mouseMoveEvent( QMouseEvent *event ) { if( isSliding ) { setValue( QStyle::sliderValueFromPosition( MINIMUM, MAXIMUM, event->x() - handleLength() / 2, width() - handleLength(), false) ); emit sliderMoved( value() ); } /* Tooltip */ if ( inputLength > 0 ) { int margin = handleLength() / 2; int posX = qMax( rect().left() + margin, qMin( rect().right() - margin, event->x() ) ); QString chapterLabel; if ( orientation() == Qt::Horizontal ) /* TODO: vertical */ { QList<SeekPoint> points = chapters->getPoints(); int i_selected = -1; bool b_startsnonzero = false; if ( points.count() > 0 ) b_startsnonzero = ( points.at(0).time > 0 ); for( int i = 0 ; i < points.count() ; i++ ) { int x = points.at(i).time / 1000000.0 / inputLength * size().width(); if ( event->x() >= x ) i_selected = i + ( ( b_startsnonzero )? 1 : 0 ); } if ( i_selected >= 0 && i_selected < points.size() ) chapterLabel = points.at( i_selected ).name; } QPoint target( event->globalX() - ( event->x() - posX ), QWidget::mapToGlobal( pos() ).y() ); secstotimestr( psz_length, ( ( posX - margin ) * inputLength ) / ( size().width() - handleLength() ) ); mTimeTooltip->setTip( target, psz_length, chapterLabel ); } event->accept(); }
/** * Convert seconds to a time in the format h:mm:ss. * * This function is provided for any interface function which need to print a * time string in the format h:mm:ss * date. * \param secs the date to be converted * \param psz_buffer should be a buffer at least MSTRTIME_MAX_SIZE characters * \return psz_buffer is returned so this can be used as printf parameter. */ char *secstotimestr( char *psz_buffer, int32_t i_seconds ) { if( unlikely(i_seconds < 0) ) { secstotimestr( psz_buffer + 1, -i_seconds ); *psz_buffer = '-'; return psz_buffer; } div_t d; d = div( i_seconds, 60 ); i_seconds = d.rem; d = div( d.quot, 60 ); if( d.quot ) snprintf( psz_buffer, MSTRTIME_MAX_SIZE, "%u:%02u:%02u", d.quot, d.rem, i_seconds ); else snprintf( psz_buffer, MSTRTIME_MAX_SIZE, "%02u:%02u", d.rem, i_seconds ); return psz_buffer; }
void TimeLabel::setDisplayPosition( float pos, int64_t t, int length ) { showBuffering = false; bufTimer->stop(); if( pos == -1.f ) { setMinimumSize( QSize( 0, 0 ) ); if( displayType == TimeLabel::Both ) setText( "--:--/--:--" ); else setText( "--:--" ); return; } int time = t / 1000000; secstotimestr( psz_length, length ); secstotimestr( psz_time, ( b_remainingTime && length ) ? length - time : time ); // compute the minimum size that will be required for the psz_length // and use it to enforce a minimal size to avoid "dancing" widgets QSize minsize( 0, 0 ); if ( length > 0 ) { QMargins margins = contentsMargins(); minsize += QSize( fontMetrics().size( 0, QString( psz_length ), 0, 0 ).width(), sizeHint().height() ); minsize += QSize( margins.left() + margins.right() + 8, 0 ); /* +padding */ if ( b_remainingTime ) minsize += QSize( fontMetrics().size( 0, "-", 0, 0 ).width(), 0 ); } switch( displayType ) { case TimeLabel::Elapsed: setMinimumSize( minsize ); setText( QString( psz_time ) ); break; case TimeLabel::Remaining: if( b_remainingTime ) { setMinimumSize( minsize ); setText( QString("-") + QString( psz_time ) ); } else { setMinimumSize( QSize( 0, 0 ) ); setText( QString( psz_length ) ); } break; case TimeLabel::Both: default: QString timestr = QString( "%1%2/%3" ) .arg( QString( (b_remainingTime && length) ? "-" : "" ) ) .arg( QString( psz_time ) ) .arg( QString( ( !length && time ) ? "--:--" : psz_length ) ); setText( timestr ); break; } cachedLength = length; }
/***************************************************************************** * Run: xosd thread ***************************************************************************** * This part of the interface runs in a separate thread *****************************************************************************/ static void Run( intf_thread_t *p_intf ) { playlist_t *p_playlist; playlist_item_t *p_item = NULL; char *psz_display = NULL; int cancel = vlc_savecancel(); while( true ) { // Wait for a signal vlc_restorecancel( cancel ); vlc_mutex_lock( &p_intf->p_sys->lock ); mutex_cleanup_push( &p_intf->p_sys->lock ); while( !p_intf->p_sys->b_need_update ) vlc_cond_wait( &p_intf->p_sys->cond, &p_intf->p_sys->lock ); p_intf->p_sys->b_need_update = false; vlc_cleanup_run(); // Compute the signal cancel = vlc_savecancel(); p_playlist = pl_Hold( p_intf ); PL_LOCK; // If the playlist is empty don't do anything if( playlist_IsEmpty( p_playlist ) ) { PL_UNLOCK; pl_Release( p_intf ); continue; } free( psz_display ); int i_status = playlist_Status( p_playlist ); if( i_status == PLAYLIST_STOPPED ) { psz_display = strdup(_("Stop")); } else if( i_status == PLAYLIST_PAUSED ) { psz_display = strdup(_("Pause")); } else { p_item = playlist_CurrentPlayingItem( p_playlist ); if( !p_item ) { psz_display = NULL; PL_UNLOCK; pl_Release( p_intf ); continue; } input_item_t *p_input = p_item->p_input; mtime_t i_duration = input_item_GetDuration( p_input ); if( i_duration != -1 ) { char psz_durationstr[MSTRTIME_MAX_SIZE]; secstotimestr( psz_durationstr, i_duration / 1000000 ); if( asprintf( &psz_display, "%s (%s)", p_input->psz_name, psz_durationstr ) == -1 ) psz_display = NULL; } else psz_display = strdup( p_input->psz_name ); } PL_UNLOCK; pl_Release( p_intf ); /* Display */ xosd_display( p_intf->p_sys->p_osd, 0, /* first line */ XOSD_string, psz_display ); } }
void PlaylistManager::UpdateTreeItem( wxTreeItemId item ) { if( ! item.IsOk() ) return; wxTreeItemData *p_data = treectrl->GetItemData( item ); if( !p_data ) return; LockPlaylist( p_intf->p_sys, p_playlist ); playlist_item_t *p_item = playlist_ItemGetById( p_playlist, ((PlaylistItem *)p_data)->i_id ); if( !p_item ) { UnlockPlaylist( p_intf->p_sys, p_playlist ); return; } wxString msg; wxString duration = wxU( "" ); char *psz_author = vlc_input_item_GetInfo( &p_item->input, _(VLC_META_INFO_CAT), _(VLC_META_ARTIST) ); if( !psz_author ) { UnlockPlaylist( p_intf->p_sys, p_playlist ); return; } char psz_duration[MSTRTIME_MAX_SIZE]; mtime_t dur = p_item->input.i_duration; if( dur != -1 ) { secstotimestr( psz_duration, dur/1000000 ); duration.Append( wxU( " ( " ) + wxString( wxU( psz_duration ) ) + wxU( " )" ) ); } if( !strcmp( psz_author, "" ) || p_item->input.b_fixed_name == VLC_TRUE ) { msg = wxString( wxU( p_item->input.psz_name ) ) + duration; } else { msg = wxString(wxU( psz_author )) + wxT(" - ") + wxString(wxU(p_item->input.psz_name)) + duration; } free( psz_author ); treectrl->SetItemText( item , msg ); treectrl->SetItemImage( item, p_item->input.i_type ); if( p_playlist->status.p_item == p_item ) { treectrl->SetItemBold( item, true ); while( treectrl->GetItemParent( item ).IsOk() ) { item = treectrl->GetItemParent( item ); treectrl->Expand( item ); } } else { treectrl->SetItemBold( item, false ); } UnlockPlaylist( p_intf->p_sys, p_playlist ); }
/***************************************************************************** * Run: xosd thread ***************************************************************************** * This part of the interface runs in a separate thread *****************************************************************************/ static void Run( intf_thread_t *p_intf ) { int i_size,i_index; playlist_t *p_playlist; playlist_item_t *p_item = NULL; input_item_t item; char psz_duration[MSTRTIME_MAX_SIZE+2]; char *psz_display = NULL; while( !p_intf->b_die ) { if( p_intf->p_sys->b_need_update == VLC_TRUE ) { p_intf->p_sys->b_need_update = VLC_FALSE; p_playlist = (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); if( !p_playlist ) { continue; } if( p_playlist->i_size < 0 || p_playlist->i_index < 0 ) { vlc_object_release( p_playlist ); continue; } if( psz_display ) { free( psz_display ); psz_display = NULL; } if( p_playlist->status.i_status == PLAYLIST_STOPPED ) { psz_display = strdup(_("Stop")); vlc_object_release( p_playlist ); } else if( p_playlist->status.i_status == PLAYLIST_PAUSED ) { psz_display = strdup(_("Pause")); vlc_object_release( p_playlist ); } else { // vlc_mutex_lock(&p_playlist->object_lock ); p_item = p_playlist->status.p_item; item = p_item->input; if( !p_item ) { vlc_object_release( p_playlist ); // vlc_mutex_unlock(&p_playlist->object_lock ); continue; } i_size = p_playlist->i_size; i_index = p_playlist->i_index+1; // vlc_mutex_unlock(&p_playlist->object_lock ); vlc_object_release( p_playlist ); if( item.i_duration != -1 ) { char psz_durationstr[MSTRTIME_MAX_SIZE]; secstotimestr( psz_durationstr, item.i_duration/1000000 ); sprintf( psz_duration, "(%s)", psz_durationstr ); } else { sprintf( psz_duration," " ); } psz_display = (char *)malloc( sizeof(char )* (strlen( item.psz_name ) + MSTRTIME_MAX_SIZE + 2+6 + 10 +10 )); sprintf( psz_display," %i/%i - %s %s", i_index,i_size, item.psz_name, psz_duration); } /* Display */ xosd_display( p_intf->p_sys->p_osd, 0, /* first line */ XOSD_string, psz_display ); } msleep( INTF_IDLE_SLEEP ); } }
SeekSlider::SeekSlider( Qt::Orientation q, QWidget *_parent, bool _static ) : QSlider( q, _parent ), b_classic( _static ) { isSliding = false; f_buffering = 1.0; mHandleOpacity = 1.0; chapters = NULL; mHandleLength = -1; // prepare some static colors QPalette p = palette(); QColor background = p.color( QPalette::Active, QPalette::Background ); tickpointForeground = p.color( QPalette::Active, QPalette::WindowText ); tickpointForeground.setHsv( tickpointForeground.hue(), ( background.saturation() + tickpointForeground.saturation() ) / 2, ( background.value() + tickpointForeground.value() ) / 2 ); // set the background color and gradient QColor backgroundBase( p.window().color() ); backgroundGradient.setColorAt( 0.0, backgroundBase.darker( 140 ) ); backgroundGradient.setColorAt( 1.0, backgroundBase ); // set the foreground color and gradient QColor foregroundBase( 50, 156, 255 ); foregroundGradient.setColorAt( 0.0, foregroundBase ); foregroundGradient.setColorAt( 1.0, foregroundBase.darker( 140 ) ); // prepare the handle's gradient handleGradient.setColorAt( 0.0, p.window().color().lighter( 120 ) ); handleGradient.setColorAt( 0.9, p.window().color().darker( 120 ) ); // prepare the handle's shadow gradient QColor shadowBase = p.shadow().color(); if( shadowBase.lightness() > 100 ) shadowBase = QColor( 60, 60, 60 ); // Palette's shadow is too bright shadowDark = shadowBase.darker( 150 ); shadowLight = shadowBase.lighter( 180 ); shadowLight.setAlpha( 50 ); /* Timer used to fire intermediate updatePos() when sliding */ seekLimitTimer = new QTimer( this ); seekLimitTimer->setSingleShot( true ); /* Tooltip bubble */ mTimeTooltip = new TimeTooltip( this ); mTimeTooltip->setMouseTracking( true ); /* Properties */ setRange( MINIMUM, MAXIMUM ); setSingleStep( 2 ); setPageStep( 10 ); setMouseTracking( true ); setTracking( true ); setFocusPolicy( Qt::NoFocus ); /* Use the new/classic style */ if( !b_classic ) setStyle( new SeekStyle ); /* Init to 0 */ setPosition( -1.0, 0, 0 ); secstotimestr( psz_length, 0 ); animHandle = new QPropertyAnimation( this, "handleOpacity", this ); animHandle->setDuration( FADEDURATION ); animHandle->setStartValue( 0.0 ); animHandle->setEndValue( 1.0 ); hideHandleTimer = new QTimer( this ); hideHandleTimer->setSingleShot( true ); hideHandleTimer->setInterval( FADEOUTDELAY ); CONNECT( this, sliderMoved( int ), this, startSeekTimer() ); CONNECT( seekLimitTimer, timeout(), this, updatePos() ); CONNECT( hideHandleTimer, timeout(), this, hideHandle() ); mTimeTooltip->installEventFilter( this ); }
/***************************************************************************** * input_ControlVarNavigation: * Create all remaining control object variables *****************************************************************************/ void input_ControlVarNavigation( input_thread_t *p_input ) { vlc_value_t text; /* Create more command variables */ if( p_input->p->i_title > 1 ) { if( var_Type( p_input, "next-title" ) == 0 ) { var_Create( p_input, "next-title", VLC_VAR_VOID ); text.psz_string = _("Next title"); var_Change( p_input, "next-title", VLC_VAR_SETTEXT, &text, NULL ); var_AddCallback( p_input, "next-title", TitleCallback, NULL ); } if( var_Type( p_input, "prev-title" ) == 0 ) { var_Create( p_input, "prev-title", VLC_VAR_VOID ); text.psz_string = _("Previous title"); var_Change( p_input, "prev-title", VLC_VAR_SETTEXT, &text, NULL ); var_AddCallback( p_input, "prev-title", TitleCallback, NULL ); } if( var_Type( p_input, "menu-title" ) == 0 ) { var_Create( p_input, "menu-title", VLC_VAR_VOID ); text.psz_string = _("Menu title"); var_Change( p_input, "menu-title", VLC_VAR_SETTEXT, &text, NULL ); var_AddCallback( p_input, "menu-title", TitleCallback, NULL ); } if( var_Type( p_input, "menu-popup" ) == 0 ) { var_Create( p_input, "menu-popup", VLC_VAR_VOID ); text.psz_string = _("Menu popup"); var_Change( p_input, "menu-popup", VLC_VAR_SETTEXT, &text, NULL ); var_AddCallback( p_input, "menu-popup", TitleCallback, NULL ); } } /* Create titles and chapters */ var_Change( p_input, "title", VLC_VAR_CLEARCHOICES, NULL, NULL ); for( int i = 0; i < p_input->p->i_title; i++ ) { vlc_value_t val2, text2; char title[sizeof("title ") + 3 * sizeof (int)]; /* Add Navigation entries */ sprintf( title, "title %2u", i ); var_Destroy( p_input, title ); var_Create( p_input, title, VLC_VAR_INTEGER|VLC_VAR_HASCHOICE|VLC_VAR_ISCOMMAND ); var_AddCallback( p_input, title, NavigationCallback, (void *)(intptr_t)i ); char psz_length[MSTRTIME_MAX_SIZE + sizeof(" []")]; if( p_input->p->title[i]->i_length > 0 ) { strcpy( psz_length, " [" ); secstotimestr( &psz_length[2], p_input->p->title[i]->i_length / CLOCK_FREQ ); strcat( psz_length, "]" ); } else psz_length[0] = '\0'; if( p_input->p->title[i]->psz_name == NULL || *p_input->p->title[i]->psz_name == '\0' ) { if( asprintf( &text.psz_string, _("Title %i%s"), i + p_input->p->i_title_offset, psz_length ) == -1 ) continue; } else { if( asprintf( &text.psz_string, "%s%s", p_input->p->title[i]->psz_name, psz_length ) == -1 ) continue; } /* Add title choice */ val2.i_int = i; var_Change( p_input, "title", VLC_VAR_ADDCHOICE, &val2, &text ); free( text.psz_string ); for( int j = 0; j < p_input->p->title[i]->i_seekpoint; j++ ) { val2.i_int = j; if( p_input->p->title[i]->seekpoint[j]->psz_name == NULL || *p_input->p->title[i]->seekpoint[j]->psz_name == '\0' ) { /* Default value */ if( asprintf( &text2.psz_string, _("Chapter %i"), j + p_input->p->i_seekpoint_offset ) == -1 ) continue; } else { text2.psz_string = strdup( p_input->p->title[i]->seekpoint[j]->psz_name ); } var_Change( p_input, title, VLC_VAR_ADDCHOICE, &val2, &text2 ); free( text2.psz_string ); } } }
/***************************************************************************** * Manage: manage main thread messages ***************************************************************************** * In this function, called approx. 10 times a second, we check what the * main program wanted to tell us. *****************************************************************************/ void Timer::Notify( void ) { vlc_value_t val; char *shortname; /* Update the input */ if( p_intf->p_sys->p_input == NULL ) { p_intf->p_sys->p_input = (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT, FIND_ANYWHERE ); /* Show slider */ if( p_intf->p_sys->p_input ) { ShowWindow( p_main_interface->hwndSlider, SW_SHOW ); ShowWindow( p_main_interface->hwndLabel, SW_SHOW ); ShowWindow( p_main_interface->hwndVol, SW_SHOW ); // only for local file, check if works well with net url input_item_t *p_item =input_GetItem(p_intf->p_sys->p_input); shortname = strrchr( input_item_GetURL(p_item), '\\' ); if (! shortname) shortname = input_item_GetURL(p_item); else shortname++; SendMessage( p_main_interface->hwndSB, SB_SETTEXT, (WPARAM) 0, (LPARAM)_FROMMB(shortname) ); p_main_interface->TogglePlayButton( PLAYING_S ); i_old_playing_status = PLAYING_S; } } else if( p_intf->p_sys->p_input->b_dead ) { /* Hide slider */ ShowWindow( p_main_interface->hwndSlider, SW_HIDE); ShowWindow( p_main_interface->hwndLabel, SW_HIDE); ShowWindow( p_main_interface->hwndVol, SW_HIDE); p_main_interface->TogglePlayButton( PAUSE_S ); i_old_playing_status = PAUSE_S; SendMessage( p_main_interface->hwndSB, SB_SETTEXT, (WPARAM) 0, (LPARAM)(LPCTSTR) TEXT("")); vlc_object_release( p_intf->p_sys->p_input ); p_intf->p_sys->p_input = NULL; } if( p_intf->p_sys->p_input ) { input_thread_t *p_input = p_intf->p_sys->p_input; if( vlc_object_alive (p_input) ) { /* New input or stream map change */ p_intf->p_sys->b_playing = 1; /* Manage the slider */ if( /*p_input->stream.b_seekable &&*/ p_intf->p_sys->b_playing ) { /* Update the slider if the user isn't dragging it. */ if( p_intf->p_sys->b_slider_free ) { vlc_value_t pos; char psz_time[ MSTRTIME_MAX_SIZE ]; vlc_value_t time; mtime_t i_seconds; /* Update the value */ var_Get( p_input, "position", &pos ); if( pos.f_float >= 0.0 ) { p_intf->p_sys->i_slider_pos = (int)(SLIDER_MAX_POS * pos.f_float); SendMessage( p_main_interface->hwndSlider, TBM_SETPOS, 1, p_intf->p_sys->i_slider_pos ); var_Get( p_intf->p_sys->p_input, "time", &time ); i_seconds = time.i_time / 1000000; secstotimestr ( psz_time, i_seconds ); SendMessage( p_main_interface->hwndLabel, WM_SETTEXT, (WPARAM)1, (LPARAM)_FROMMB(psz_time) ); } } } /* Take care of the volume, etc... */ p_main_interface->Update(); /* Manage Playing status */ var_Get( p_input, "state", &val ); if( i_old_playing_status != val.i_int ) { if( val.i_int == PAUSE_S ) { p_main_interface->TogglePlayButton( PAUSE_S ); } else { p_main_interface->TogglePlayButton( PLAYING_S ); } i_old_playing_status = val.i_int; } /* Manage Speed status */ var_Get( p_input, "rate", &val ); if( i_old_rate != val.i_int ) { TCHAR psz_text[15]; _stprintf( psz_text + 2, _T("x%.2f"), 1000.0 / val.i_int ); psz_text[0] = psz_text[1] = _T('\t'); SendMessage( p_main_interface->hwndSB, SB_SETTEXT, (WPARAM) 1, (LPARAM)(LPCTSTR) psz_text ); i_old_rate = val.i_int; } } } else if( p_intf->p_sys->b_playing && vlc_object_alive( p_intf ) ) { p_intf->p_sys->b_playing = 0; p_main_interface->TogglePlayButton( PAUSE_S ); i_old_playing_status = PAUSE_S; } if( !vlc_object_alive( p_intf ) ) { /* Prepare to die, young Skywalker */ /* p_main_interface->Close(TRUE);*/ return; } }