discstation 0.1.17 → 0.1.20

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.
@@ -0,0 +1,76 @@
1
+ # Optical drive + media state for DiscStation. Emits one JSON line.
2
+ # Works on PowerShell 2.0 (Win7) and later. Optional arg: a drive letter ("D:")
3
+ # to force; otherwise the first optical drive is used.
4
+ param([string]$Drive = "")
5
+
6
+ $ErrorActionPreference = "Stop"
7
+ . (Join-Path $PSScriptRoot "_json.ps1")
8
+
9
+ $out = @{ drive = ""; media_loaded = $false; blank = $false; label = "";
10
+ fs = ""; media_type = ""; rewritable = $false; capacity_bytes = 0 }
11
+
12
+ try {
13
+ $cd = @(Get-WmiObject Win32_CDROMDrive)
14
+ if ($Drive) { $cd = @($cd | Where-Object { $_.Drive -eq $Drive }) }
15
+ if ($cd.Count -eq 0) { Write-Output (ConvertTo-JsonCompat $out); exit 0 }
16
+ $d = $cd[0]
17
+ $out.drive = $d.Drive
18
+ # NOTE: [bool]"False" is $true in PowerShell (any non-empty string casts
19
+ # truthy) -- compare explicitly instead of casting.
20
+ $out.media_loaded = ($d.MediaLoaded -eq $true) -or ("$($d.MediaLoaded)" -eq "True")
21
+ } catch { Write-Output (ConvertTo-JsonCompat $out); exit 0 }
22
+
23
+ if (-not $out.media_loaded) { Write-Output (ConvertTo-JsonCompat $out); exit 0 }
24
+
25
+ # Volume label + filesystem (WMI logical disk).
26
+ try {
27
+ $ld = Get-WmiObject Win32_LogicalDisk -Filter ("DeviceID='" + $out.drive + "'")
28
+ if ($ld) {
29
+ if ($ld.VolumeName) { $out.label = $ld.VolumeName }
30
+ if ($ld.FileSystem) {
31
+ $fs = $ld.FileSystem.ToLower()
32
+ if ($fs -match "udf") { $out.fs = "udf" }
33
+ elseif ($fs -match "cdfs|iso9660") { $out.fs = "iso9660" }
34
+ else { $out.fs = $fs }
35
+ }
36
+ if ($ld.Size) { $out.capacity_bytes = [int64]$ld.Size }
37
+ }
38
+ } catch {}
39
+
40
+ # IMAPI2: physical media type, blank flag, recordable capacity.
41
+ try {
42
+ $master = New-Object -ComObject "IMAPI2.MsftDiscMaster2"
43
+ for ($i = 0; $i -lt $master.Count; $i++) {
44
+ $rec = New-Object -ComObject "IMAPI2.MsftDiscRecorder2"
45
+ $rec.InitializeDiscRecorder($master.Item($i))
46
+ $match = $false
47
+ foreach ($p in $rec.VolumePathNames) { if ($p -and $p.TrimEnd('\') -ieq $out.drive) { $match = $true } }
48
+ if (-not $match) { continue }
49
+ $fmt = New-Object -ComObject "IMAPI2.MsftDiscFormat2Data"
50
+ if (-not $fmt.IsRecorderSupported($rec)) { break }
51
+ $fmt.Recorder = $rec
52
+ $fmt.ClientName = "DiscStation"
53
+ try { $out.blank = ($fmt.MediaHeuristicallyBlank -eq $true) } catch {}
54
+ try { if ($fmt.MediaPhysicallyBlank) { $out.blank = $true } } catch {}
55
+ try { $out.capacity_bytes = [int64]$fmt.TotalSectorsOnMedia * 2048 } catch {}
56
+ $t = 0; try { $t = [int]$fmt.CurrentPhysicalMediaType } catch {}
57
+ # IMAPI_MEDIA_PHYSICAL_TYPE
58
+ $map = @{ 1="cd-rom"; 2="cd-r"; 3="cd-rw"; 4="dvd-rom"; 5="dvd-r"; 6="dvd-ram";
59
+ 7="dvd+r"; 8="dvd+rw"; 9="dvd+r dl"; 10="dvd-r dl"; 12="dvd+rw dl";
60
+ 16="bd-rom"; 17="bd-r"; 18="bd-re" }
61
+ if ($map.ContainsKey($t)) { $out.media_type = $map[$t] }
62
+ if ($out.media_type -match "rw|ram|-re") { $out.rewritable = $true }
63
+ break
64
+ }
65
+ } catch {}
66
+
67
+ # An audio CD has readable media, no filesystem, and (usually) no IMAPI type.
68
+ if (-not $out.fs -and -not $out.blank -and ($out.media_type -eq "" -or $out.media_type -match "^cd")) {
69
+ try {
70
+ $ld2 = Get-WmiObject Win32_CDROMDrive -Filter ("Drive='" + $out.drive + "'")
71
+ # Win32_CDROMDrive has no track info; treat "media loaded, no FS, not blank" as audio.
72
+ $out.media_type = "audio_cd"
73
+ } catch {}
74
+ }
75
+
76
+ Write-Output (ConvertTo-JsonCompat $out)
@@ -0,0 +1,30 @@
1
+ # Eject or close the optical tray via IMAPI2, with a Shell.Application fallback.
2
+ # Usage: eject.ps1 <drive letter e.g. D:> [close]
3
+ param([string]$Drive = "", [switch]$Close)
4
+
5
+ $ErrorActionPreference = "Stop"
6
+ $ok = $false
7
+
8
+ try {
9
+ $master = New-Object -ComObject "IMAPI2.MsftDiscMaster2"
10
+ for ($i = 0; $i -lt $master.Count; $i++) {
11
+ $rec = New-Object -ComObject "IMAPI2.MsftDiscRecorder2"
12
+ $rec.InitializeDiscRecorder($master.Item($i))
13
+ $match = -not $Drive
14
+ foreach ($p in $rec.VolumePathNames) { if ($p -and $Drive -and $p.TrimEnd('\') -ieq $Drive) { $match = $true } }
15
+ if (-not $match) { continue }
16
+ if ($Close) { $rec.CloseTray() } else { $rec.EjectMedia() }
17
+ $ok = $true
18
+ break
19
+ }
20
+ } catch {}
21
+
22
+ if (-not $ok -and -not $Close -and $Drive) {
23
+ try {
24
+ $sh = New-Object -ComObject "Shell.Application"
25
+ $sh.Namespace(17).ParseName($Drive).InvokeVerb("Eject")
26
+ $ok = $true
27
+ } catch {}
28
+ }
29
+
30
+ if ($ok) { exit 0 } else { Write-Error "eject failed"; exit 1 }