NAME

App::DrivePlayer::Player - mpv-based audio player that streams from Google Drive

SYNOPSIS

use App::DrivePlayer::Player;

my $player = App::DrivePlayer::Player->new(
    auth             => $auth_obj,      # Google::RestApi::Auth::*
    on_state_change  => sub { my $state = shift; ... },  # 'play','pause','stop'
    on_track_end     => sub { ... },
    on_position      => sub { my ($pos_s, $dur_s) = @_; ... },
);

$player->play({ drive_id => $file_id, title => 'Song' });
$player->pause_resume;
$player->seek(90);          # jump to 1:30
$player->set_volume(80);    # 0-100
$player->stop;
$player->quit;              # terminate mpv

# Call periodically from a GUI timer:
$player->poll;

DESCRIPTION

Controls an mpv subprocess via its JSON IPC socket. Audio files are streamed directly from Google Drive using the Drive media URL with a Bearer token injected as an HTTP header. The Bearer token is cached and automatically refreshed after 55 minutes.

mpv is started lazily on the first call to "play" and reused for subsequent tracks.

ATTRIBUTES

auth

is: ro, required: 1

An authentication object with a headers() method returning an arrayref of the form ['Authorization', 'Bearer TOKEN'] (e.g. Google::RestApi::Auth::OAuth2Client).

on_state_change

is: ro, isa: CodeRef, optional

Called with the new state string ('play', 'pause', or 'stop') whenever the playback state changes. Not called when the state is set to its current value.

on_track_end

is: ro, isa: CodeRef, optional

Called with no arguments when a track ends naturally (EOF) or is stopped explicitly.

on_position

is: ro, isa: CodeRef, optional

Called by "poll" with ($position_seconds, $duration_seconds) when both values are available from mpv.

METHODS

new

my $player = App::DrivePlayer::Player->new(%args);

Constructor. auth is required; all callbacks are optional.

play

$player->play(\%track);

Begin playing a track. %track must contain at least drive_id. Starts mpv if it is not already running. Sets state to 'play'.

pause_resume

$player->pause_resume;

Toggle between 'play' and 'pause'. No-op when stopped.

stop

$player->stop;

Stop playback and set state to 'stop'. mpv remains running.

seek

$player->seek($seconds);

Seek to an absolute position in seconds. No-op when stopped.

set_volume

$player->set_volume($percent);   # 0-100

Set the playback volume.

get_volume

my $pct = $player->get_volume;

Return the current volume (0-100). Returns 50 if mpv is not responding.

state

my $state = $player->state;   # 'play', 'pause', or 'stop'

Return the current playback state.

current_track

my $track = $player->current_track;   # hashref or undef

Return the track hashref passed to the most recent "play" call.

poll

$player->poll;

Query mpv for the current playback position and duration, firing the on_position callback if both are available. Also drains any pending mpv events. Intended to be called from a periodic GUI timer.

quit

$player->quit;

Send a quit command to mpv, wait briefly, then SIGTERM it if still running. Closes the IPC socket. Should be called when the application exits.