App-DrivePlayer
view release on metacpan or search on metacpan
lib/App/DrivePlayer/GUI.pm view on Meta::CPAN
sub _play_at_path {
my ($self, $path, %opts) = @_;
my $track = $self->_track_at_path($path) or return;
return unless $self->_init_api();
eval { $self->player->play($track) };
if ($@) {
$self->_show_error("Playback error: $@");
return;
}
$self->_playing_track_id($track->{id});
$self->_playing_row_ref(Gtk3::TreeRowReference->new($self->track_store, $path));
$self->_update_now_playing($track);
$self->_highlight_path($path) unless $opts{no_scroll};
}
sub _toggle_play {
my ($self) = @_;
if (!$self->player || $self->player->state eq 'stop') {
my $sel = $self->track_view->get_selection();
my (undef, @paths) = $sel->get_selected_rows();
my $path = @paths ? $paths[0] : Gtk3::TreePath->new_from_indices(0);
$self->_play_at_path($path);
} else {
return unless $self->_init_api();
$self->player->pause_resume();
}
}
sub _stop {
my ($self) = @_;
return unless $self->player;
$self->player->stop();
$self->progress->set_value(0);
$self->time_label->set_text('0:00');
$self->now_playing_label->set_text('Not playing');
}
sub _next_track {
my ($self) = @_;
my $path = $self->_current_path();
if ($path) {
my $iter = $self->track_store->get_iter($path);
return unless $iter && $self->track_store->iter_next($iter);
$self->_play_at_path($self->track_store->get_path($iter));
} else {
$self->_play_at_path(Gtk3::TreePath->new_from_indices(0))
if @{ $self->_playlist };
}
}
sub _prev_track {
my ($self) = @_;
my $path = $self->_current_path() or return;
return unless $path->prev();
$self->_play_at_path($path);
}
# ---- Player callbacks ----
sub _on_track_end {
my ($self) = @_;
$self->_next_track();
}
sub _on_position {
my ($self, $pos, $dur) = @_;
return if $self->_progress_dragging;
$self->progress->set_range(0, $dur) if $dur;
$self->progress->set_value($pos) if defined $pos;
$self->time_label->set_text(_sec_str($pos));
$self->dur_label->set_text(_sec_str($dur));
# Persist duration when mpv reports it for a track that doesn't have one yet.
if ($dur && $dur > 0) {
my $id = $self->_playing_track_id;
my $track = $id ? $self->_track_by_id->{$id} : undef;
if ($track && !$track->{duration_ms}) {
my $ms = int($dur * 1000);
$track->{duration_ms} = $ms; # mutate to prevent firing again
$self->db->update_track_metadata($track->{id}, duration_ms => $ms);
$self->_refresh_track_row($track->{id});
}
}
}
sub _on_state_change {
my ($self, $state) = @_;
my $icon = $state eq 'play' ? 'media-playback-pause' : 'media-playback-start';
$self->play_btn->set_image(Gtk3::Image->new_from_icon_name($icon, 'button'));
if ($state eq 'stop') {
$self->stop_btn->hide();
} else {
$self->stop_btn->show();
}
}
sub _player_poll {
my ($self) = @_;
if ($self->player) {
eval { $self->player->poll() };
$log->warn("Player poll error: $@") if $@ && $log;
}
}
# ---- Sidebar activation ----
sub _sidebar_activated {
my ($self, $view) = @_;
return if $self->_suppress_sidebar_activated;
my ($path) = $view->get_cursor();
return unless $path;
my $store = $self->sidebar_store;
my $iter = $store->get_iter($path);
my $type = $store->get($iter, 1);
my $value = $store->get($iter, 2);
my $label = $store->get($iter, 0);
# Resolve the alpha-nav category for the current selection. Leaf rows look
( run in 1.395 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )