Skip to content

Commit

Permalink
Guarantee previous track return where seek supported
Browse files Browse the repository at this point in the history
  • Loading branch information
alyosha committed Sep 26, 2020
1 parent 09dc95b commit 3ec02b5
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 50 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ for now I've just tried to cover those places that throw errors when unavailable
Rhythmbox is an example of a fully-implemented player, while a player like chromium
is still very limited in terms of supported functionality.

For players that support the `Seek` command, `Prev` will return to the previous
track regardless of the position of the current track. If `Seek` is not
supported, `Prev` will only return to the previous track if the command is
called within the first few seconds of playback (default MPRIS behavior).

## Config
To configure a default media player, add a line like the following to your
vimrc dotfile:
Expand Down
4 changes: 2 additions & 2 deletions dbus/get_property
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ case $2 in
"Volume")
sed_pattern="/double/{s/[[:alpha:]-]//g;s/^\s*//g;p}"
;;
"Shuffle")
"Shuffle"|"CanSeek")
sed_pattern="/boolean/{s/variant//g;s/boolean//g;s/^\s*//g;p}"
;;
"Position")
Expand All @@ -22,4 +22,4 @@ dbus-send \
/org/mpris/MediaPlayer2 \
org.freedesktop.DBus.Properties.Get \
string:'org.mpris.MediaPlayer2.Player' \
string:$2 | sed -ne "$sed_pattern"
string:$2 | sed -ne "$sed_pattern"
108 changes: 60 additions & 48 deletions plugin/vimedia.vim
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ fu! s:QuitCmd(player)
endfu

" *************************************************************************** "
" ********************** D-Bus Command Callbacks ************************ "
" ************************* Command Callbacks *************************** "
" *************************************************************************** "

fu! s:SetPlayerCallback(channel, msg)
Expand Down Expand Up @@ -96,6 +96,18 @@ fu! s:PauseAllCallback(channel, msg)
call s:PauseAllPlayers(a:msg)
endfu

fu! s:PreviousCallback(channel, msg)
if a:msg == "true"
call job_start(s:SeekCmd(s:selected_player, -1 * s:ticker_microseconds), {"callback": function("s:SeekStartCallback")})
else
call job_start(s:ControlPlaybackCmd(s:selected_player, "Previous"))
endif
endfu

fu! s:SeekStartCallback(channel, msg)
call job_start(s:ControlPlaybackCmd(s:selected_player, "Previous"))
endfu

fu! s:MuteCallback(channel, msg)
call s:SetVolumeAll(a:msg, 0.0)
endfu
Expand Down Expand Up @@ -138,7 +150,7 @@ fu! s:QuitCallback(channel, msg)
endfu

" *************************************************************************** "
" ************************** Timer Functions **************************** "
" ************************* Base Functionality ************************** "
" *************************************************************************** "

fu! s:init_now_playing_config()
Expand All @@ -149,51 +161,6 @@ endfu

call s:init_now_playing_config()

fu! s:Refresh(timer)
if s:selected_player == "N/A"
return
endif

call job_start(s:GetPropertyCmd(s:selected_player, "Position"), {"out_cb": function("s:GetPositionCallback")})
call job_start(s:GetMetadataCmd(s:selected_player, "Title"), {"out_cb": function("s:GetTitleCallback")})
call job_start(s:GetMetadataCmd(s:selected_player, "Artist"), {"out_cb": function("s:GetArtistCallback")})
endfu

fu! NowPlayingText()
return s:current_track_name . " - " . s:current_artist_name
endfu

fu! PlaybackTicker()
let l:pos_seconds = s:ticker_microseconds / 1000000
let l:min = l:pos_seconds / 60
let l:sec = l:pos_seconds - (l:min * 60)
return l:min . ":" . (l:sec > 9 ? l:sec : ("0" . l:sec))
endfu

fu! s:UpdateStatusline(timer)
if g:vimedia_statusline_enabled == 0
return
endif

if s:selected_player == "N/A" || s:current_artist_name == "N/A" || s:current_track_name == "N/A"
return
endif

set statusline=
set statusline+=\%{NowPlayingText()}
set statusline+=%=
set statusline+=\%{PlaybackTicker()}
endfu

"" Refresh track/artist name and playback ticker every half-second
let timer = timer_start(500, function('s:Refresh'), {'repeat':-1})
"" Update the status line each second with the latest playback info
let timer = timer_start(1000, function('s:UpdateStatusline'), {'repeat':-1})

" *************************************************************************** "
" ************************* Base Functionality ************************** "
" *************************************************************************** "

fu! s:init_player_config()
let s:selected_player_abbrev = ""

Expand Down Expand Up @@ -240,7 +207,7 @@ fu! s:Skip() abort
endfu

fu! s:Previous() abort
call job_start(s:ControlPlaybackCmd(s:selected_player, "Previous"))
call job_start(s:GetPropertyCmd(s:selected_player, "CanSeek"), {"out_cb": function("s:PreviousCallback")})
endfu

fu! s:Seek(duration_seconds) abort
Expand Down Expand Up @@ -347,6 +314,51 @@ fu! s:CheckPlayer(fn, ...) abort
endif
endfu

" *************************************************************************** "
" ************************** Timer Functions **************************** "
" *************************************************************************** "

fu! s:Refresh(timer)
if s:selected_player == "N/A"
return
endif

call job_start(s:GetPropertyCmd(s:selected_player, "Position"), {"out_cb": function("s:GetPositionCallback")})
call job_start(s:GetMetadataCmd(s:selected_player, "Title"), {"out_cb": function("s:GetTitleCallback")})
call job_start(s:GetMetadataCmd(s:selected_player, "Artist"), {"out_cb": function("s:GetArtistCallback")})
endfu

fu! NowPlayingText()
return s:current_track_name . " - " . s:current_artist_name
endfu

fu! PlaybackTicker()
let l:pos_seconds = s:ticker_microseconds / 1000000
let l:min = l:pos_seconds / 60
let l:sec = l:pos_seconds - (l:min * 60)
return l:min . ":" . (l:sec > 9 ? l:sec : ("0" . l:sec))
endfu

fu! s:UpdateStatusline(timer)
if g:vimedia_statusline_enabled == 0
return
endif

if s:selected_player == "N/A" || s:current_artist_name == "N/A" || s:current_track_name == "N/A"
return
endif

set statusline=
set statusline+=\%{NowPlayingText()}
set statusline+=%=
set statusline+=\%{PlaybackTicker()}
endfu

"" Refresh track/artist name and playback ticker every half-second
let timer = timer_start(500, function('s:Refresh'), {'repeat':-1})
"" Update the status line each second with the latest playback info
let timer = timer_start(1000, function('s:UpdateStatusline'), {'repeat':-1})

" *************************************************************************** "
" *************************** Command Bindngs *************************** "
" *************************************************************************** "
Expand Down

0 comments on commit 3ec02b5

Please sign in to comment.