discstation 0.1.20 → 0.1.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/arduino/c6/DiscStation_C6.ino +7 -1
- package/arduino/v1/DiscStation.ino +4 -1
- package/install-windows.ps1 +29 -6
- package/package.json +1 -1
- package/src/discstation.py +409 -83
- package/src/discstation_burn.py +96 -18
- package/src/discstation_host.py +47 -16
- package/src/static/app.js +72 -0
- package/src/static/index.html +37 -3
- package/src/static/style.css +38 -0
- package/src/win/burn-audio.ps1 +18 -3
- package/src/win/burn-data.ps1 +21 -9
- package/src/win/burn-image.ps1 +17 -13
- package/src/win/disc-info.ps1 +13 -8
- package/src/win/play-audio-cd.ps1 +94 -0
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# Play a Red Book audio CD via Windows Media Player's COM control - mpv on
|
|
2
|
+
# Windows has no libcdio, so cdda:// is "disabled at compile-time" there.
|
|
3
|
+
# WMPlayer.OCX only actually plays when hosted in a real window with a
|
|
4
|
+
# message pump; a bare `New-Object -ComObject` never leaves playState
|
|
5
|
+
# "Ready". Runs as a tiny persistent process, polled by the caller:
|
|
6
|
+
#
|
|
7
|
+
# Commands: caller writes one command to $CmdFile (PAUSE | STOP | NEXT |
|
|
8
|
+
# PREV | VOL:<0-100>); this script deletes it once consumed. A file-based
|
|
9
|
+
# channel instead of stdin - a background thread reading Console stdin
|
|
10
|
+
# here crashed the whole process outright (a piped stdin under a
|
|
11
|
+
# powershell.exe launched via -File from a console-less pythonw.exe
|
|
12
|
+
# parent apparently isn't safe to read from a second thread).
|
|
13
|
+
# Status (stdout): TRACK:<0-based index> | DONE | ERROR:<message>
|
|
14
|
+
#
|
|
15
|
+
# Usage: play-audio-cd.ps1 <drive e.g. D:> <command file path>
|
|
16
|
+
param(
|
|
17
|
+
[Parameter(Mandatory = $true)] [string] $Drive,
|
|
18
|
+
[Parameter(Mandatory = $true)] [string] $CmdFile
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
$ErrorActionPreference = "Stop"
|
|
22
|
+
Add-Type -AssemblyName System.Windows.Forms
|
|
23
|
+
|
|
24
|
+
# Write-Output through a redirected/piped stdout (SSH, or Python's own
|
|
25
|
+
# subprocess.PIPE) buffers until the process exits instead of flushing
|
|
26
|
+
# per line - confirmed live (only the final "DONE" ever arrived; every
|
|
27
|
+
# "TRACK:" sent during actual playback was stuck in the buffer). Writing
|
|
28
|
+
# straight to the console stream and flushing after each line sidesteps
|
|
29
|
+
# PowerShell's own output-pipeline buffering.
|
|
30
|
+
function Send-Status([string]$msg) {
|
|
31
|
+
[Console]::Out.WriteLine($msg)
|
|
32
|
+
[Console]::Out.Flush()
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
try {
|
|
36
|
+
$form = New-Object System.Windows.Forms.Form
|
|
37
|
+
$form.Show()
|
|
38
|
+
[System.Windows.Forms.Application]::DoEvents()
|
|
39
|
+
|
|
40
|
+
$wmp = New-Object -ComObject WMPlayer.OCX.7
|
|
41
|
+
$drives = $wmp.cdromCollection
|
|
42
|
+
$target = $null
|
|
43
|
+
for ($i = 0; $i -lt $drives.count; $i++) {
|
|
44
|
+
if ($drives.Item($i).driveSpecifier.TrimEnd('\') -ieq $Drive.TrimEnd('\')) { $target = $drives.Item($i); break }
|
|
45
|
+
}
|
|
46
|
+
if (-not $target) { Send-Status "ERROR:No CD drive $Drive"; exit 2 }
|
|
47
|
+
|
|
48
|
+
$wmp.currentPlaylist = $target.playlist
|
|
49
|
+
$wmp.controls.play()
|
|
50
|
+
} catch {
|
|
51
|
+
Send-Status ("ERROR:" + $_.Exception.Message)
|
|
52
|
+
exit 1
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
$lastTrack = -1
|
|
56
|
+
while ($true) {
|
|
57
|
+
Start-Sleep -Milliseconds 200
|
|
58
|
+
[System.Windows.Forms.Application]::DoEvents()
|
|
59
|
+
|
|
60
|
+
if ($wmp.playState -eq 8) { Send-Status "DONE"; break } # wmppsMediaEnded
|
|
61
|
+
|
|
62
|
+
# currentItem.playlistIndex comes back empty on this drive/build -
|
|
63
|
+
# confirmed live - but .name reliably reads "Track N" for a CD
|
|
64
|
+
# playlist item, so parse the number out of that instead.
|
|
65
|
+
$track = -1
|
|
66
|
+
try {
|
|
67
|
+
$item = $wmp.controls.currentItem
|
|
68
|
+
if ($item -and $item.name -match 'Track\s+(\d+)') { $track = [int]$Matches[1] - 1 }
|
|
69
|
+
} catch {}
|
|
70
|
+
if ($track -ge 0 -and $track -ne $lastTrack) {
|
|
71
|
+
$lastTrack = $track
|
|
72
|
+
Send-Status "TRACK:$track"
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (Test-Path -LiteralPath $CmdFile) {
|
|
76
|
+
$line = (Get-Content -LiteralPath $CmdFile -Raw -ErrorAction SilentlyContinue)
|
|
77
|
+
Remove-Item -LiteralPath $CmdFile -ErrorAction SilentlyContinue
|
|
78
|
+
if ($line) {
|
|
79
|
+
$line = $line.Trim()
|
|
80
|
+
switch -Regex ($line) {
|
|
81
|
+
'^PAUSE$' {
|
|
82
|
+
if ($wmp.playState -eq 3) { $wmp.controls.pause() } else { $wmp.controls.play() }
|
|
83
|
+
}
|
|
84
|
+
'^STOP$' { $wmp.controls.stop(); Send-Status "DONE"; break }
|
|
85
|
+
'^NEXT$' { $wmp.controls.next() }
|
|
86
|
+
'^PREV$' { $wmp.controls.previous() }
|
|
87
|
+
'^VOL:(\d+)$' { $wmp.settings.volume = [Math]::Min(100, [Math]::Max(0, [int]$Matches[1])) }
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
try { $wmp.controls.stop(); $wmp.close() } catch {}
|
|
94
|
+
try { $form.Close() } catch {}
|