NAME

App::DrivePlayer::SheetDB - Sync the DrivePlayer library to/from a Google Sheet

SYNOPSIS

use App::DrivePlayer::SheetDB;

my $sheet = App::DrivePlayer::SheetDB->new(
    api            => $google_rest_api,
    spreadsheet_id => $id,             # omit when calling create()
);

my $id     = $sheet->create();             # create spreadsheet, returns ID
my $counts = $sheet->push_to_sheet($db);  # { scan_folders => N, tracks => N }
my $counts = $sheet->pull_from_sheet($db);

DESCRIPTION

Maintains a Google Spreadsheet with one worksheet per scan folder, plus a folders index tab:

folders

drive_id and name for every top-level folder in the library.

One tab per folder (named after the folder)

Track metadata columns: drive_id title artist album track_number year duration_ms genre composer comment. Structural fields (folder_id, etc.) are re-derived from Drive scanning and are not stored in the sheet.

The local SQLite database remains the working store for all runtime queries. The Sheet is a portable sync target accessible from any device with Drive access.

NEW DEVICE WORKFLOW

1. File -> Sync from Sheet   # pulls scan_folders into SQLite
2. Library -> Sync           # discovers audio files on Drive
3. File -> Sync from Sheet   # applies saved metadata to the scanned tracks

METHODS

new(%args)

api (Google::RestApi instance) is required. spreadsheet_id is optional (omit before calling create()).

create()

Creates a new "DrivePlayer Library" spreadsheet with a folders tab. Returns and stores the new spreadsheet ID.

push_to_sheet($db)

Writes the folders index and one worksheet of track metadata per folder, replacing whatever was there before.

pull_from_sheet($db)

Upserts scan folders into SQLite and applies track metadata to any tracks already present (keyed by drive_id). Tracks not yet scanned locally are silently skipped.