11use std:: time:: Duration ;
22
3- use cursive:: {
4- theme:: Style ,
5- utils:: { markup:: StyledString , span:: SpannedString } ,
6- } ;
7-
83use {
94 cursive:: {
105 event:: { Event , EventResult , MouseButton , MouseEvent } ,
11- theme:: { ColorStyle , Effect } ,
6+ theme:: { ColorStyle , Effect , Style } ,
127 traits:: View ,
8+ utils:: { markup:: StyledString , span:: SpannedString } ,
139 view:: Nameable ,
1410 CbSink , Cursive , Printer , XY ,
1511 } ,
@@ -29,6 +25,7 @@ const SEEK_TIME: Duration = Duration::from_secs(10);
2925
3026// Drawing constants
3127const SPACER : & ' static str = " " ;
28+ const TICK : u32 = 5 ;
3229
3330// A struct representing the view and state of the audio player.
3431pub struct PlayerView {
@@ -44,6 +41,12 @@ pub struct PlayerView {
4441 timed_bool : ExpiringBool ,
4542 // Whether or not the player is being shown.
4643 is_visible : bool ,
44+ // The elapsed playback time in whole seconds.
45+ elapsed : usize ,
46+ // The duration of the current track.
47+ duration : usize ,
48+ // The index of the current track.
49+ index : usize ,
4750 // The styled strings required to render the header and playlist.
4851 lines : Vec < SpannedString < Style > > ,
4952 // The vertical offset required to ensure the current track is visible in the playlist.
@@ -62,6 +65,9 @@ impl PlayerView {
6265 mouse_seek_time : None ,
6366 offset_y : 0 ,
6467 is_visible : true ,
68+ elapsed : 0 ,
69+ duration : 0 ,
70+ index : 0 ,
6571 lines : Vec :: new ( ) ,
6672 showing_volume : ExpiringBool :: new ( false , Duration :: from_millis ( 1500 ) ) ,
6773 number_input : vec ! [ ] ,
@@ -74,36 +80,58 @@ impl PlayerView {
7480 let cb_sink = siv. cb_sink ( ) . clone ( ) ;
7581 let player_view = PlayerView :: new ( player, cb_sink) . with_name ( super :: ID ) ;
7682
77- siv. set_fps ( crate :: FPS ) ;
83+ siv. set_fps ( TICK ) ;
7884 siv. pop_layer ( ) ;
7985 siv. add_layer ( player_view) ;
8086 }
8187
8288 pub fn update_playlist ( & mut self , next : Playlist , set_playing : bool ) {
83- _ = self . cb_sink . send ( Box :: new ( |siv| {
84- siv. set_fps ( crate :: FPS ) ;
85- } ) ) ;
86-
8789 let is_stopped = self . player . is_stopped ( ) ;
90+
91+ let volume = if self . player . is_muted {
92+ 0.0
93+ } else {
94+ ( self . player . volume as f32 ) / 100.0
95+ } ;
96+
8897 self . player . previous = Some ( self . player . current . clone ( ) ) ;
8998 self . player . current = next;
9099 self . player . stop ( ) ;
91100 self . player . play ( ) ;
92101
102+ self . player . set_volume ( volume) ;
103+
93104 if !set_playing && is_stopped {
94105 self . player . stop ( ) ;
95106 }
96107
97108 self . lines . clear ( ) ;
98- self . is_visible = true ;
109+
110+ self . show ( ) ;
99111 }
100112
101113 pub fn hide ( & mut self ) {
102114 self . is_visible = false ;
115+
116+ _ = self . cb_sink . send ( Box :: new ( |siv| {
117+ siv. set_fps ( 0 ) ;
118+ } ) ) ;
103119 }
104120
105121 pub fn show ( & mut self ) {
106122 self . is_visible = true ;
123+
124+ _ = self . cb_sink . send ( Box :: new ( |siv| {
125+ siv. set_fps ( TICK ) ;
126+ } ) ) ;
127+ }
128+
129+ fn play_or_pause ( & mut self ) {
130+ match self . player . status {
131+ PlaybackStatus :: Paused => self . player . resume ( ) ,
132+ PlaybackStatus :: Playing => self . player . pause ( ) ,
133+ PlaybackStatus :: Stopped => self . player . play ( ) ,
134+ } ;
107135 }
108136
109137 fn increase_volume ( & mut self ) {
@@ -265,12 +293,12 @@ impl PlayerView {
265293 let index = position. y - offset. y + self . offset_y - 1 ;
266294
267295 if index == self . player . current . index {
268- self . player . play_or_pause ( ) ;
296+ self . play_or_pause ( ) ;
269297 } else {
270298 self . player . play_index ( index) ;
271299 }
272300 }
273- Area :: Background => _ = self . player . play_or_pause ( ) ,
301+ Area :: Background => _ = self . play_or_pause ( ) ,
274302 }
275303 }
276304
@@ -364,16 +392,6 @@ impl PlayerView {
364392 format ! ( "{}vol: {:>3} %{}" , SPACER , self . player. volume, SPACER )
365393 }
366394
367- // The elapsed playback time to display. When seeking with the mouse we use the
368- // elapsed time had the seeking process completed.
369- #[ inline]
370- fn elapsed ( & self ) -> usize {
371- match self . mouse_seek_time {
372- Some ( t) if self . player . is_paused ( ) => t,
373- _ => self . player . elapsed ( ) . as_secs ( ) as usize ,
374- }
375- }
376-
377395 // Computes the y offset needed to show the results of the fuzzy match.
378396 #[ inline]
379397 fn update_offset ( & self ) -> usize {
@@ -440,6 +458,14 @@ impl View for PlayerView {
440458 }
441459 }
442460
461+ self . elapsed = match self . mouse_seek_time {
462+ Some ( t) if self . player . is_paused ( ) => t,
463+ _ => self . player . elapsed ( ) . as_secs ( ) as usize ,
464+ } ;
465+
466+ self . duration = self . player . current_file ( ) . duration ;
467+ self . index = self . player . current . index ;
468+
443469 self . size = self . required_size ( size) ;
444470 self . offset_y = self . update_offset ( ) ;
445471
@@ -465,24 +491,23 @@ impl View for PlayerView {
465491 }
466492
467493 let ( w, h) = ( self . size . x , self . size . y ) ;
468- let f = self . player . current_file ( ) ;
469- let duration_x = w. saturating_sub ( 9 ) ;
470- let elapsed = self . elapsed ( ) ;
471- let ( length, extra) = ratio ( elapsed, f. duration , w. saturating_sub ( 16 ) ) ;
494+
495+ let dur_col = w. saturating_sub ( 9 ) ;
472496
473497 // HEADER
474498 if h > 1 {
475499 // Artist + album + year
476- if let Some ( entry) = self . lines . chunks ( 5 ) . nth ( self . player . current . index ) {
477- if let Some ( header) = entry. get ( 4 ) {
500+
501+ if let Some ( line) = self . lines . chunks ( 5 ) . nth ( self . index ) {
502+ if let Some ( header) = line. get ( 4 ) {
478503 p. print_styled ( ( 0 , 0 ) , header) ;
479504 }
480505 }
481506
482507 // Volume
483508 if self . showing_volume . is_true ( ) {
484509 p. with_color ( ColorStyles :: prompt ( ) , |p| {
485- p. print ( ( duration_x . saturating_sub ( 5 ) , 0 ) , & self . volume ( ) )
510+ p. print ( ( dur_col . saturating_sub ( 5 ) , 0 ) , & self . volume ( ) )
486511 } ) ;
487512 } ;
488513 }
@@ -525,38 +550,39 @@ impl View for PlayerView {
525550 if let Some ( option) = self . playback_opts ( ) {
526551 p. with_color ( ColorStyles :: info ( ) , |p| {
527552 p. with_effect ( Effect :: Italic , |p| {
528- p. print ( ( duration_x . saturating_sub ( 3 ) , row) , option)
553+ p. print ( ( dur_col . saturating_sub ( 3 ) , row) , option)
529554 } )
530555 } )
531556 }
532557 }
533558
534559 // Duration
535- p. print_styled ( ( duration_x , row) , duration_line) ;
560+ p. print_styled ( ( dur_col , row) , duration_line) ;
536561 }
537562
538563 // FOOTER
539564 if h > 0 {
540- let bottom_row = h - 1 ;
541- let remaining = f. duration . saturating_sub ( elapsed) ;
565+ let last_row = h - 1 ;
566+ let ( length, extra) = ratio ( self . elapsed , self . duration , w. saturating_sub ( 16 ) ) ;
567+ let remaining = self . duration . saturating_sub ( self . elapsed ) ;
542568
543569 // Elapsed time
544570 p. with_color ( ColorStyles :: hl ( ) , |p| {
545- p. print ( ( 0 , bottom_row ) , & mins_and_secs ( elapsed) ) ;
571+ p. print ( ( 0 , last_row ) , & mins_and_secs ( self . elapsed ) ) ;
546572 } ) ;
547573
548574 // Progress bar
549575 p. with_color ( ColorStyles :: progress ( ) , |p| {
550- p. print ( ( length + 8 , bottom_row ) , sub_block ( extra) ) ;
576+ p. print ( ( length + 8 , last_row ) , sub_block ( extra) ) ;
551577 } ) ;
552578 p. cropped ( ( length + 8 , h) )
553579 . with_color ( ColorStyles :: progress ( ) , |p| {
554- p. print_hline ( ( 8 , bottom_row ) , length, "█" ) ;
580+ p. print_hline ( ( 8 , last_row ) , length, "█" ) ;
555581 } ) ;
556582
557583 // Remaining time
558584 p. with_color ( ColorStyles :: hl ( ) , |p| {
559- p. print ( ( duration_x , bottom_row ) , & mins_and_secs ( remaining) )
585+ p. print ( ( dur_col , last_row ) , & mins_and_secs ( remaining) )
560586 } ) ;
561587 }
562588 }
@@ -567,7 +593,7 @@ impl View for PlayerView {
567593
568594 if let Some ( action) = PLAYER_EVENT_TO_ACTION . get ( & event) {
569595 match action {
570- PlayOrPause => self . player . play_or_pause ( ) ,
596+ PlayOrPause => self . play_or_pause ( ) ,
571597 Stop => self . player . stop ( ) ,
572598 Next => self . next ( ) ,
573599 Previous => self . previous ( ) ,
0 commit comments