Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Changes In Branch merge-playablefile-virtualfile Excluding Merge-Ins
This is equivalent to a diff from 13b4854065 to b1f5b6074e
|
2024-08-05
| ||
| 05:01 | Merge merge-playablefile-virtualfile (but don't integrate). Update NEWS. check-in: 1986a4b965 user: alexa tags: trunk | |
| 04:57 | Update TRUNKSTATUS Closed-Leaf check-in: b1f5b6074e user: alexa tags: merge-playablefile-virtualfile | |
| 04:56 | Add a TODO check-in: 20ae9e67c9 user: alexa tags: merge-playablefile-virtualfile | |
| 03:57 | Merge the VirtualFile class into the PlayableFile class. Remove HTTP/Gemini loading. The two classes were overlapping in functionality. By combining them, we simplify some of the file handling code. check-in: 32db9d5345 user: alexa tags: merge-playablefile-virtualfile | |
| 01:19 | Add a check for the UI theme being an array check-in: 13b4854065 user: alexa tags: trunk | |
| 01:18 | Check for an empty array as a theme. Use the default theme in this case. check-in: 4bfcddb0b8 user: alexa tags: trunk | |
Changes to TRUNKSTATUS.
| ︙ | |||
14 15 16 17 18 19 20 | 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | - - + + | Loading ======= * VGM loading: working * Module loading: working * XSPF/JSPF: working, seems to use more RAM than I would like * Local files: working |
| ︙ |
Changes to src/audio-formats/flacfile.cr.
| ︙ | |||
24 25 26 27 28 29 30 | 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 | - - + + + - - + + + + + + + + + + + + |
# reading it from a file. The file can optionally be compressed with Gzip,
# Bzip2, or ZStandard.
class FlacFile < PlayableFile
@io : IO?
@flac : RAFlac::StreamedFlac?
@flacDec : RAFlac::StreamedDecoder?
|
| ︙ |
Changes to src/audio-formats/midifile.cr.
| ︙ | |||
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | 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 | + - - + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + |
#### Simple wrapper for MIDI files.
####
module Benben
class MidiFile < PlayableFile
class_getter! globalSoundfont : Haematite::SoundFont?
class_getter globalSoundfontPath : String = ""
@@globalSoundfontMut : Mutex = Mutex.new
getter! soundfont : Haematite::SoundFont?
getter soundfontPath : String = ""
getter! synth : Haematite::Synthesizer?
getter! seq : Haematite::Sequencer?
@file : Haematite::SequencedFile?
@arraypool : RemiLib::ArrayPool(Float64) = RemiLib::ArrayPool(Float64).new(0.0)
|
| ︙ | |||
92 93 94 95 96 97 98 | 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 | + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + - + - + + - - + - + - + |
if (sf = @soundfont).is_a?(Haematite::MmapSoundFont)
sf.close
end
@soundfont = Haematite::SoundFont.new(@soundfontPath)
end
end
def ensureFile : Bool
# KLUDGE: MIDI files are handled differently because of how SoundFonts are
# loaded. The ensureFile method loads only the MIDI file into RAM without
# creating a MIDI synthesizer.
#
# To actually ensure the file is in RAM and a synth is created, the
# ensureFileInRAM method is instead used, but only internally. This must
# be done after a SoundFont is loaded.
ensureMIDIFileInRAM
true
rescue err : Exception
{% if flag?(:benben_debug) %}
RemiLib.log.error("Cannot load MIDI #{@filename}: #{err}\nBacktrace:\n#{err.backtrace.join('\n')}")
{% else %}
RemiLib.log.error("Cannot load MIDI #{@filename}: #{err}")
{% end %}
false
end
|
Changes to src/audio-formats/modulefile.cr.
| ︙ | |||
26 27 28 29 30 31 32 | 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | - - + + + |
class ModuleFile < PlayableFile
alias Xmp = RemiXmp
@ctx : Xmp::Context = Xmp::Context.new
@loaded : Bool = false
@dtinfo : RemiXmp::ModuleInfo?
|
| ︙ | |||
76 77 78 79 80 81 82 | 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | - - + + + + + |
else
IO.copy(file, io)
end
end
io.to_slice
end
|
| ︙ | |||
121 122 123 124 125 126 127 128 129 130 | 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 | + - |
end
def volume=(value)
@ctx.volume = value
end
def unload : Nil
Benben.dlog!("Unloading module file: #{@filename}")
@dtinfo = nil
@ctx.unload if @loaded
@loaded = false
|
| ︙ |
Changes to src/audio-formats/mpeg1file.cr.
| ︙ | |||
20 21 22 23 24 25 26 | 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 | - - + + + - - + + + + + + + + + + |
#### Simple wrapper for MPEG-1 files.
####
module Benben
class Mpeg1File < PlayableFile
@decoder : RemiMpg123::Decoder?
|
| ︙ |
Changes to src/audio-formats/opusfile.cr.
| ︙ | |||
36 37 38 39 40 41 42 | 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | - - + + + |
@outputGain : Float32 = 0.0f32
@channels : UInt8 = 0u8
@tagPacket : Bytes = Bytes.new(0)
getter? needResampling : Bool = false
@sampleRate : UInt32 = 48000
@totalSamples : UInt64 = 0u64
|
| ︙ | |||
144 145 146 147 148 149 150 | 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 | - + + + + + |
# Opus at 48Khz then resample.
@needResampling = true
@sampleRate = 48000
Opus::Decoder.new(48000, 2)
end
end
|
| ︙ | |||
202 203 204 205 206 207 208 209 210 211 212 | 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 | + - |
def rewind : Nil
unload
ensureFile
end
def unload : Nil
Benben.dlog!("Unloading Opus file: #{@filename}")
@decoder = nil
@demuxer = nil
@io.try(&.close)
@io = nil
|
Changes to src/audio-formats/pcmfile.cr.
| ︙ | |||
19 20 21 22 23 24 25 | 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 | - - + + + - - + + + + + + + + + + |
#### Wrapper for PCM files (e.g. RIFF WAVE and Au files)
####
module Benben
class PcmFile < PlayableFile
@file : RemiAudio::Formats::AudioFile?
|
| ︙ |
Changes to src/audio-formats/playablefile.cr.
| ︙ | |||
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | 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 | + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + |
#### This program is distributed in the hope that it will be useful,
#### but WITHOUT ANY WARRANTY; without even the implied warranty of
#### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
#### Affero General Public License for more details.
####
#### You should have received a copy of the GNU Affero General Public License
#### along with this program. If not, see <https://www.gnu.org/licenses/>.
require "remixspf"
require "../taginfo"
####
#### Simple wrapper for MIDI files.
####
module Benben
abstract class PlayableFile
class PlayableFileError < BenbenError
end
# Where a `PlayableFile` comes from.
enum Source
# A local file.
Local
# A file that is downloaded over HTTP/HTTPS.
#Http
# A file that is downloaded over Gemini.
#Gemini
end
#getter source : Source = Source::Local
|
| ︙ | |||
45 46 47 48 49 50 51 | 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 | + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + |
else
@taginfo = TagInfo.create(self)
end
end
abstract def totalSamples : UInt64
def timeLength : Time::Span
if ret = @timeLength
ret
else
calcTimeLength
@timeLength.not_nil!
end
end
|
Changes to src/audio-formats/vgmfile.cr.
| ︙ | |||
19 20 21 22 23 24 25 | 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 | - + - - + + + - + - + - + + + + + + + + + + + + + + | #### #### Simple wrapper for VGM files. #### module Benben class VgmFile < PlayableFile |
| ︙ | |||
68 69 70 71 72 73 74 | 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 | + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + |
ensureFile
outputRateMul, outputRateDiv, _, _ = Yuno::VgmPlayer.calcResampling(Benben.config.sampleRate, @file.not_nil!)
@totalSamples = Yuno::VgmFile.vgmSampleToPcmSample(@file.not_nil!.header.totalSamples.to_i64!,
outputRateDiv.to_i64!,
outputRateMul.to_i64!).to_u64!
end
end
# Returns the total number of samples for each loop.
def samplesPerLoop : UInt64
if ret = @samplesPerLoop
ret
else
ensureFile
outputRateMul, outputRateDiv, _, _ = Yuno::VgmPlayer.calcResampling(Benben.config.sampleRate, @file.not_nil!)
@samplesPerLoop = Yuno::VgmFile.vgmSampleToPcmSample(@file.not_nil!.header.loopSamples.to_i64!,
outputRateDiv.to_i64!,
outputRateMul.to_i64!).to_u64!
|
Changes to src/audio-formats/vorbisfile.cr.
| ︙ | |||
32 33 34 35 36 37 38 | 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | - - + + + |
@decoder : Vorbis::Decoder?
@channels : UInt8 = 0u8
@tagPacket : Bytes = Bytes.new(0)
@sampleRate : UInt32 = 0u32
@totalSamples : UInt64 = 0u64
@mutex : Mutex = Mutex.new
|
| ︙ | |||
97 98 99 100 101 102 103 | 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 | - + + + + + |
demux.rewind
demux.nextPacket
demux.nextPacket
demux.nextPacket
end
end
|
| ︙ | |||
147 148 149 150 151 152 153 154 155 156 157 | 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 | + - |
def rewind : Nil
unload
ensureFile
end
def unload : Nil
Benben.dlog!("Unloading Vorbis file: #{@filename}")
@decoder = nil
@demuxer = nil
@io.try(&.close)
@io = nil
|
Changes to src/common.cr.
| ︙ | |||
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | 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 | + + + + + + + + + + + + + - - - - - - - - - - - - - |
# :nodoc:
macro dlog!(msg)
{% if flag?(:benben_debug) %}
RemiLib.log.dlog!({{msg}})
RemiLib.log.debugStream.flush
{% end %}
end
###
### Exceptions and Aliases
###
class BenbenError < Exception
end
alias RAFlac = RemiAudio::Codecs::FLAC
alias MVerb = RemiAudio::DSP::MVerb
alias Zita = RemiAudio::DSP::ZitaReverb
alias ReverbPreset = MVerb::Preset|Zita::Preset
alias ThemeColor = UInt8|Tuple(UInt8, UInt8, UInt8)|String
end
require "./audio-formats/modulefile"
require "./audio-formats/flacfile"
require "./audio-formats/opusfile"
require "./audio-formats/vorbisfile"
require "./audio-formats/mpeg1file"
require "./audio-formats/midifile"
require "./audio-formats/vgmfile"
require "./audio-formats/pcmfile"
####
#### Common Stuff and Globals
####
module Benben
|
| ︙ |
Changes to src/filemanager.cr.
| ︙ | |||
11 12 13 14 15 16 17 | 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 | - + - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - + + - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + - - - - - - - + + - - - - - - - - - - - + - - + + + + - - + + + - - + + - - - + + - - - - + + + + + + + - - + + - - - - - - - + + + + + + + + + + - - - - - - - + + + - - + - + - - - - - - - + + + + + + + + + + - - - - - - - - - + + + + + + + + + + - - - - - - + + + - - - + - - - - + + + + + + + + + - - - + + - - + + + - - - - - + + + + + + + + + - - + - - - - - + + | #### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU #### Affero General Public License for more details. #### #### You should have received a copy of the GNU Affero General Public License #### along with this program. If not, see <https://www.gnu.org/licenses/>. require "uri" require "./common" |
| ︙ | |||
474 475 476 477 478 479 480 | 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 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 | - + - + - + - - + + - - + + + + + + - + - + - + - - + + + - + - - |
#
# If the queue is set to repeat, and the `FileManager` is currently at the
# end of the queue, then it loops back and returns the first entry.
# Otherwise, if it is not set to repeat and it's at the end of the queue,
# this returns `nil`.
#
# This may load a file if it is not already in memory.
|
| ︙ |
Deleted src/loaders/gemini.cr.
| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
|
Deleted src/loaders/http.cr.
| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
|
Deleted src/loaders/normal.cr.
| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
|
Deleted src/loaders/xspf.cr.
| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
|
Changes to src/playermanager.cr.
| ︙ | |||
51 52 53 54 55 56 57 | 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 | - - - + + + - + - + - + - + - + - + - + - + + - + - + |
delegate loopIndefinitely, to: @player
delegate currentLoop, to: @player
delegate infoLine, to: @player
def initialize
end
|
| ︙ |
Changes to src/rendering/renderer.cr.
| ︙ | |||
144 145 146 147 148 149 150 | 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 | - + - - - - - - - - - - - - - - - - - - + - - |
jobs : Array(Job) = [] of Job
# Used to check for duplicate output filenames.
outputPaths : Hash(Path, Bool) = {} of Path => Bool
# Get each file
loop do
|
| ︙ | |||
214 215 216 217 218 219 220 | 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 | - - + + - + - + - + - + - + - + - + - - + + |
unless Benben.args["overwrite"].called?
RemiLib.log.error("File exists: #{filename}")
next
end
end
# All good, store the new job
|
| ︙ |