1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282
|
namespace eval record_channels {
set_help_text record_channels \
{Convenience function to control recording of individual channels of
sounddevice(s).
There are three subcommands (start, stop and list) to respectively start
recording additional channels, to stop recording all or some channels and
to list which channels are currently being recorded.
record_channels [start] [<device> [<channels>]]
record_channels stop [<device> [<channels>]]
record_channels list
When starting recording, you can optionally specify a prefix for the
destination file names with the -prefix option.
Some examples will make it much clearer:
- To start recording:
record_channels start PSG record all PSG channels
record_channels PSG the 'start' keyword can be left out
record_channels SCC 1,3-5 only record channels 1 and 3 to 5
record_channels SCC PSG 1 record all SCC channels + PSG channel 1
record_channels all record all channels of all devices
record_channels all -prefix t record all channels of all devices using
prefix 't'
- To stop recording
record_channels stop stop all recording
record_channels stop PSG stop recording all PSG channels
record_channels stop SCC 3,5 stop recording SCC channels 3 and 5
- To show the current status
record_channels list shows which channels are being recorded
}
set mute_help_text \
{Convenience function to control (un)muting of individual channels of
soundevice(s).
Examples:
mute_channels PSG mute all PSG channels
mute_channels SCC 2,4 mute SCC channels 2 and 4
unmute_channels PSG 1 SCC 3-5 unmute PSG channel 1, SCC channels 3 to 5
mute_channels show which channels are currently muted
unmute_channels unmute all channels on all devices
solo PSG 2 mute everything except PSG channel 2
}
set_help_text mute_channels $mute_help_text
set_help_text unmute_channels $mute_help_text
set_help_text solo $mute_help_text
set_tabcompletion_proc record_channels [namespace code tab_sounddevice_channels]
set_tabcompletion_proc mute_channels [namespace code tab_sounddevice_channels]
set_tabcompletion_proc unmute_channels [namespace code tab_sounddevice_channels]
set_tabcompletion_proc solo [namespace code tab_sounddevice_channels]
proc tab_sounddevice_channels {args} {
set result [machine_info sounddevice]
if {([lindex $args 0] eq "record_channels") && ([llength $args] == 2)} {
set result [concat $result "start stop list all"]
}
return $result
}
proc parse_channel_numbers {str} {
set result [list]
foreach a [split $str ", "] {
set b [split $a "-"]
foreach c $b {
if {![string is integer $c]} {
error "Not an integer: $c"
}
}
switch [llength $b] {
0 {}
1 {lappend result [lindex $b 0]}
2 {for {set i [lindex $b 0]} {$i <= [lindex $b 1]} {incr i} {
lappend result $i
}}
default {error "Invalid range: $a"}
}
}
return [lsort -unique $result]
}
proc get_all_channels {device} {
set i 1
set channels [list]
while {[info exists ::${device}_ch${i}_record]} {
lappend channels $i
incr i
}
return $channels
}
proc get_all_devices_all_channels {} {
set result [list]
foreach device [machine_info sounddevice] {
lappend result $device [get_all_channels $device]
}
return $result
}
proc get_recording_channels {} {
set result [list]
set sounddevices [machine_info sounddevice]
foreach device $sounddevices {
set active [list]
foreach ch [get_all_channels $device] {
set var ::${device}_ch${ch}_record
if {[set $var] ne ""} {
lappend active $ch
}
}
if {[llength $active]} {
lappend result "$device: $active"
}
}
return $result
}
proc get_muted_channels {} {
set result [list]
set sounddevices [machine_info sounddevice]
foreach device $sounddevices {
set active [list]
foreach ch [get_all_channels $device] {
set var ::${device}_ch${ch}_mute
if {[set $var]} {
lappend active $ch
}
}
if {[llength $active]} {
lappend result "$device: $active"
}
}
return $result
}
proc parse_device_channels {tokens} {
set sounddevices [machine_info sounddevice]
set device_channels [list]
if {[lindex $tokens 0] == "all"} {
foreach device $sounddevices {
lappend device_channels $device [get_all_channels $device]
}
return $device_channels
}
while {[llength $tokens]} {
set device [lindex $tokens 0]
set tokens [lrange $tokens 1 end]
if {$device ni $sounddevices} {
error "Unknown sounddevice: $device"
}
set range [lindex $tokens 0]
if {($range ne "") && ($range ni $sounddevices)} {
set channels [parse_channel_numbers $range]
set tokens [lrange $tokens 1 end]
foreach ch $channels {
if {![info exists ::${device}_ch${ch}_record]} {
error "No channel $ch on sounddevice $device"
}
}
} else {
set channels [get_all_channels $device]
}
lappend device_channels $device $channels
}
return $device_channels
}
proc record_channels {args} {
set start true
set device_channels [list]
# parse subcommand (default is start)
set first [lindex $args 0]
switch $first {
list {
return [join [get_recording_channels] "\n"]
}
start -
stop {
set start [string equal $first "start"]
set args [lrange $args 1 end]
}
}
if {$start} {
set prefix [utils::filename_clean [guess_title]]
# see if there's a -prefix option to override the default
set prefix_index [lsearch -exact $args "-prefix"]
if {$prefix_index >= 0 && $prefix_index < ([llength $args] - 1)} {
set prefix [lindex $args [expr {$prefix_index + 1}]]
set args [lreplace $args $prefix_index [expr {$prefix_index + 1}]]
}
}
# parse devices/channels
set device_channels [parse_device_channels $args]
# stop without any further arguments -> stop all
if {!$start && ![llength $device_channels]} {
foreach device [machine_info sounddevice] {
set channels [get_all_channels $device]
lappend device_channels $device $channels
}
}
set retval ""
# actually start/stop recording
foreach {device channels} $device_channels {
foreach ch $channels {
set var ::${device}_ch${ch}_record
if {$start} {
set directory [file normalize $::env(OPENMSX_USER_DATA)/../soundlogs]
# create dir always
file mkdir $directory
set software_section $prefix
if {$software_section ne ""} {
set software_section "${software_section}-"
}
set $var [utils::get_next_numbered_filename $directory "${software_section}${device}-ch${ch}_" ".wav"]
append retval "Recording $device channel $ch to [set $var]...\n"
} else {
if {[set $var] ne ""} {
append retval "Stopped recording $device channel $ch to [set $var]...\n"
}
set $var ""
}
}
}
return $retval
}
proc do_mute_channels {device_channels state} {
foreach {device channels} $device_channels {
foreach ch $channels {
set ::${device}_ch${ch}_mute $state
}
}
}
proc mute_channels {args} {
# parse devices/channels
set device_channels [parse_device_channels $args]
# no argumnets specified, list muted channels
if {![llength $device_channels]} {
return [join [get_muted_channels] "\n"]
}
# actually mute channels
do_mute_channels $device_channels true
}
proc unmute_channels {args} {
# parse devices/channels
set device_channels [parse_device_channels $args]
# no arguments specified, unmute all channels
if {![llength $device_channels]} {
set device_channels [get_all_devices_all_channels]
}
#actually unmute channels
do_mute_channels $device_channels false
}
proc solo {args} {
# parse devices/channels
set device_channels [parse_device_channels $args]
# mute everything, unmute specified channels
do_mute_channels [get_all_devices_all_channels] true
do_mute_channels $device_channels false
}
namespace export record_channels
namespace export mute_channels
namespace export unmute_channels
namespace export solo
} ;# namspace record_channels
namespace import record_channels::*
|