And folders of tracks, too! The only thing that worked in 3117 was
playlist files. Hah!
Fixes#436
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Files are now loaded to unique keys, and containers such as playlists
and CUE sheets maintain their file order. Deduplication now only applies
to top level files and not playlist contents. Sorting applies to top
level files, and playlist or container names, but not their contents.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This should fix an exception being thrown because the observer wasn't
registered, or known to be registered. Only register it when it will be
used, and only unregister it if it was registered.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Apparently, this doesn't work too well with real HDCD tracks, and causes
all sorts of weird volume issues. Just leave the volume alone, and let
HDCD decoding make tracks louder, possibly, rather than try to halve the
volume automatically on a detector that isn't terribly good.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
And disabled by default, at that. I can't actually hear the difference
of Peak Extension in the Rock track I have that claims to use it. And
Low Level Range Extension is more trouble than it's worth on tracks that
use it by mistake, or maliciously, if the case may be. I may add track
tag level control in the future.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Thanks to upstream VGMStream for fixing this in the Audacious plugin,
which I derived this code from in the first place, which explains the
memory leak getting in.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Raw DSD is counting frames in bytes, not bits/samples, so it needs to be
scaled up when dividing by the raw sample rate.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
It's regarded as unstable as some plugins randomly decide to overflow
the main thread queue and crash the player on the main thread check, but
only sometimes, and not always.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Apparently, this was preventing some signed plugins from being loaded
into the process, preventing their use as MIDI plugins. And this may be
needed for future AudioUnit DSP filter support, for third party plugins
there, as well.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Move the stack-based buffer, which is rather large, to the player class
instance, where it will be allocated on the heap.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Improve rendering functions of Audio Unit player, and also fix looping
for the Audio Unit player, and any other possible future players which
use blocked decoding with timestamped events.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Also hide the Apple plugins from settings so they don't get activated
unless there's no SoundFont configured.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
BASSMIDI: 2.4.15.3
BASSFLAC: 2.4.5.5
BASSOPUS: 2.4.3
BASSWV: 2.4.7.4
WavPack: 5.8.1
And updated the WavPack plugin to support threaded decoding, using up to
four worker threads, as detected from the host machine's CPU count.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Now using Accelerate methods to calculate and multiply ramps per channel
and add the remainder if necessary.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
If the current track has played for more than 5 seconds, previous track
now restarts the current track, instead of jumping back to the previous
track.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This code did not check the number of samples in a packet before adding
it to the output buffer, which apparently had the potential to cause the
output code to emit up to 512 samples of silence between tracks. This,
as one can guess, is a bad thing, and causes noticeable gapping between
tracks.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Output logging, a debugging feature that is only enabled at build time
if I need to chase down some audio mixing or output bug, was not logging
anything at all. Change to use Cocoa file writing methods, and actually
implement the output writer function again.
This code is left disabled 99% of the time anyway, and especially in
release builds. Like the node logging code elsewhere, it has the
potential to be very noisy and consume massive amounts of disk space.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This should be included, for safety purposes, in case the rounding up to
the nearest multiple of 256 samples doesn't bump the buffer size enough.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The streaming support was breaking because initial packet detection was
failing due to bit reservoir errors. Instead, detect consecutive sync
frames in the initial read buffer, then attempt to sync to a decodable
frame in the first block of data, otherwise give up.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Add missing HLS MIME type: audio/mpegurl
Update FFmpeg to version 7.1.1, carrying the same patches, and one new
patch: Implementing support for HLS ID3 tags changing mid-stream.
We cannot do away with fdk-aac yet, because the USAC codec is missing
features that fdk-aac implements already.
Fixes#428
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Move minimp3 packet decoder state into the decoder_ex state structure,
instead of using the redundant duplicate structure. Also reduce input
buffer size for streams to 16KiB, and actually use the defined macro in
the header file to declare the streaming buffer size.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Seeking should clear the sample buffer if it contains anything, and non-
seekable files should return an error on an attempt to seek.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
There were several issues which broke debug and possibly release
signing, and broke VGMStream in debug situations. Not sure if it was
also broken in release.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The double members should be ordered first so they are aligned to an 8
byte boundary. The rest are fine as-is.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
libMAD had memory safety issues, possibly with corrupt files. Hopefully,
this will fix the problem.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
These two visualization components, SceneKit and Core Graphics based,
only use the FFT data. So now make the request drop the PCM data.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The Visualization Manager PCM/FFT copy function was already observing
these parameters for null input and only returning output to the ones
which were not null. This just makes it clear that they are both
optional parameters. This is useful for future visualization adventures,
allowing PCM copy without invoking the FFT processing, or requesting FFT
without also having to keep the PCM.
This is mostly only a compile time change, and has no noticeable effect
on the current runtime behavior, as the only consumers of the Visualizer
data currently request both PCM and FFT.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This affects User Defaults, but only has any effect on ChunkLists which
are being used for conversion, and only if they're processing DSD source
material. Thus, the observer should only be added on the one stream that
is converting DSD, and should definitely be removed when the object is
deallocated.
This fixes a serious crash bug that mostly appears to only affect Intel
Macs, and has no major side effects on Apple Silicon that I can tell.
It's a good thing I still own an Intel Mac or two to test on, even if
they are both trapped on older releases of macOS.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Apparently I somehow didn't notice this situation because I still had
Rubber Band enabled, and existing users kept it enabled ever since I
introduced it.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Move this commonly used string decoding helper to the CogAudio framework
and import it in every plugin that uses it.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Apparently, stringWithUTF8String: just returns nil when the encoding is
not UTF-8, rather than throwing an exception.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Xcode really wants to add focusRingType="none" to everything now upon
opening with the editor, for some reason.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Now it handles multiple attached pictures and tries to pick out the one
which may be the front cover picture, or otherwise picks the first one.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Operation blocks cannot expect their out of scope variables to be
present when the block executes, so design the block operation to pull
inputs from a queue array one at a time, like the rest of the blocks do.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Clearly, NSUserDefaults bindings were not really meant to be used in
practice at all, as they do nothing but crash the app.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Change hotkey storage system, hopefully this will fix the stability
issues that have been plaguing it for a while now.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
MASShortcutView is apparently buggy on older macOS versions. So everyone
there gets hard coded shortcuts and nothing else.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The converter doesn't just require an output format call, it also
requires this input format change callback to actually signal it to
reopen the converter process with a new format setup.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Output format mostly requires stopping and restarting the output device,
and this also prevents us from using the latency function properly,
which apparently always returns 0 for output devices anyway. These
changes also prevent the output callback from hanging when resets occur.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
It turns out that initializing NSUserDefaultsController like this is a
really bad idea, especially on older versions of macOS. This is probably
also why the equalizer was crashing for people on first activation.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Properly support translating the System Default Device name for sound
output devices. Pending a Spanish translation, but in its current state,
it's no different from where it was before this change.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Fix default output device logging, and also the preferences if no
default device happens to be set.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Fixes visualization latency under virtual machines, at least. Not sure
which local or native systems would be reporting high latency here, but
this should fix them as well.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Move the DSPs to the output node, so they don't get closed and reopened
across each file. Also restructure the output handler to buffer a little
on its own, to account for track switch activity.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The filter uses a pre-buffer of input audio, so extrapolate from the
actual input to fill the buffer. Fixes clicking on non-zero-crossing
track endings.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Buffers were being treated as empty before they were actually processed,
due to races between the current node's end of stream marker and
actually feeding the output buffer.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Pitch and tempo weren't snapping to exactly 1.0 before, as a result of
various things. This fixes that.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This optional code, disabled at compile time by default, allows finding
weird issues with the sample decoding chain.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Hopefully this works for most ASCII and UTF-8 tags, and continues to
work for weird tag encodings.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Option to make selection follow the playback, within the lag of the
output buffer, including if Always Stop After Current or Repeat One is
enabled. Allows easily queueing up a list of tracks in Always Stop mode,
then hitting the Play button again to play the next track. Enabled by
default, but always optional to disable.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
A new menu option under the Control menu, disabled by default, which
stops playback after the current track completes.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Apparently, this isn't needed, and on two users reporting crashes,
actually causes exceptions to be thrown somewhere.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This required some minor workarounds to deal with the play time counting
that works toward play count reporting.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This was attempting to retrieve the NSURL host object, possibly on a
file URL where the two did not match a previous check. Now we only pass
the full scheme/host/path check if both URLs are not file URLs.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Perform the file container checks in an operation queue, since those are
a major bottleneck at this point, too.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Playlist Loader was sorting only the non-container tracks, and not the
final track list. Move the sort operation to the end of the processing.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
There is a race condition with the next Node in the chain and the End of
Stream marker, considering how tiny the buffering is for these DSPs. Set
End of Stream instead after inserting the end of stream flush chunk.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
DSPs should not be performing a cascading reset when resetting just
their own buffers, for example, on init or shutdown of just that one
DSP filter.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Improve handling where FFmpeg may call the provided file reader with
AVSEEK_SIZE repeatedly, when file size is not likely to change between
repeated calls. This prevents repeated seek operations that would
otherwise be required to probe the file size each time.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Add event traces to playlist loading and metadata processing queues.
Unfortunately, most of the old non-error events should not be logged,
because Sentry gets terribly spammy with captureMessage events. They
should only be used for error events, or other uncommon events which
do not already throw exceptions or NSError objects.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Enable processor usage profiling for the app to gather information for
potential bottleneck tracking.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Cleaned up project settings to current defaults, except for the macOS
deployment version, which is still 10.13. Cleaned up a lot of headers
and such to include with angle braces instead of double quotes. Enabled
build sandbox in a lot of places. Disabled subproject signing in several
places, for libraries and frameworks which will be stripped and signed
when they are copied into place in the final build.
Also, while trying to solve compilation issues, the visualization
controller was reverted to the Objective C implementation, which is
probably faster anyway. Stupid Swift/Objective-C language mixing issues.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Seeking should clear the buffers completely now, and will be nearly
instant, depending on how fast the input can decode.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This includes setting and unsetting the equalizer DSP chain objects on
track change and advancing on track playback end, and also bugs with
applying equalizer presets to the band configuration items when the
equalizer is disabled or when playback is stopped.
Fixes#420
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Seeking now mutes properly, and will not leave the audio muted across
other operations. Audio output changes should also mute and destroy the
buffers of the input chain, so that the audio resets properly.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This should not interact with the Audio Player object on a background
thread, but instead the main thread queue.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Fixes output volume setting on seek or audio output restart on format
change. Also safeguards these setters so they don't go off if the nodes
aren't actually allocated.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Two playback event items were set to queue a playback start to a
background thread, when playback should instead be queued on the main
thread. Fix this in a simple way.
This crash was easily reproducible by skipping through tracks rapidly.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Sometimes the play count data only includes the filenames, and thus will
fail a query for just the tags. Also, a file query may be stored without
the subsong fragment tag, which will also break the tags.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Play Count sorting was entirely missing, and sample rate and bits per
sample sorting caused exceptions due to the capitalization of the fields
versus the column identifiers.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The TagLib framework build process leaves several
key fields empty. This breaks App Store submission.
Fix it again. Dang.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Remove deprecated functions, make use of free functions that clear the
pointers before returning, etc.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Remove deprecated functions, make use of free functions that clear the
pointers before returning, etc.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
When adding tracks to the playlist, clear the search filter first, so
the playlist doesn't become all jumbled, or so we don't overflow the
playlist indexes.
Also add some bug fixes for reversing the arranged to disarranged index
lists, so if an arranged index is past the end of the arranged list, as
is the case for appending, we shift the indexes forward past the end of
the diarranged object list.
Extra exception handling was added as well, so these things will only
cause a failure to add playlist items at worst, instead of crashing the
player entirely.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Update the readers to support the newly added tag fields, and also read
the supported format list from the library itself.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Now buffer twice as much audio as would be requested for a single
visualization PCM/FFT chunk, which should hopefully prevent it from
flickering due to running out of audio because of too low latency.
Now it buffers up to two chunks at the current hard coded visualization
sample rate, which works out to about 186 milliseconds.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
We implement this function to return the current latency buffered,
regardless of how often this function may be called. In practice, it is
only called on track completion, to time the reporting of the next track
display. We also avoid using Rubber Band's latency function, as in most
cases, this function will be called from other threads, and also, it
currently only gets called after Rubber Band has been emptied out, so it
would otherwise calculate zero samples buffered. And thirdly, Rubber
Band's latency function doesn't account for the buffered samples already
removed from it and waiting to be fed out.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The code was polling the input chunk duration after emptying out the
chunk's samples, which resulted in an input duration account sitting at
exactly zero, so the end overrun flush would not be cut short properly,
resulting in gaps between tracks.
Correct the input sum to tabulate before emptying the input chunk, so
output remains properly gapless.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
In case playlist setup is reset or not, move the reset above the menu
setup code, so the menu is set up correctly if a reset occurs.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Reset to defaults if no columns are visible. Also log this situation in
Firebase events, in case it becomes relevant.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This code was being duplicated across three different playback functions
which basically did most of the same things.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Check all audio chain elements for allocation failures, and also dispose
of all of the previous handles in reverse order, including nulling the
final node handle so the output does not attempt to poll for audio while
the chain is being rebuilt.
Also set up output node to handle the new null finalNode state, and
return an empty chunk to the caller.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Play Count cannot be updated for tracks which have been deleted before
the update was added to them. This was another cause of a rare crash.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
We should not be processing a potential playback restart when the chain
is being torn down for shutdown.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This should be perfectly safe to use in all situations now. It may have
been unstable due to mishandling return values, or not supporting
requesting more sample data from the library without feeding in more
input first.
Also, still signaling the End of Stream flag on chunk reading should be
correct, as downstream processors only react to it when the buffer runs
empty.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The Downmixer wasn't updating its output format correctly, so it was
prone to outputting the wrong format for a while, which could confuse
the output device and produce garbage output.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The delay value should be scaled by the resampling ratio, similar to
how it already is when allocating the impulse buffer. This went
undetected, as it scribbled over other memory without causing immediate
crashes, but instead later heap corruption.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Check for paused processing state in various places, so that startup
playback works properly, and resume playback at seek offset works
properly and doesn't hang the player.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The samples available function returns a signed integer, so it can
apparently return negative on error, and the DSP was incorrectly casting
this to an unsigned type, and thus attempting to buffer an inordinate
number of samples and crashing.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The merge function should be able to tell when the caller has no audio
left to process, such as on end of stream.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
FreeSurround needs more buffering from its input, so increase buffering
of previous node to 100ms.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Fixes timestamps in several cases where they were being processed
incorrectly, which was causing some chunked audio files to mis-report
timestamps into the past or the future, which caused the seekbar to jump
around in an unpredictable way.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Stream timestamps were correctly being converted from the monotonically
increasing frame count, but the AudioChunk parameter was being set from
the frame count rather than the converted seconds count.
Fixes#418
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Timed wait for 500us is kind of stupid and makes the threads wake up way
too much, and use way more CPU time. Reduce this, as the semaphores are
signaled appropriately, and the waiter should not wake up constantly.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Visualization now buffers in the audio output pipeline, and uses a
container system to delay multiple buffer chains from emitting
visualization data over top of each other. This should stabilize
display output significantly, while introducing minimal lag before
DSP configuration changes take effect.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The latency should not be incremented when writing sample data to the
buffer, but rather be posted by the output.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Upstream functions which return empty chunks on error do not return nil,
so the caller should check for an empty duration instead.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Impulses should be gain scaled roughly based on the sample ratio
relative to the original impulses. Lower target sample rate means less
impulses means gain goes up, higher target sample rate means more
impulses so gain goes down. Somewhat simple, seems to work.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
We were forcing a resampling ratio to match the HRTF filter supplied
with the app, now we resample the HRTF to match the input audio, which
will be resampled to match the output device settings.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This prepares the filter to be the same as the rest of the filters, in
that they support flexible sample rates to match the output device.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
And disable it by default in new installations, otherwise leave the
setting alone. The disablement setting is shared with the engine
setting, so the default should not really change anything, except for
new installs.
Also, the time/pitch shifting dialog disables itself and displays an
obvious notice button, which opens the Rubber Band settings.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
These should have been defined already, but now they're the safe
defaults that should spring the dialog on startup, and doesn't grant
consent by default.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
It's more like the output monitor thread, since it only monitors output,
rather than actually handing the output callbacks.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Sample block merging code should not be duplicated across the DSPs that
require it, but instead should be a common function. Also added some
optimizations to the Float32 converter function, to bypass conversion if
the audio format needs no conversion.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Attempt to completely fill the input buffer of the Rubber Band library
between each call to the process function, instead of processing in
as small an increment as the source node provides. May reduce processing
power required.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Audio Chunks now have full timestamp accounting, including DSP playback
speed ratio for the one DSP that can change play ratio, Rubber Band.
Inputs which support looping and actually reporting the absolute play
position now do so.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
In case multiple playlist entries are left marked as "current" in the
playlist database, resume playback on the first one, and unmark all the
rest of them.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
FreeSurround, like the Equalizer, which attempt to coalesce Audio Chunks
into larger blocks of 4096 samples, must check if the audio format has
changed between blocks, and stop stacking chunks together when a new
format is detected. They will continue processing with less sample data
than expected, as necessary.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The last of the built-in processors is now in the threaded processing
chain, and all DSPs are marked high priority and with short buffers.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Change one remaining semaphore wait to 500us, and change the buffering
so that it can always overflow the requested duration by one chunk, so
that at least one chunk will always fit in the buffer. This also allows
the DSP nodes to flush at the end of the stream without losing their
output.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The end of stream flushing should only request remaining samples once,
as should the rest of the process. The problem with the Rubber Band code
in this case is that it will wrap the remaining samples pointer after it
has been flushed, and emit a really huge number.
Also, add code to try to equalize the samples output with the samples
input, relative to the tempo stretching, as Rubber Band seems to flush
entirely too much data at end of stream, which can create noticeable
gaps in the output. This solves that as well.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This should be guarded, so that no other thread tries to free the DSP
while it is potentially writing to the Rubber Band instance.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This comment was copied by accident when duplicating the original
Converter Node class for the new DSP base.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
DSP threads, such as the Rubber Band processing, and planned moves of
other processing to buffer threads, such as the Equalizer, FreeSurround,
HRTF, and Downmixing for output, because they all have small output
buffers. Since these buffers drain and fill fast, they should be
processed at a high priority. Hopefully, App Store doesn't complain
about the use of these APIs.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The items not applicable to Finer / R3 engine were not being disabled
properly. Change the dialog to use a transformer to disable them on the
preferences value instead of coding it, since the code didn't seem to
work.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This class can more flexibly process and emit varying chunk sizes than
the previous code could, solving the problem of wide tempo changes.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Now there's a configuration dialog for tweaking the settings
in semi-real time. Everything that can be changed without
restarting is changed without restarting, otherwise the audio
pipeline is reset, which happens quickly enough anyway.
Awaiting translation to Spanish, other languages have been
removed pending their maintainers fixing most of their
problems, which includes me being lazy and AI translating
bits so I could rush updates.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The Polish, Russian, and Turkish translations have
no active maintainers, so I was stupidly relying on
AI translation to fill in the newer things. These
translations will sit mostly idle until I get active
maintainers for them.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This should improve performance slightly. It's
still recommended to switch off SceneKit to
save CPU usage, or switch of vis entirely.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Gah, how in heck did Xcode end up inserting an absolute
path? Fix that, and some other leftovers.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The TagLib framework build process leaves several
key fields empty. This breaks App Store submission.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Make exception handling more robust and thorough. Never
know what may happen, make sure to handle most cases.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Both the midi_processing and the various players may
throw exceptions, so we should check for these too.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
SSEQPlayer throws exceptions, there should be exception
handling to catch them and fail gracefully.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The TagLib C++ code was missing generic try/catch handling
which could result in any generic errors throwing straight
to a full crash. Add exception handling and logging, which
will fix a logged crash regardless of whether the tags are
read correctly or not by the newer TagLib version.
Fixes#415
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
You will need to reset your settings after this, but then it should
stay put for the indefinite future.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Due to a race condition with the visualization control racing with
the Crashlytics consent dialog, it was possible that the repaint
function would be called before the control was fully initialized,
which would cause the visualization drawing code to crash due to
division by zero error.
The fix is two-fold: First guards were added to the borrowed
code so that the draw functions won't run if they would later
divide by zero on an uninitialized width property. Secondly, the
top level visualization windows added a startup variable guard
so their drawing code will return immediately if setup has not
completed yet.
Note that this bug was only just noticed in a recent App Store
submission, but was unrelated to the recent commits to the code
base, and could have triggered much earlier in the development
cycle. Strangely, it did not.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
It should also be possible to sort by the column, ascending or
descending. This also necessitated adding playlist row refreshing
for play count updates.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
In the event of local paths containing not just UTF-8 characters,
but also un-decoded URL percent sequences, which will end up double
encoded in the player, code which reverses percent encoding should
later re-apply it.
Apparently, this whole time, since the last code overhaul, the
URL encoding was being stripped, then the file opener was converting
these paths back into URLs without re-encoding, which didn't break
until someone played an album in a folder containing a partially
decoded UTF-8 sequence. Thanks, Zophar's Domain, and whoever ripped
the Golden Sun GSF set for finding this bug!
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
When the input buffer has less samples in it than the LPC order,
it would crash reaching past the ends of the buffer. Now, it will
pad past the correct end of the audio with silence, while still
extrapolating a prime input minimum of the LPC order. Should fix
the last of the outstanding crashes.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The NSCalendar assignment should have a placeholder month and day
of January 1st, instead of the invalid month/day of 0/0. Also,
even if this somehow fails, don't attempt to assign it if it
returns nil.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Since in one case, it probably wasn't combining them into one stack
allocation, it probably blew up the stack allocation quite a bit.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
I will implement the more complex setup of providing options for
most of the configuration that Rubber Band provides, at a later
date, when I feel like creating a complex configuration dialog
for it, and asking for help translating every option and setting.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
mpan told me these were broken, oops. One of them
may as well not be translated until it gets a proper
translation.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The emoji labeled buttons will convert and save their respective
state icon to the settings folder, and refresh the current icon
as necessary.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
It should be deriving its channel count from the file format,
since it's applied before any other filters.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Implements a simple speed control using a resampler
designed for real time changes. A rubberband speed
control will be implemented at a later date.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Change to the future render api, hopefully float support
will be available eventually. Also change to allocate the
sample buffers from the heap instead of the stack.
Version 11.0 requires macOS 10.15, and I haven't raised the minimum
deployment version that far yet.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Volume scaling would potentially crash when handling
unaligned blocks of samples, and also handled them
completely wrong. It should be counting up single
samples until the buffer is aligned to a multiple of 16
bytes, and it should not exceed the intended count.
BUG: It was not only counting the unaligned samples
backwards, it was ignoring the real sample count.
Fixes#380
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Shuffle around @autoreleasepool blocks, and also add one
to the audio processing code in the playback callback, so
audio memory is released during playback instead of
accumulating.
Fixes#379
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This appears to maybe be necessary as the prior join call doesn't seem to
be doing what it should.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Switch the CI image to the latest stable OS version, and latest stable
Xcode version, selected by another action.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This is checked inside the audio thread, it isn't needed in the watcher
thread. Remove the second check.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Spanish translation provided by Kevin López Brante.
Polish, Russian, and Turkish translations of specifically these messages
provided by GPT-4, to be replaced by human translations if our
translators offer them, but it's been a while since I've gotten an update
out and I didn't really want to wait so long.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Adjust the buffering so if latency is too low, we fill the rest of
the output with silence instead of peeking at the oldest part
of the buffer. Also increase latency by half a buffer size so
that the requested sample is in the center of the buffer, which
improves the 4096 sample situation with the current low
latency output.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Buffer up to 20 seconds per stage, and buffer only up
to 2 seconds before starting the next stage.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
A stopped instance of OutputCoreAudio should not continue to feed the
visualization system with stale audio, potentially while another instance
is already starting up and feeding its own audio output.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
These strings were added to the InfoPlist translations in a
previous commit, but likely need to be added to the
Info.plist file directly as well.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This reverts usage of the AVFoundation output to use
the previous lower latency CoreAudio output, and
paves the way for a change I am cooking up soon.
Fixes several issues with playback and seeking latency.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Do this by serializing the background thread actions against
the AudioPlayer object, so we don't start playback multiple
times at once.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The other translations currently have placeholders, awaiting translation.
I may end up using machine translation from Deepl just for Russian,
Polish, and Turkish, until I get human translations from a contributor.
Spanish will be provided by our team later tonight.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Perform playback start and seeking operations in the background, instead
of on the main thread, which should help prevent them from stalling the
user interface.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
These column header names were missing from the strings
tables. Add them based on existing translations of the same
field names by our translators.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Default repeat mode should now be Repeat All, and the menu items should
now all function, fixed by removing a bunch of pointless attributes from
each affected menu item.
Fixes#371
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This output may prove to have lower latency, but the results are too
glitchy to really be usable. Not even visualization latency is handled
correctly.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This is imported by the player, though it doesn't fail when it's
missing, so that would explain why I didn't spot this error sooner.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
They'll be imported by the plugin on startup anyway, and they don't
really have any exported functions we can use.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Correctly scale the AudioChunk frame counts. This more and more makes me
think I should be scaling this in the AudioChunk code instead, but then
code may not know about the special case of every 8 frames only being
one byte per channel.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
DSD wasn't tracking the correct sample count, because DSD
Audio Chunks store the byte count, rather than the bit count.
This may be changed in the future, so I'll have to remember.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
And default it to disabled. As was pointed out to me by a user, DSD is
apparently mastered to a level of -6 dB, so double its level on output
by default.
Also reorder all preferences dialog controls so they are instantiated in
display order, which should help screen readers, maybe.
Fixes#368
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Resampler flush may indefinitely produce 1 sample if there is a rounding
error with the buffering calculations. Work around this.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
When the clipped sample rate changes, the resampler needs to be
restarted. This was previously failing because the target sample rate
wasn't changing.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
When reading partial chunks, and when returning partial data, it is
essential to maintain this lossless chunk status across either whole or
partial chunk reads. Otherwise, the converter chain sees the lossless
flag constantly changing on lossless files, such as PCM or DSD, and
causes the DSD decimator and/or resampler to be torn down and reset
repeatedly, causing glitches in the audio.
The glitch was not, in fact, with the decimator itself, and was
occurring to a degree without it, as it would be restarting the
resampler repeatedly as well.
Fixes#367
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The latency is half of the FIFO, or half the filter size, and each byte
is 8 samples, so return the value accordingly.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This comment was in the original sample decimator code, I neglected to
include it in my port over to Cog. Doesn't really serve any functional
change, though. It would have clarified that I needed to reduce the gain
level much sooner, though.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Instead of clear playlist and play. This was confusing people,
apparently. I should have changed it sooner, since this is what
I use normally anyway.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Defaulting to ctrl-cmd-O, though I may change this if
someone has any better ideas for a default.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Also included missing BASS_MPC, which was still being imported
even though it wasn't actually included.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Makes volume slider logarithmic when limited to 100% to allow easier changing of volume towards the bottom of the slider.
The tooltip remains as the slider location instead of the logarithmic value of the actual volume.
Only track new, removed, or renamed files. Tracking Xattr changes was
apparently causing the tracker dialog to crash on things like the user
changing file type associations, which either added or removed a per-
file association xattr, or when clicking Change All, removed this xattr
from all associated files tracked by Spotlight.
Fixes#361
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
AppleScript is apparently such a legacy system, that when it sends URLs
to your app to open, they're in the old Carbon format. So we need to
translate these to proper URL strings for the rest of the app to deal
with them at all.
The format of these URLs is as follows:
/method/::
Followed optionally by:
username/password@
Where the slash and password are optional.
Followed by:
hostname
Followed optionally by:
/portnumber
And finally, followed by:
:path:on:server:filename.ext
So, in hostname field, we must swap slashes to colons. And in the path
field, swap colons to slashes. What a bizarre world.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
If transfer completes quickly, do not hang waiting for it to achieve
reading state. Also add some comments indicating what we're doing.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Merge the existing metadata entry dictionary with new values, because
sometimes, the caller may pass us a dictionary with some fields missing.
Fixes stream metadata for many HTTP streams.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
* Adds decimal digits to volume slider tooltip
Modifies the volume slider tooltip so that:
-If the volume slider falls below 10%, the volume tooltip will display one decimal digit of precision (e.g. 3.4%).
-Else if the volume slider falls below 1%, display one decimal digit of precision (e.g. 0.34%).
-Otherwise display the volume slider tooltip as normal.
This helps show changes in volume between 0% and 10% where a change in volume isn't shown in the UI but is heard (especially when the "Limit volume control to 100%" option is unchecked in the "Output" Preferences submenu.
* Update VolumeSlider.m
Fix variable declaration
---------
Co-authored-by: Christopher Snowhill <chris@kode54.net>
Add item to strings tables for translations of the menu item. English is
already done as the base language, awaiting Spanish at least, will await
Polish and Russian when the respective translators get to it.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Repair the SceneKit container definition in the Xcode project file, so
that the Visualization scene gets copied properly on project build.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This change had several components. For one, the delay of the dispatch
was increased from 5 milliseconds to 50 milliseconds. Two, the post to
the notification center was included in the delayed dispatch, so that
retains the PlaylistEntry object. Finally, the playlistController's
currentEntry object is reassigned from the input PlaylistEntry object,
which facilitates all watchers which are observing that variable for
updates. This final step also retains self for the callback, which
should be fine, since it's a quick dispatch with a short delay.
Fixes#335
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Input thread now signals when it has stopped and is about to return, in
case the input thread returns before the BufferChain dealloc function
would be waiting for it to terminate. Somehow, even though the Semaphore
is being signaled at this point, the BufferChain still ends up waiting
the default of 2.5 seconds for the signal that apparently never comes,
delaying file stoppage. This prevents the wait action entirely. Must
have been some sort of race condition.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This new method should cause all stops to default to immediate stoppage,
and only stops that occur after an end of track signal should indicate
to play out the entire buffer.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This should not really be necessary for proper player operation any
longer, and can safely be removed.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Several actions have been reworked to be non-blocking, as their
operation should still occur in the main thread, but should not block
the thread they are called from, as they are not required to continue
processing there.
End of secure access has also been made non-blocking, as it is usually
only called when an input is done accessing a given file or folder, so
it should be important to return quickly, as the input is likely about
to terminate, and other things are waiting for it to return.
Also remove a nested block call for the storage access, as it is within
an existing serializing block, so it shouldn't need to be nested.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Based on the C++11 code by Joel Yliluoma / bisqwit, which in turn is
based on information from NX-Engine. I have also taken the liberty of
bundling the required wavetable bank and PixTone drums. Contrary to the
documentation provided with the code, my version of dou_1006.zip, as
downloaded over a decade ago, had the wavetable bank at offset 635,816
bytes into the file, not 1,115,748 bytes. Possibly a difference of
having applied the translation patch? My copy is the original version,
so I had to use a real resource parser to locate the waveforms.
The player will obey the configured sample rate, loop count, and fade
time for synthesizers, and also obey Repeat One to play indefinitely.
The code should be quite robust to minor abuses, though I can't imagine
how well it would hold up to random bad files, other than playing
outright garbage.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Releasing sandbox access was incorrectly synchronizing on the object,
but still running code in the calling thread. It has been updated to
match the rest of the interface, which serializes all access through the
main thread only. This should prevent the sandbox from carrying stale
handles to already-released objects.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Must always remember to have xcode-select set to Xcode.app and not
the Command Line Tools when archiving the app myself, as otherwise
Xcode will fail to package the SceneKit objects into the resulting
bundle.
The code which looked up Sandbox handles for a given path had a bug
where it would re-add the handle to the in-memory cache storage even if
it already had just retrieved the current handle from the cache. I hope
this will fix the crashes which have been plaguing people adding a lot
of files to the playlist all at once from a single folder.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Update from 0e34925..fd7da37, with the following changes:
- C140: simplify update loop, add unbanked mode
- It resembles MAME's code more closely now.
- OKIM6258: make more tolerant against late writes
- enforce "discrete YM3438" mode for YM3438 VGMs
- Update emu2413 to v1.5.9
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Change upload script to use curl to upload to Bunny. The access
key is stored in the system keychain, with confirmation on access.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Remove shell script that was modifying the import path of a framework,
as we are no longer using libvorbis like that.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Add display name and category fields to project. Thanks, Apple, for
adding those to Xcode all of a sudden.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Synchronize with dispatches to the main thread instead of using
synchronization primitives. This prevents the main thread from
hanging another thread as a result of other threads entering the
sync block, then dispatching a callback to the main thread, which
also tries to lock on the sync block.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
All concurrency from other threads should pass through the viewContext's
performBlock or performBlockAndWait functions, and no other way. So now,
all access to Core Data is either happening on the main thread, or by
using these code blocks, all of which will wait for their access to
proceed.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This should fix some potential initialization errors it may have had
before, but this doesn't fix the broken Sound Canvas VA plugin. Roland
says it's supposed to be broken on macOS 12+ and/or Apple silicon
anyway, so I guess there's no dodging that.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This is needed to re-parent the VolumeSlider window, as there is only a
single VolumeSlider, but two different VolumeButtons and their
respective NSPopover windows. So, always recreate the view on open,
which doesn't appear to have a noticeable impact on performance.
Fixes#331
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
It was referencing the old SpectrumView class, when it should have been
referencing the safe SpectrumViewCG class, which will software render a
single frame of spectrum data when the customizing dialog is opened.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This was crashing trying to assign a nil CFStringRef from mystery audio
devices to the NSString passed to the enumerate block function, which
was predictably crashing. Ignore such devices instead.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
External artwork already supported the HEIC format, just not the correct
filename extension for the format.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Tag reading can read cue sheets as either a single NSString, or an
NSArray of NSStrings, so handle either case.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Stop visualization processing when the host window is completely
occluded, thus reducing background CPU usage levels significantly
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This should fix up potential locking issues with maintaining a copy of
the results set while certain other background actions may happen, such
as the player updating play counts while playing.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Updated:
- libFLAC from 1.3.3-235-g772efde6 to 1.4.1
- libvgm from 001ca75 to 0e34925
- libid3tag from 0.16.1 with patch to 0.16.2
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This magically fixes the stupid header maps that were pulling the system
semaphore.h into Swift projects, when they shouldn't have been doing
that in the first place. This is the same reason that the FLAC library
has its assert.h renamed to FLAC_assert.h.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
And this is the actual meat of getting it to work properly, the changes
the Swift code needed to actually be fully functional.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
These imports needed to be changed so that Swift bridging didn't import
the system's semaphore.h instead of CogAudio's Semaphore.h, which is a
completely different thing.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
There has been an API in GME to detect tracks ending for quite some time
now, and this just adds a little bit to the existing comment, which
previously noted that there was no way to detect if a track had ended,
which may have been true several major versions of GME long past.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The output has been assigning twice as many samples as it was supposed
to ever since commit 8d851e5bda, which
ended up generating the correct 1024 samples (2048 per GME parameter),
but assigned 2048 to the AudioChunk, which resulted in over-reading the
audio buffer, and thankfully not crashing, but instead causing an awful
sound distortion effect as random memory contents were played as PCM
audio.
Fixes#320
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Allow .mp3 and such to fall back to the FFmpeg container handler, in
case there are chapters in a renamed file.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The input isn't supposed to close its own sources, as it did not open
them itself, and they should be cleaned up automatically when they are
released to zero reference count.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Let the FFmpeg decoder handle RIFF files, if they happen to be named
.mp3 and not something like .wav.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This fixes the update URL and parameter handling. Seems there
was an extraneous newline returned by the security command.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Fixed RAD2 files referencing instruments not present in the
file, which caused the player to reference uninitialized memory
and usually crash.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The SID builder needs a static initializer, otherwise multiple instances
created simultaneously, such as during populating info on adding a lot
of tracks, will race and crash the player.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
CUEs will now deduplicate playlist entries based on their dependencies,
and prevent loading redundant tracks if you add an entire directory, or
use the option to add a directory when adding single files from it.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The subdirectory parser, the CUEsheet reader, and the legacy XML
playlist reader were missing grants for Sandbox access.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Clarified the button name to "Open", which is what the button actually
says, not "OK". Also used double quotes around the other button name.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Clean up redundant paths automatically, and on startup. Also refresh the
preferences dialog path list every time it is opened.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Deduplicate loaded tracks, to prevent duplicate items when adding a
folder that happens to contain playlists or CUE sheets referencing the
very same files.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Newly added paths weren't adding all of the necessary data to the list
storage to make it possible to remove them without restarting the
player. Oops.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Added a warning dialog to notify the user of the purpose of the add
folder dialog that will pop up after it. Otherwise, they may get the
idea that the dialog is a glitch and should be cancelled.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Only ask permission for container folders if the container has local
files, and not for purely remote files, such as stream playlists.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Buffer up to 5 milliseconds of audio, or at minimum 1024 samples, each
call. Also pre-allocate the buffer, rather than using a stack buffer.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This is an unnecessary step, and results in the offset being off by the
duration of the first pre-read block. This is incorrect.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The Vorbis, Opus, MAD MPEG, and especially the FFmpeg inputs needed to
have their metadata update intervals severely reduced, to reduce CPU
usage, especially on files with lots of tags. Interval reduced to only
once per second.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Oops, this compare blunder resulted in DSD decimation breaking every
1024 samples or so, owing to block sizes, and caused ticking sounds as a
result. It would also cause HDCD decoding to break completely.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Neither of these two changes is really important, but they do simplify
things, and the division on that one function makes the non-decimating
DSD support actually functional, as the caller expects a specific number
of samples, and that was otherwise octupling the input sample count.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Another large stack buffer was at play here. Consolidated it into an
existing buffer that can perform double duty here, since neither place
it's used conflicts with each other.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
It already supported reading the CUESHEET metadata block, but I managed
to break reading and processing CUESHEET Vorbis comments, which broke
CUE tagging, as well as files that didn't have both tags.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Playlist View pasteboard copier function should only be generating URLs,
and it should verify that the entry has a valid URL to begin with.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
In case the current track isn't part of an album, or is otherwise not
matching any albums in the playlist. Though the Album filter predicate
wasn't working for a while due to changes.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Only unregister the listener if it actually has been registered, and
clear the handle upon doing so.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The local and seekable file scanner could crash on bad MPEG files if
they failed to decode any frames and broke due to either end of file or
other unrecoverable errors, due to a division by zero error attempting
to calculate the file bitrate. Now correctly return error state if this
occurs, bailing early.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Apparently we need this to prevent Core Data from stomping on itself
when another thread accesses it.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Apparently, the autotools package uses a different versioning scheme
than the CMake build. Also rebuilt and re-versioned libvorbis and
libvorbisfile.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Sample rate changes will now occur on exact sample boundaries, like they
are supposed to. Also, FreeSurround accounts for its output latency.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
It was previously crashing horribly on adding search results. This makes
it actually functional, and renders it using a view-based table instead.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The DSPs should not be deinitialized from another thread, possibly while
they are currently processing.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Apparently, all these new changes with FreeSurround have pushed the
default 512KB thread stack size to the limit. And I'm not even using
stack variables, really, except for maybe the autoreleasepools.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Apparently, the LFE channel is not being initialized at all if bass
redirection isn't enabled, and even if it is, it's uninitialized for a
great portion of the spectrum. Clear it all on every iteration.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The output implementation has a block size of 4096, so the class
implementation should also use that.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This is the code that actually needs to be added to make it process
audio. This insertion makes the whole app crash when processing audio at
all. Weirdly, simply reverting these two files makes the audio code work
again. I can't explain it.
Also, commenting out CMAudioFormatDescriptionCreate makes it work, too.
There's something weird going on with that function.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This is a working implementation of FreeSurround, but I can't get it to
work in the Cog code base, as the whole project crashes head over heels
if this code is inserted into the output chain.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Move the Float32 converter to a different location, for any future plans
to support decoding audio files to common data for any other purpose.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This should be more correct, especially considering that the library can
handle 32 bit files now.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Apparently, the decoder is capable of returning zero length frames
without having hit the end of the stream.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Now the Preferences panels are 110 points wider, and most things are
shifted around in ways to make the current set of translations fit into
the dialogs.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Please do not translate the token names, they are used by the code to
look up which value to insert into the string.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The MainMenu.strings file had several mistyped quotation marks, and
several strings outside of quotation marks or comments, breaking the
menu translation entirely. This makes the translation actually work.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Insertions which occur when the playlist is filtered can try to add past
the end of the playlist. Let's try to dodge that.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
- Updated libFLAC to the latest Git commit, post 1.3.4.
- Updated libid3tag to 0.16.1.
- Updated libopus to the latest Git commit.
- Updated my FFmpeg libfdk-aac patch. Previously was overwriting
memory when it was supposed to be skipping samples.
Also added debug versions of several of the libraries, and changed
the library extractor script to unpack the debug libraries over the
release set to add the particular matching debug versions when
building a debug build.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Due to a change designed to stop playback when the end of the file is
reached, which should not be checked for unseekable files, which are
web streams that only stop when the connection drops, or when the user
stops playback manually.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The reader was previously returning a failure state on open if the read
completed and fit entirely into the read buffer, which broke most remote
M3U or PLS playlists.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Only pop up the path suggester and check on local file URLs, not remote
URLs, which shouldn't be checked, since they don't require sandbox
permission grants or bookmarks.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Oops, I should have remembered that the data structure changes would
break this search predicate. Now apply the search predicate to the
playlist representation, which allows searching against the data blocks
using the PlaylistEntry property implementation.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The declarations for the translation were missing from the project files
so that it wasn't being used. Also added the missing strings to the
files that were already added to the translation.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This should also seal up any potential hole for problems if there's an
audio format change and no audio buffered.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The input chain could hang up indefinitely, and MAD decoder didn't
indicate end of file properly.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
readAudio now returns an AudioChunk object directly, and all inputs have
been changed to accomodate this. Also, input and converter processing
have been altered to better work with this.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Most projects needed to be changed to enable C or Objective C modules.
Hopefully, this improves debugging.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The input file has already been opened for decoding by an earlier step
in the testing process, reuse the decoder from that. Spares a decoder
open cycle on all embedded cuesheet supporting formats.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Apparently, Apple's Spatial Audio processor doesn't really support weird
configurations like this. So we need to filter them down to stereo.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This filter replaces the old one, and uses OpenAL Soft presets. Since
there aren't that many of those, I've left off configuration for now,
except to turn it on or off.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This redesign completely changes how tags are stored in memory. Now all
arbitrary tag names are supported, where possible. Some extra work will
be needed to support arbitrary tags with TagLib, such as replacing it
with a different library.
Translation pending for a couple of strings.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Regular control size ends up being 13 points, rather than the previous
default of Small control size, which ended up being 11 points.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
- Switch to fine grained folder and file watching responses
- Navigate the PathNode tree using a fast dictionary of path components
- Quickly refresh the file tree by locating parent nodes to refresh
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
When opening files from external association, such as opening files, or
opening folders with Cog, correctly obey the configured clear and play
or enqueue and play actions, by playing the new additions.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The fragment remover need not detect whether the given path is a folder
or a file, as it is only removing hash marked fragments, not actually
removing the entire filename if it's only a file and not a folder like
the old versions used to. This greatly speeds up access, especially on
network shares.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
When cleaning up the path list, actually remove the pruned entries from
the Core Data storage, so they don't end up resolving to broken
bookmarks in the player, breaking playback on migrated configurations.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Broken bookmarks weren't reporting as isStale, but rather, were failing
to resolve at all, and without this change, they were impossible to
detect in a migrated configuration.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Disable the compiled in AVIF support there, as the OS supports it
natively. Keep the libraries for older OSes.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Matroska files use the "TITLE" field for the album when there are
chapters. Also, Matroska container uses shorter gain field names for
album and track gain, differentiating them by either being global or
specific to each chapter.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Enable playback of video file extensions. Like other video formats
handled by the FFmpeg decoder, video streams are dropped in decode and
only the first audio stream is played.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Use tag string encoding guessing for tag decoding, just in case there
are invalid files with non-standard encoded strings inside the tags, or
if there are streams with such tags. We don't want any crashes.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Improve tag reading performance for Ogg, Opus, FLAC, TTA, and TAK, by
eliminating TagLib from the equation in those cases and just using the
respective file inputs to do the tag reading, which is apparently a lot
faster anyway.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Prevent the player from locking up in certain circumstances, by not
locking chainQueue the entire time this function is processing.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Remove a single .inc include from CogAudio build phase, as it's included
but not compiled as Pascal like Xcode thinks. Also remove a bunch of
files from being copied into the resulting .framework and .bundle files
during link stage, as we don't need to distribute that stuff.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The deinterleaved format was being specified incorrectly. Now it asks
for the correct format, which is deinterleaved, and the bytes per frame
or packet sizes are relative to a single channel's buffer, not all
buffers. Oops, that could have been more clear in the documentation.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Ask for permission to access the folders containing container files,
such as .CUE sheets, or .M3U or .PLS playlists.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Apparently someone managed to crash this with their playlists. No idea
how. Added more safety checks.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Moved external cover art reader to a place where it can be used for any
format, even formats unsupported by Metadata Reader interfaces.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This callback should be unregistered when plugin loading completes,
otherwise we could end up processing bundles loaded by external stuff,
like Audio Units loading for MIDI playback.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Add support for more file name extensions, so we don't fall back on
Core Audio Input for these files.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
When seeking to the end of a file, no longer crash due to out
of range std::vector access, because it was using at() with an
offset of the array size. Instead, offset from the begin()
iterator return value, which allows offsetting to end().
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Default time, fade, loop count, and sample rate may now be overridden.
Synchronized preferences strings tables. Spanish translation of new
options pending, new releases won't be pushed until they're complete.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Also fix the fact that the XIB wasn't embedding the XIB/NIB in the app
as a result of the translation move.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Equalizer was copying the output of the equalizer repeatedly to the
first output channel, instead of copying each channel correctly. This
had the effect of making the equalizer output adjusted audio to only the
left channel in stereo output, and possibly render the stream sounding
weird.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
If somehow a plugin doesn't load, skip cuesheet should skip it anyway,
as we don't want any recursive loops.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
- Plugs the Total duration text to macOS's localization technology
- Adds a proper Spanish translation
- Adapts certain dialogs to make them more suitable for translation
Signed-off-by: Kevin López Brante <kevin@kddlb.cl>
Bundle libOpenMPT as a dynamic framework, which should be safe once
again, now that there is only one version to bundle. Also, now it is
using the versions of libvorbisfile and libmpg123 that are bundled with
the player, instead of compiling minimp3 and stbvorbis.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This allows us to eliminate the requirement to continue bundling version
0.5.x of libOpenMPT for compatibility with macOS 10.13 through 10.14.x.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Revert "Remove the file tree, as Sandbox does not permit"
This reverts commit 02ec735687.
This also changes how the File Tree choosing works.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Sample rate now has a locale independent formatting, and no longer uses
scientific notation for large numbers.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Actually hook up the Reset Play Counts menu item so it actually does
something instead of just sitting there looking pretty.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Handle the configuration better, by adding the path to the grants list
if it is newly configured.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Process main queue messages by handling the loading in a background
queue, and sync it to the main thread periodically, while pausing to
wait for the results. This allows the file open dialog to return
immediately, and display loading progress on the status bar.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The ratings column needs to be made variable width, for variable font
sizes. If anyone knows how to force the width to fit the current text,
I'm open to suggestions.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
When restarting playback on the current track, restart the correct
track, in case restarting near the end of it.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Track play counts for the correct track, even on short tracks. Also
correctly track the play count of the last played item in the play queue
which stops with bufferChain set to nil, so the previous iteration was
not tracking it.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Full access should be synchronized, otherwise rapid access to the same
path from different threads will cause crashes.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Previously, the cleanup thread was not being run. Also, only reset the
metadata deduplication store when the cache is first emptied.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Include entitlement granted user folders in the permission check, so
that if the file or folder is nested under one of them, it allocates a
static permission object, rather than querying the list of configured
paths every time. This also prevents the player from popping open the
path grant / suggester dialog every time a default path is in the file
set listed, which should provide some relief to most users.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Versioning now happens before building Cog itself, and goes
into the Info.plist in the project directory. The original
file became a template file which is altered any time a
build occurs.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This required adding the included script in every project that links to
one of the bundled libraries. The script is designed to sleep for a
while if another thread is already extracting the libraries. The script
uses a temporary file as an extraction step lock, so other instances
sleep, and then detect the libraries.updated file, which is created
before the lock is removed.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Wait for the equalizer to be shut down properly by the main thread
before destroying it. Otherwise, the main thread could crash on stop,
due to accessing the equalizer handle while it's being torn down in the
output thread.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Now the API makes both PCM and FFT data optional, and will do nothing if
neither are requested. Also, it now supports a latency offset in seconds
with floating point precision. The two built-in visualizations currently
request zero larency. Increasing the latency asks for even older samples
while specifying a negative count requests samples from the "future"
relative to what the listener is hearing.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Don't bug out on end of playlist, when didBeginStream will receive a nil
track pointer, which should result in unsetting the current track in the
player, and not send a DidBegin notification to everything, including
the visualization views' event handlers.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Fix counts for tracks with subsongs from piling all the counts onto the
first subsong seen, by using the URL fragment in the filename check and
storage.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Remove the sandbox reference, because the user will add folders outside
the sandbox, and we have entitlements to access these folders.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Cuesheets can now expose which URLs they contain, which may help with
sandbox path configuration. That is, if the CUE sheets are already
readable.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
If upsampling the audio by a significant factor, it may be necessary to
process more than one buffer at a time, rather than lose input.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The visualization buffer now holds up to 45 seconds of loop, and the
latency measurement code now caps this at 30 seconds, and restarts the
output if latency exceeds 30 seconds, such as if a sound output is
reset.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Don't post a metadata event on open, because inputs will relay it to the
player as an early notification bubble, which is unwanted.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
For one thing, the example code I followed was Swift and handled auto
releasing handles in the background, while Objective-C requires manual
handle reference management.
For two, there was no autoreleasepool around the block handling the
input audio chunks, which need to be released as they are pulled out and
disposed of. This also contributed to memory leakage.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Tabulate first seen information when loading the metadata, rather than
when first adding the tracks to the playlist. This should fix first seen
information when metadata is available, as the information will be
useless without track titles.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Cuesheets were invoking a seek operation on open, rather than on first
playback, and this has a heavy toll on FFmpeg audio formats, apparently.
Defer the initial seek to the first readAudio call, and do not invoke it
if a seek was already called on that input session.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This is essential for chapters, as otherwise, we would be skipping an
awful lot of samples every chapter, or every seek within a chapter.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Determine the length of the file from the container, rather than the
individual audio stream. The former is more likely to be set than the
latter is.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Correctly configure AVFoundation with the channel layouts supported by
WAVEFORMATEXTENSIBLE speaker position flags, which includes varied
formats supported by FFmpeg and Core Audio inputs.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Update this patch to the latest FFmpeg master source, and update to use
fmtconvert instead of a naive for loop.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Stop output when requested, except on natural completion of the last
track in the play queue. Also fix deadlocks with stopping and
restarting.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Stream metadata encoding may not be UTF-8, even though the Vorbis
Comment specification clearly calls for this.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The crash was because we weren't copying the results array before
iterating over it, and the deadlock was because this was forced to go
through the main thread, rather than going through its calling thread,
which could lock up if the main thread was busy working with the Sandbox
Broker object.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Commit only once the entire batch is loaded and processed. Also commit
using the correct function.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Made the OpenMPT / legacy OpenMPT and mpg123 libraries pre-built.
Changed the OpenMPT and vgmstream plugins to import the libraries as
they are now. Made mpg123 embedded and imported by the main binary,
since it's now shared by two plugins.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The playlist was being pruned of entries marked for deletion, but they
were not being pruned from the set that was then added to the player.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The Path Suggester will now automatically open when new files are added
to the playlist and a given path is not in the sandbox settings. It will
also pop for both the File Tree and MIDI SoundFont path configuration
settings being changed.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Synchronize storage access to main thread only, to prevent enumeration
from hitting a case of the main thread writing to the storage.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Added a title to the window, make the table view resize properly, and
remove the font size inheritance from the main window.
Signed-off-by: Kevin López Brante <kevin@kddlb.cl>
The output now uses AVSampleBufferAudioRenderer to play all formats, and
uses that to resample. It also supports Spatial Audio on macOS 12.0 or
newer. Note that there are some outstanding bugs with Spatial Audio
support. Namely that it appears to be limited to only 192 kHz at mono or
stereo, or 352800 Hz at surround configurations. This breaks DSD64
playback at stereo formats, as well as possibly other things. This is
entirely an Apple bug. I have reported it to Apple with reference code
FB10441301 for reference, in case anyone else wants to complain that it
isn't fixed.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
All optional fallback code for older versions has also been removed, and
everything now assumes 10.13.0 or newer. Some cases are still included
for point releases, such as 10.13.2.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This needs to be called on the main thread, as something may or may not
be enumerating over the data while this thread decides to call it.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Do not clear the progress indicator if a loading task is already running
in the background, but instead return without doing anything.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Remove the stale Updates check preferences pane, and remove the donation
option from the menu, as it is considered In App Purchases.
Consider adding actual App Store In App Purchase options of "Buy me a
coffee" or similar, with no guarantee of return for the purchase, other
than furthering development. Make them repeatable purchases.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
New version strings are in a different place, and Sparkle will no longer
be including the Git hash in the CFBundleVersion query, so we must get
it from the ZIP filename.
Hopefully this blank assignment will spare these files from being
touched by Xcode again in the future, when the variable in question is
imported from a developer supplied configuration file.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This file should not be referenced directly by projects, otherwise it
will be expected to exist, even in CI.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Only initialize viewController once, the first time the volume control
is opened. Re-initializing it can cause an error assigning it as first
responder to the volume slider popover view.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Redesign the code signing from the ground up. Now all bundles and their
embedded frameworks import the Shared.xcconfig file and enable its
settings, so they may be signed with Apple Development instead of sign
to run locally. This apparently isn't necessary for frameworks which are
embedded in the main app bundle directly, only for the bundles and their
frameworks.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Require asking user consent for data transmission on first launch, or
otherwise disable sending crash reports by default.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Automatically format any XML escapes of file type association names.
Adjust Info.plist to account for this change.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
2022-06-21 18:59:57 -07:00
179 changed files with 30 additions and 7845 deletions
-(void)setFeedURL:(nullableNSURL*)feedURL__deprecated_msg("Please call -[SPUUpdater clearFeedURLFromUserDefaults] to migrate away from using this API and transition to either specifying the feed URL in your Info.plist, using channels in Sparkle 2, or using -[SPUUpdaterDelegate feedURLStringForUpdater:] to specify the dynamic feed URL at runtime");
-(nullableid<SUVersionComparison>)versionComparatorForUpdater:(SPUUpdater*)updater__deprecated_msg("Custom version comparators are deprecated because they are incompatible with how the system compares different versions of an app.");
-(BOOL)updaterMayCheckForUpdates:(SPUUpdater*)updater__deprecated_msg("Please use -[SPUUpdaterDelegate updater:mayPerformUpdateCheck:error:] instead.");
-(void)updater:(SPUUpdater*)updateruserDidSkipThisVersion:(SUAppcastItem*)item__deprecated_msg("Please use -[SPUUpdaterDelegate updater:userDidMakeChoice:forUpdate:state:] instead.");
*Ifthestate.stageis`SPUUserUpdateStateInstalling`,thismaysendaquiteventtotheapplicationandrelaunchitimmediately(inthisstate,thisbehavesasafast"install and Relaunch").
-(void)dismissUserInitiatedUpdateCheck__deprecated_msg("Transition to new UI appropriately when a new update is shown, when no update is found, or when an update error occurs.");
-(nullableinstancetype)initWithDictionary:(NSDictionary*)dict__deprecated_msg("Properties that depend on the system or application version are not supported when used with this initializer. The designated initializer is available in SUAppcastItem+Private.h. Please first explore other APIs or contact us to describe your use case.");
-(nullableinstancetype)initWithDictionary:(NSDictionary*)dictfailureReason:(NSString*_Nullable__autoreleasing*_Nullable)error__deprecated_msg("Properties that depend on the system or application version are not supported when used with this initializer. The designated initializer is available in SUAppcastItem+Private.h. Please first explore other APIs or contact us to describe your use case.");
-(nullableinstancetype)initWithDictionary:(NSDictionary*)dictrelativeToURL:(NSURL*_Nullable)appcastURLfailureReason:(NSString*_Nullable__autoreleasing*_Nullable)error__deprecated_msg("Properties that depend on the system or application version are not supported when used with this initializer. The designated initializer is available in SUAppcastItem+Private.h. Please first explore other APIs or contact us to describe your use case.");
-(void)formatVersion:(NSString*_Nonnull*_Nonnull)inOutVersionAandVersion:(NSString*_Nonnull*_Nonnull)inOutVersionB__deprecated_msg("Please use -formatUpdateDisplayVersionFromUpdate:andBundleDisplayVersion:withBundleVersion:");
/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "43"; */
"43.title" = "Text Cell";
/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "45"; */
"45.title" = "Text Cell";
/* Class = "NSTextFieldCell"; title = "Anonymous system profile information is used to help us plan future development work. Please contact us if you have any questions about this.\n\nThis is the information that would be sent:"; ObjectID = "183"; */
"183.title" = "Anonymous system profile information is used to help us plan future development work. Please contact us if you have any questions about this.\n\nThis is the information that would be sent:";
/* Class = "NSButtonCell"; title = "Don’t Check"; ObjectID = "cCJ-V0-aTi"; */
"cCJ-V0-aTi.title" = "عدم التحقق";
/* Class = "NSTextFieldCell"; title = "Check for updates automatically?"; ObjectID = "gmh-T4-BO0"; */
"gmh-T4-BO0.title" = "هل تريد أن يتم التحقق من وجود تحديثات تلقائيًا؟";
/* Class = "NSButtonCell"; title = "Include anonymous system profile"; ObjectID = "gz7-LM-gNf"; */
"gz7-LM-gNf.title" = "تضمين تقرير عن النظام دون ذكر معلومات عن المستخدم";
/* Class = "NSButtonCell"; title = "Automatically download and install updates"; ObjectID = "AUc-33-qGN"; */
"AUc-33-qGN.title" = "تنزيل التحديثات وتثبيتها تلقائيًا في المست";
/* Class = "NSButtonCell"; title = "Check Automatically"; ObjectID = "OhZ-1K-DmA"; */
/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "43"; */
"43.title" = "Text Cell";
/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "45"; */
"45.title" = "Text Cell";
/* Class = "NSTextFieldCell"; title = "Anonymous system profile information is used to help us plan future development work. Please contact us if you have any questions about this.\n\nThis is the information that would be sent:"; ObjectID = "183"; */
"183.title" = "Informace z anonymního systémového profilu pomáhají vývojářům lépe plánovat budoucí vývoj aplikace.\nBudete-li mít nějaký dotaz, obraťte se na nás.\n\nToto jsou informace, které budou odeslány:";
/* Class = "NSButtonCell"; title = "Don’t Check"; ObjectID = "cCJ-V0-aTi"; */
"cCJ-V0-aTi.title" = "Nevyhledávat";
/* Class = "NSTextFieldCell"; title = "Check for updates automatically?"; ObjectID = "gmh-T4-BO0"; */
/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "43"; */
"43.title" = "Text Cell";
/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "45"; */
"45.title" = "Text Cell";
/* Class = "NSTextFieldCell"; title = "Anonymous system profile information is used to help us plan future development work. Please contact us if you have any questions about this.\n\nThis is the information that would be sent:"; ObjectID = "183"; */
"183.title" = "Anonymous system profile information is used to help us plan future development work. Please contact us if you have any questions about this.\n\nThis is the information that would be sent:";
/* Class = "NSButtonCell"; title = "Don’t Check"; ObjectID = "cCJ-V0-aTi"; */
"cCJ-V0-aTi.title" = "Søg ikke";
/* Class = "NSTextFieldCell"; title = "Check for updates automatically?"; ObjectID = "gmh-T4-BO0"; */
"gmh-T4-BO0.title" = "Søg efter opdateringer automatisk?";
/* Class = "NSButtonCell"; title = "Include anonymous system profile"; ObjectID = "gz7-LM-gNf"; */
/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "43"; */
"43.title" = "";
/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "45"; */
"45.title" = "";
/* Class = "NSTextFieldCell"; title = "Anonymous system profile information is used to help us plan future development work. Please contact us if you have any questions about this.\n\nThis is the information that would be sent:"; ObjectID = "183"; */
"183.title" = "Das anonymisierte Systemprofil unterstützt uns bei der zukünftigen Entwicklung. Bitte kontaktiere uns, wenn du Fragen hierzu hast.\n\nDiese Informationen würden an uns gesendet werden:";
/* Class = "NSButtonCell"; title = "Don’t Check"; ObjectID = "cCJ-V0-aTi"; */
"cCJ-V0-aTi.title" = "Nicht suchen";
/* Class = "NSTextFieldCell"; title = "Check for updates automatically?"; ObjectID = "gmh-T4-BO0"; */
"gmh-T4-BO0.title" = "Automatisch nach Updates suchen?";
/* Class = "NSButtonCell"; title = "Include anonymous system profile"; ObjectID = "gz7-LM-gNf"; */
/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "43"; */
"43.title" = "Text Cell";
/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "45"; */
"45.title" = "Text Cell";
/* Class = "NSTextFieldCell"; title = "Anonymous system profile information is used to help us plan future development work. Please contact us if you have any questions about this.\n\nThis is the information that would be sent:"; ObjectID = "183"; */
"183.title" = "Οι ανώνυμες πληροφορίες του προφίλ του συστήματός σας, μας βοηθούν στο σχεδιασμό της μελλοντικής ανάπτυξης του προγράμματος. Παρακαλώ επικοινωνήστε μαζί μας άν έχετε ερωτήσεις.\n\nΑυτές είναι οι πληροφορίες που θα σταλούν σε εμάς:";
/* Class = "NSButtonCell"; title = "Don’t Check"; ObjectID = "cCJ-V0-aTi"; */
"cCJ-V0-aTi.title" = "Κανένας έλεγχος";
/* Class = "NSTextFieldCell"; title = "Check for updates automatically?"; ObjectID = "gmh-T4-BO0"; */
"gmh-T4-BO0.title" = "Αυτόματος έλεγχος για ενημερώσεις;";
/* Class = "NSButtonCell"; title = "Include anonymous system profile"; ObjectID = "gz7-LM-gNf"; */
"gz7-LM-gNf.title" = "Συμπερίληψη του ανώνυμου προφίλ του συστήματός σας";
/* Class = "NSButtonCell"; title = "Automatically download and install updates"; ObjectID = "AUc-33-qGN"; */
"AUc-33-qGN.title" = "Αυτόματη λήψη και εγκατάσταση ενημερώσεων";
/* Class = "NSButtonCell"; title = "Check Automatically"; ObjectID = "OhZ-1K-DmA"; */
/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "43"; */
"43.title" = "Text Cell";
/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "45"; */
"45.title" = "Text Cell";
/* Class = "NSButtonCell"; title = "Check Automatically"; ObjectID = "176"; */
"OhZ-1K-DmA.title" = "Check Automatically";
/* Class = "NSButtonCell"; title = "Don’t Check"; ObjectID = "177"; */
"cCJ-V0-aTi.title" = "Don’t Check";
/* Class = "NSTextFieldCell"; title = "Check for updates automatically?"; ObjectID = "178"; */
"gmh-T4-BO0.title" = "Check for updates automatically?";
/* Class = "NSTextFieldCell"; title = "DO NOT LOCALIZE"; ObjectID = "179"; */
"179.title" = "DO NOT LOCALIZE";
/* Class = "NSButtonCell"; title = "Include anonymous system profile"; ObjectID = "180"; */
"gz7-LM-gNf.title" = "Include anonymous system profile";
/* Class = "NSButtonCell"; title = "Automatically download and install updates"; ObjectID = "AUc-33-qGN"; */
"AUc-33-qGN.title" = "Automatically download and install updates";
/* Class = "NSTextFieldCell"; title = "Anonymous system profile information is used to help us plan future development work. Please contact us if you have any questions about this.\n\nThis is the information that would be sent:"; ObjectID = "183"; */
"183.title" = "Anonymous system profile information is used to help us plan future development work. Please contact us if you have any questions about this.\n\nThis is the information that would be sent:";
/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "43"; */
"43.title" = "Text Cell";
/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "45"; */
"45.title" = "Text Cell";
/* Class = "NSTextFieldCell"; title = "Anonymous system profile information is used to help us plan future development work. Please contact us if you have any questions about this.\n\nThis is the information that would be sent:"; ObjectID = "183"; */
"183.title" = "La información de perfil de sistema anónimo se usa para ayudarnos a planear el trabajo de desarrollo futuro. Por favor, póngase en contacto con nosotros si tiene preguntas sobre esto.\n\nEsta es la información que nos enviaría:";
/* Class = "NSButtonCell"; title = "Don’t Check"; ObjectID = "cCJ-V0-aTi"; */
"cCJ-V0-aTi.title" = "No comprobar";
/* Class = "NSTextFieldCell"; title = "Check for updates automatically?"; ObjectID = "gmh-T4-BO0"; */
"gmh-T4-BO0.title" = "¿Comprobar si hay actualizaciones automáticamente?";
/* Class = "NSButtonCell"; title = "Include anonymous system profile"; ObjectID = "gz7-LM-gNf"; */
"gz7-LM-gNf.title" = "Incluir perfil de sistema anónimo";
/* Class = "NSButtonCell"; title = "Automatically download and install updates"; ObjectID = "AUc-33-qGN"; */
"AUc-33-qGN.title" = "Descargar e instalar actualizaciones automáticamente";
/* Class = "NSButtonCell"; title = "Check Automatically"; ObjectID = "OhZ-1K-DmA"; */
/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "43"; */
"43.title" = "Text Cell";
/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "45"; */
"45.title" = "Text Cell";
/* Class = "NSTextFieldCell"; title = "Anonymous system profile information is used to help us plan future development work. Please contact us if you have any questions about this.\n\nThis is the information that would be sent:"; ObjectID = "183"; */
"183.title" = "Anonymous system profile information is used to help us plan future development work. Please contact us if you have any questions about this.\n\nThis is the information that would be sent:";
/* Class = "NSButtonCell"; title = "Don’t Check"; ObjectID = "cCJ-V0-aTi"; */
"cCJ-V0-aTi.title" = "Älä tarkista";
/* Class = "NSTextFieldCell"; title = "Check for updates automatically?"; ObjectID = "gmh-T4-BO0"; */
/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "43"; */
"43.title" = "Text Cell";
/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "45"; */
"45.title" = "Text Cell";
/* Class = "NSTextFieldCell"; title = "Anonymous system profile information is used to help us plan future development work. Please contact us if you have any questions about this.\n\nThis is the information that would be sent:"; ObjectID = "183"; */
"183.title" = "Les informations anonymes de profil système nous aident à planifier les futurs développements. Contactez-nous pour toute question à ce sujet.\n\nCi-dessous figurent les informations qui seront transmises:";
/* Class = "NSButtonCell"; title = "Don’t Check"; ObjectID = "cCJ-V0-aTi"; */
"cCJ-V0-aTi.title" = "Ne pas vérifier";
/* Class = "NSTextFieldCell"; title = "Check for updates automatically?"; ObjectID = "gmh-T4-BO0"; */
"gmh-T4-BO0.title" = "Rechercher automatiquement les mises à jour?";
/* Class = "NSButtonCell"; title = "Include anonymous system profile"; ObjectID = "gz7-LM-gNf"; */
"gz7-LM-gNf.title" = "Avec transmission anonyme de mon profil système";
/* Class = "NSButtonCell"; title = "Automatically download and install updates"; ObjectID = "AUc-33-qGN"; */
"AUc-33-qGN.title" = "Télécharger et installer automatiquement les mises à jour";
/* Class = "NSButtonCell"; title = "Check Automatically"; ObjectID = "OhZ-1K-DmA"; */
/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "43"; */
"43.title" = "Text Cell";
/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "45"; */
"45.title" = "Text Cell";
/* Class = "NSButtonCell"; title = "Check Automatically"; ObjectID = "176"; */
"OhZ-1K-DmA.title" = "חפש עדכונים אוטומטית";
/* Class = "NSButtonCell"; title = "Don’t Check"; ObjectID = "177"; */
"cCJ-V0-aTi.title" = "אל תחפש";
/* Class = "NSTextFieldCell"; title = "Check for updates automatically?"; ObjectID = "178"; */
"gmh-T4-BO0.title" = "לחפש עדכונים באופן אוטומטי?";
/* Class = "NSTextFieldCell"; title = "DO NOT LOCALIZE"; ObjectID = "179"; */
"179.title" = "DO NOT LOCALIZE";
/* Class = "NSButtonCell"; title = "Include anonymous system profile"; ObjectID = "180"; */
"gz7-LM-gNf.title" = "כלול מידע מערכת אנונימי";
/* Class = "NSButtonCell"; title = "Automatically download and install updates"; ObjectID = "AUc-33-qGN"; */
"AUc-33-qGN.title" = "הורד והתקן עדכונים באופן אוטומטי";
/* Class = "NSTextFieldCell"; title = "Anonymous system profile information is used to help us plan future development work. Please contact us if you have any questions about this.\n\nThis is the information that would be sent:"; ObjectID = "183"; */
"183.title" = "מידע מערכת אנונימי משמש כדי לעזור לנו לתכנן את עבודת הפיתוח העתידית. אנא צור איתנו קשר אם יש לך שאלות בנושא.\n\nזהו המידע שיישלח:";
/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "43"; */
"43.title" = "Text Cell";
/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "45"; */
"45.title" = "Text Cell";
/* Class = "NSTextFieldCell"; title = "Anonymous system profile information is used to help us plan future development work. Please contact us if you have any questions about this.\n\nThis is the information that would be sent:"; ObjectID = "183"; */
"183.title" = "Anonimizirani podaci profila susatava pomažu nam planirati budući razvoj. Kontaktiraj nas, ako imaš pitanja o tome.\n\nŠalju se sljedeći podaci:";
/* Class = "NSButtonCell"; title = "Don’t Check"; ObjectID = "cCJ-V0-aTi"; */
"cCJ-V0-aTi.title" = "Nemoj provjeravati";
/* Class = "NSTextFieldCell"; title = "Check for updates automatically?"; ObjectID = "gmh-T4-BO0"; */
/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "43"; */
"43.title" = "Text Cell";
/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "45"; */
"45.title" = "Text Cell";
/* Class = "NSTextFieldCell"; title = "Anonymous system profile information is used to help us plan future development work. Please contact us if you have any questions about this.\n\nThis is the information that would be sent:"; ObjectID = "183"; */
"183.title" = "Anonymous system profile information is used to help us plan future development work. Please contact us if you have any questions about this.\n\nThis is the information that would be sent:";
/* Class = "NSButtonCell"; title = "Don’t Check"; ObjectID = "cCJ-V0-aTi"; */
"cCJ-V0-aTi.title" = "Manuális keresés";
/* Class = "NSTextFieldCell"; title = "Check for updates automatically?"; ObjectID = "gmh-T4-BO0"; */
"gmh-T4-BO0.title" = "Keresse automatikusan a frissítéseket?";
/* Class = "NSButtonCell"; title = "Include anonymous system profile"; ObjectID = "gz7-LM-gNf"; */