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>
When testing the path for whether it's in storage, run more tests to
make sure we only care about valid paths, and a path that actually has
a string.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Plist generator now emits the output to the temporary folder, which we
have write permission to.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Skip the frame during decode, which will likely incur a BADDATAPTR error
on the first frame, as has already been logged in the development
process. Instead, skip the first frame, then proceed to the next one.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This reverts commit 453e29b2f5. Also it
applies a different workaround for VBRI headers, which doesn't require
patching libmad to work.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Refine the global variable usage, eliminating double underscore prefixes
and trusting that static global variables will exist in the object where
the class was created. Got rid of that nasty NSApplication extension
hack that was previously in use.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Allow opening directory URLs as-is, rather than treating them like
files. Return the full path if the caller requests opening on a
directory.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Implement Sandbox Broker support for the File Tree root path, in case it
is needed to enumerate files from within it.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Metadata loading now filters the request list down to unique file paths
that don't have metadata loaded, makes sure that another instance of the
loader isn't already loading the same files, and waits for previous
instances to complete before beginning another metadata load task. It
also will update the playlist entries for all affected tracks, even if
they were not explicitly selected for loading or reloading.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Add dealloc function to close the file container, in case the caller
neglected to do so on its own.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Refine the output function a bit, including adding some minor safety
checks, in case the caller requests zero samples, or requests a format
with zero channels.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Move the Core Audio output function block to its own declarative
function, so that its block variables are isolated, and so that debug
traces show up in a more sensible place.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Sandbox Broker now returns a handle to the exact path object that was
retained by the caller, so it will be released correctly, regardless of
what happens to the list of bookmarked paths.
Also refined the bookmark path comparison function. For existing paths,
it will find the first match. For new paths, it will prefer the longest
path instead, to try to find the deepest matching bookmark.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Refuse to update the dock icon image if the dock icon plaque image fails
to load somehow. Really weird case.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Remember if play count was already tracked for the current file across
restarts, if resume playback after restart is enabled.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This notification can't escape the sandbox anyway, and I forgot to
remove it after adding the app sandbox code again.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
- Implemented App Sandboxing in a more friendly manner.
- All sandboxed paths will need to be set in Preferences. Set as loose
a path as you want. The shortest path will be preferred.
- Removed Last.fm client support, as it was non-functional by now,
unfortunately. Maybe something better can come in the future.
- Added support for insecure SSL to the HTTP/S reader, in case anyone
needs streams which are "protected" by self-signed or expired
certificates, without having to futz around by adding certificates to
the system settings, especially for expired certificates that can't
otherwise be dodged this way.
If you want to import your old playlists to the new version, copy the
contents of `~/Library/Application Support/Cog` to the alternate sandbox
path: `~/Library/Containers/org.cogx.cog/Data/Library/Application `...
...continued...`Support/Cog`. The preferences file will migrate to the
new version automatically.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Remove the AppCheck code from the debug builds, as it's not even enabled
on the project in Firebase anyway.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This header type was missing, causing some Fraunhofer VBR MP3 files to
decode the wrong length information.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
There was a slight bug with handling Xing/LAME headers with main data
pointers indicating data preceding the header frame. This should allow
decoding their information properly.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Metadata notifier should have been reformatted to use the properties as
dotted members, and also check for empty strings.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Remember last play position in the playlist, rather than using an index
variable to store its position and play time. Still store whether the
player was last playing in a configuration variable, though.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Remove or rename obsolete English.lproj files, renaming where
en.lproj does not already exist, or removing if en.lproj has
already replaced it.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The strings are now part of the localized strings storage, which is
still awaiting a volunteer to add more translations to the app.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This code turned out to be somewhat of a mistake to employ, so it's now
being removed, and shall not be re-added, as it doesn't really work.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Add play count data collection, including first seen times for every
file first added to the playlist. Data is indexed by album, artist, and
title, or by filename, whichever matches first. Add interfaces to
AppleScript automation definition as well.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Handle missing track items in the databse more gracefully, by deleting
the track entries before passing them on to the caller, so problems do
not occur later.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Prevent the notification balloons from displaying empty hyphens or tags
if either album or artist is empty but not nil.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Device name logging is essential in determining if crashes are on
specific device models that haven't been blocklisted.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Invalid files may include nil URLs, which should be skipped or stop
playback altogether. Invalid files will be marked as an error, and
stop playback.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
As it doesn't seem to work properly on Intel machines, anyway. It just
leads to pointless crashes, and doesn't seem to serve any purpose.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Restrict the use of workgroup joining and workgroup intervals to macOS
Monterey or newer, as it seems the way I use it, it's completely broken
on macOS Big Sur, which was the original minimum target for the API.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The SceneKit visualizer now has a crash check, which will trigger if an
exception is thrown by the app.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Apply changes to exit the thread if workgroup initialization or joining
fails, instead of attempting to continue executing the thread.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Make the album match predicate an exact match, rather than using the
"like" operator, in case there's a speed up from doing so.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Apply the index sort to the fetch request itself, rather than applying
it to the resulting array afterward.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The list generator now selects only a list of unique album names, which
may include empty string as well as NSNull, so filter those as well.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Rewrite the album filter function to apply the filter predicate against
Core Data directly, which also requires filtering out deLeted entries so
they don't end up in the results, and also requires sorting the results.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Add an extra step to the workgroup exit call, so that it only calls to
leave if the join token is valid, or at least initialized.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Sending reports is now handled synchronously on the startup path, so
that unsent reports can be sent before a startup crash causes further
crashes to occur. This is apparently needed to help one particular user
catch whatever is causing the app to crash for them.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Fix streaming metadata titles being overridden by the Icecast stream
strings. Now the Icy metadata only overrides missing strings, so Vorbis
Comments take priority.
Fixes#275
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Fix a potential bug where the device enumerator would return a nil
device name string, which would result in a crash. Instead, report an
unknown numbered device.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Move the initializer to a function that will be called earlier in the
startup stage. Mainly to catch crashes in the playlist importer for
legacy playlist formats.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Reject system identifier numbers that aren't supported, outright, rather
than waiting until the decoder is initialized.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The new Core Data interface is especially stringent with receiving
NSNumber for the numeric types rather than NSString as was mistakenly
allowed before. Fix that to prevent exceptions.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Apparently my Xcode version generates files which are incompatible with
whatever Xcode build environment that Github CI runs.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The member that I set myself to indicate deletion has one capital letter
to differentiate it from the built-in "delete" property of managed
objects, which doesn't do what I want, so I had to dodge it with that
capitalization thing.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Use a custom script found on Stack Overflow, with some minor changes for
a little more sanity, such as using find -print0 / xargs -0 to support
paths with spaces in them.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Header include paths are named after the framework, which is all lower-
case, not uppercase like the source folder is named. The header include
paths inside the project are lowercase as well, so this fits.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Change most, if not all, possible import paths to use the full header
directory paths instead of relative or "assume include paths" settings.
This should fix building with the CI.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
These header files were imported from the wrong path. I really have no
idea why Xcode didn't catch these already with my build tree.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
It was a fun ride, but I think I want to try something different. Users,
please be sure not to have DNS blocking for Crashlytics if you want me
to have any useful bug reporting info if it crashes on you, or otherwise
blows up. Otherwise, I don't get any useful data to help me fix crashes.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Fix the default volume scale reading for newly added tracks, as this
value should be 1 for any files which do not have tags. Also add an
override to the tag applying function, to reset the default on tag
re-read operations.
Please reload the tags or re-add your files to fix them playing
silently.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Add a compatibility getter/setter for URL, which was renamed to url, due
to Core Storage having a requirement of all attributes starting with a
lower case letter.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Fixed the implementation to work correctly with the new Core Data
storage system. Tracks will be garbage collected later.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The PlaylistEntry class needs a compatibility wrapper for the Unsigned
member, as it is assigned by all of the inputs. Case sensitivity and all
that is. And unfortunately, Core Data requires all model members to
start with a lower case letter.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The copy action now includes formatted text of the selected entries when
copying, in addition to the supported file and URL types.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Completely rewrite the playlist storage once again, this time with a
much faster Core Data implementation. It still uses a little magic for
Album Artwork consolidation, but string consolidation doesn't seem to be
needed to reduce the disk storage size. Works much faster than my silly
implementation, too.
Old implementations are still kept for backwards compatibility with
existing playlists.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Synchronize audio setup and audio stopping on the object's own pointer,
to hopefully prevent race conditions with out of sync calls to the stop
function from both the main and the audio thread.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The changes include no longer leaving the workgroup for seeking or for
converter format changes, and also still leaving the workgroup on thread
termination if there was an error with intervals starting or finishing.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Prevent an unhandled exception when a notification is sent on a track
which has been deleted from the playlist.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Jobs are meant to be serialized, so prevent multiple jobs from queueing
simultaneously, as they are not designed to interact with each other.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Long actions, such as file opening, playlist loading, metadata loading
and refreshing, etc, are now handled through NSProgress. Additionally,
a new status bar change displays the progress of the task instead of
the total duration of the playlist. Finally, app quit is blocked by a
running task, and if the app is quit while a task is running, it will
be delayed until the task completes, at which time the app will
terminate cleanly.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Prevent a race condition with deleting playlist entries while their
metadata is still being loaded by the player.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Guard Open in Finder against being called on a playlist with no
selection, which may happen if the action is triggered on an empty
playlist, which would cause an array out of bounds access error.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Guard the playlist entry retrieval function against being called on an
empty playlist, because an empty playlist would result in a division by
zero error to occur here.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
If there is somehow a legacy XML playlist, and there is no queue entry
in the plist, then it should not throw an exception from trying to add
a nil object to the return dictionary.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
An impulse cache reduces any glitching from format channel count changes
to near insignificant levels, resulting in a more pleasant experience
when there are different mixed formats playing, or even a file which
changes format mid-playback.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Ensure that dynamic info updates, even on static files, only update the
exact track they apply to, by atomically assigning the userInfo property
before opening the decoder, so that callbacks to the player indicate the
correct track and don't assume it's the one that's currently visibly
playing. Fixes start of track metadata notifications from overwriting
the previously playing track.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Only do a rough estimation on files without Xing or LAME or iTunes
headers. This is much faster, even if less accurate, and may include
the footer tag if present.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Every schema upgrade process should fall through to the next highest
version number, so they should all run, if the user has somehow upgraded
their database from such an old version.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The inputs now have their own metadata function, so it should merge in
the track tags from the Cuesheet, and not just forward it to the
decoder.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Bugsnag framework was possibly missing from the config files, so
it's been added properly on older Xcode.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This should prevent a crash if the input is recycled for another file,
which would cause the output buffer to be freed, but the output size to
contain a count on first call to readAudio, which would cause a memory
access crash.
Possibly fixes#269
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Various warnings related to uninitialized variables, or setting values
to variables that would not be used later or would be overwritten by per
loop initializers.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
If one condition returned memory successfully, but the other did not, it
would result in the cleanup code accessing an uninitialized pointer and
iterating over it, crashing.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Surprised I didn't catch this sooner. This could have resulted in a
division by zero error if either sample rate somehow was zero.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The two toolbars seem to require unique identifiers for each of their
items, even when they're separate toolbars in separate windows.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Now read all metadata and signal it, and also support pre-buffering
a small block of sample frames if there is embedded artwork, since the
embedded artwork must be handled by the sample decode function.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Add support for plain "genre" tag, in addition to the previously
supported "icy-genre" field for streams, this one is for static files.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
DFT should use aligned memory blocks for best results. Also allocate one
extra sample for DFT output, just in case DFT zop is as bad as zrop.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
DFT float happens to clobber one extra sample on forward translate, so
allocate one extra for every complex buffer.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Work back to a vDSP implementation, this time using overlap-save instead
of overlap-add, also accumulating the results as complex values, only
inversing them once at the end, and finally, replacing the FFT method
with the newer DFT API.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The legacy 2D visualizer now supports customizable bar and peak dot
colors, and renders a grid and labels in the windowed mode.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Constrain observer events to the exact context requested, and remove
them with the same context specified.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Only uninitialize the equalizer if sound output was successfully started
and the equalizer AudioUnit was successfully ininitialized.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
String and art adder functions now perform type checks, in case of
memory errors that somehow result in classes changing type. Which in
itself is a strange thing to happen.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Restructure the add string or art functions so they don't take a pointer
to a pointer, which may have caused issues when receiving a nil string
from the caller. Instead, take a plain pointer, and return the object,
returning the ID of the object to a pointer to an int64_t.
Also change several prototypes and functions to use _Nonnull or
_Nullable where appropriate.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Optimization level bugs now affect Apple Silicon release builds, so
reduce optimization level there as well.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
When leaving the workgroup, clear the token, as the join call requires
the token to be uninitialized.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Errors should stop all attempts to further use the audio thread priority
code, so there won't be debug breakpoints called on older OSes.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The properties function should not be dereferencing an invalid index
into the layer codec name array if layer is not set to 1 through 3. This
could happen if, for instance, an MP3 file has an invalid ID3v2 tag.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This condition would underflow when skipping a bunch of samples on the
start of playback, or otherwise seeking, and could cause an unsigned
underflow, which would cause the subsequent vDSP_vflt32 to overread into
the MAD sample buffer and crash.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
As the decimator has shown to be twice as loud as it should be, the
volume should be reduced by half when converting DSD to PCM with it.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Pure downsampling is slower, but may or may not be more accurate. Though
probably not worth it. It did help me realize a minor error, though.
The decimator's volume is twice as loud as it should be.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This prevents crashes where inputs were not returning either properties
or metadata blocks and the file open cache was attempting to cache the
resulting nil pointer as if it were valid. Also prevent the metadata
redundant string coalescing from processing nil objects as well, in case
it's used that way somewhere else.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The symbol uploads on archive are useless unless they're uploaded with
the API key set correctly in the script.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Submodule projects are sometimes out of my control, so I shouldn't have
to deal with team identifiers in projects that don't affect my build
process in any meaningful way. The only way to deal with this would be
to fork and modify every project I touch that contains this stuff. No.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Set baseline real-time priority for audio threads even on old macOS,
since that API is available there. Only set it once, and do not attempt
again if it fails, only once per thread.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
I'm not sure about macOS Ventura, but stable releases of macOS, at
least on Intel, require that threads joining Audio Interval
workgroups already be set to run as real-time before joining. Not
doing this results in an uncaught exception and a crash.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Now it allocates audio workgroups per thread, using work slices like the
Apple documentation describes for asynchronous threads.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Add an extra condition to the visibility check, which is similar to the
previous version of this check, which now guards against the window it
is hosted in not being visible.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
On Big Sur or newer, it is possible to join the audio threads to the
same OS workgroup as the audio output device, improving response.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
For legacy systems that do not support Metal. The Metal SceneKit view
does work on even 10.13.6, if a Metal GPU is present in the system.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Update all project files with new upgrade version number, and add the
dead code stripping option. Don't touch MASShortcut because it's not my
project.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
When visualizer windows are created, but not actually visible, stop the
update timer, to save processing, especially if the vis is enabled in
one or the other main/mini windows.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Replace overlap-add vDSP/Accelerate implementation with a faster PFFFT
overlap-save implementation, using fewer FFT steps as well.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Rewrite some of the output and a lot of the downmixer to use Accelerate
framework instead of dumb for loops.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Apparently this simpler API already existed on a minimum of 10.11 for
creating a system font with monospaced digits.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Use delayed dispatching on expensive operations which occur every time
the "heard" track end happens, and when audio metadata is changed by a
stream, so that they are inserted into the main thread queue after the
invoking callback returns control execution back to the audio thread.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Since the existing code already supports setting any arbitrary track as
a stopping point, add a menu interface to toggle Stop After for any
track in the playlist. Stop After will be removed from the given track
after it has been played. Stop After will not be remembered on disk.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Gate registering observers behind a check variable in the object state,
which will be zero initialized by the Objective-C runtime, and will
prevent the class from erroneously unregistering observers without them
being registered in the first place. Apparently, services cannot be
unregistered if they were never registered first, or else an exception
will be thrown upon attempting to unregister them. This fixes a crash on
startup in the now several times running failure to work properly on
legacy Macs without Metal graphics, now that the new visualization
system has been implemented.
It's probably not worth bringing back the previous Core Graphics based
visualizer method anyway, as on those same legacy machines, it was
causing out of control CPU usage by WindowServer. At least on modern
Macs, any amount of 60fps UI updating will cause WindowServer to use
about 45% of a core, regardless of how many apps are drawing that much
at once.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Apparently, PFFFT double is much faster than vDSP, and I didn't even
notice. Thanks to Aleksey Vaneev for testing this properly.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
When resampling the impulse according to the playback rate, it becomes
necessary to normalize the resulting impulse by the inverse of the
sample ratio, as resampling adds more or less loudness by virtue of
interpolating samples.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This will be proper at least unless I get this commit merged upstream.
Squashed the changes to a single commit, and removed extraneous
whitespace that crept into the code.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
If the system has no working Metal devices, disable the visualization.
The legacy visualization was also too slow for said systems to handle
reasonably anyway, so I guess it's safe to say that they shouldn't have
to handle any visualizers at all. At least have working audio playback,
of course, since that is the primary function of the application. Too
bad that the OpenGL renderers don't work on my scene, it would be nice
to have a fallback there. GL 4.1 crashes on an M1, and both GL 4.1 and
3.2 crash with SIGFPE division by zero error on Intel Macs without Metal
devices. Meh.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Remove the default Metal device option, as it can return nil on systems
where it won't be expected to work.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The frequency mode, apparently the default, doesn't like that the code
was setting the width of the spectrum data to 11 instead of the default
1000. This was causing it to overwrite freed memory when the spectrum
started processing audio.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The OpenGL fallback was causing division by zero errors on Intel Macs
running macOS High Sierra.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Apparently, old macOS wants to divide something by the scale size, so
setting it to zero causes division by zero errors? Let's set it to a
really small number instead.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The function I added only works for non-interleaved real/imaginary pairs
and not the interleaved setup that r8brain expects. Fix that by removing
the multiply implementation and using the original one.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The used fork of r8brain now uses the Accelerate vDSP FFT functions for
resampling, which should provide a slight speedup, or significant for
large sample ratios.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Adding a cast here silences a warning from passing a long to a function
accepting an int. It doesn't really matter here anyway, as the long in
question is hard coded to initialize to a fixed sample rate. Even when
sample rate configuration is eventually added, this will still be hard
capped to well within the range of 32-bit integers.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Metadata logic code should be using this dictionaryWithDictionary method
so that the resulting dictionary is actually immutable, like it claims
to be, rather than simply casting it. Safety coding, all that jazz. Not
really a major issue, just feels right.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Most file formats the player supports may or may not have UTF-8 safe
strings in their metadata. This should not be assumed to be UTF-8, and
when it is assumed, it results in nil NSString objects, which results in
inline initializers crashing due to uncaught exceptions.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Moved the string encoding guesser/converter to the Plugin.h header, so
it may be accessible from any plugin. I may make it a global member of
something eventually, but a static inline for such a simple function
should be fine for now.
This function facilitates converting arbitrary 8 bit encoded strings to
Unicode NSString objects. It should be used anywhere that UTF-8 is
expected, but not necessarily guaranteed, and where other 8-bit
encodings may also be supplied by a user's files.
Not using this setup for string inputs has already led to failed UTF-8
decoding resulting in nil NSStrings being passed to the inline array or
dictionary initializers, which results in crashes due to uncaught
exceptions.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
On legacy OSes, and legacy GPUs, it should use OpenGL and not Metal,
otherwise there could be horrible performance, or even crashes.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
When the visualization window is not open, it should not continue to run
the scene until the app is quit. Apparently, the windowed mode is really
slow on old Intel machines, too. Full screening it is enough to bodge
the entire system session until the machine is remotely rebooted.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Change the peak sphere positions so they float on top of the bottom or
the bars, instead of clipping into them.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Add a dedicated spectrum visualization window, and add the necessary
hooks to start its event timer if playback is already running when it is
first opened.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Enable 8x multisampled anti-aliasing, to improve the appearance of the
spectrum on non-Retina/HiDPI displays. It can't really hurt on HiDPI,
either. Hopefully this won't cause it to use a whole load of GPU
resources, more than is reasonable.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Disable color fringing and motion blurring, which were causing artifacts
with the transparent background.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Since we use a non-default path in the repository to store shared hooks,
it needs to be configured on a freshly cloned repository before it can
be usable.
Yeah, I forgot to follow my own directions before working on the project
for quite some time. The error crept in at the following commit:
2aa3ddd545 - Icon replacement, and team ID
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Add options to the Appearance preferences page to allow changing the
spectrum's projection between a 2D-like one and 3D perspective, and add
options to change the bar and peak dot colors.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Introduced a brand new spectrum view based on SceneKit, with a scene
created by @kddlb and then altered by me to add the peak spheres. This
new scene should be lighter on display resources, even though it's fully
3D instead of a vector 2D scene done in Cocoa drawing primitives.
Co-authored-by: Kevin Lopez Brante <kevin@kddlb.cl>
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
FFmpeg processed files may also contain the LAME tag magic of 'Lavf' or
'Lavc', not just 'LAME'. Missed this when I was maintaining the FFmpeg
code that handles this, or at least adding iTunes support to it.
Fixes#250 again.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Update includes turning on system generated icons for all file types,
as well as adding several new file types from VGMStream that I missed
the last time around. Also includes some new fields that Xcode added in.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Update the Info.plist generator to emit file type definitions which use
system generated icons in place of the legacy icons in the app bundle.
Also include the new LSHandlerRank field. And also add a definition for
the scripting definition, which I accidentally added to the Info.plist
manually when I fixed scripting.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Apparently, Info.plist, as generated by Xcode, is perfectly fine with
raw apostrophes in the source code, and doesn't require it to be an XML
entity.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Fixed an issue with individual files that reference single subsongs
inadvertently dumping all tracks in the referenced bank to the playlist,
instead of only adding the one bookmark or txtp file. Now it matches the
behavior of foobar2000.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This time, a two-fer. First, ensure that file start seeking still skips
over the Xing/LAME header packet properly. Then, ensure that decoding
the last desired packet of the file does not indicate having decoded
more sample data than desired, which may have caused errors when
resuming playback position on restart and then smoothly transitioning to
the next track.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This is a possible fix for another gap issue I experienced, and may be
exposed by seeking from the start of the file without decoding first.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This error was caused by the necessary fix of the previous commit, only
it caused something completely different. Due to the fact that MP3 is
included in the list of formats supported for embedded CUE Sheets, the
open stage performs a seek to the file start after opening the file,
even if there is no sheet embedded. And the resulting seek was supposed
to be a null operation, since the file was already at the start. But, as
a result, this reset the start skip counter to zero, and because the
offset wasn't backwards, but to the same position, it didn't reset the
skip counter to the start of track delay. So, as a result, start of
track delay wasn't being removed, introducing a gap. Now, this change
bypasses the seek function altogether if seeking would do nothing from
the current playback position. Whew.
Fixes#250 and MP3 gaplessness in general, surprised I didn't notice
this sooner myself, but I guess I didn't bother to verify whether my
change would break anything. Whoops.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
A backwards comparison led to seeking forward doing a full seek up from
the file start, and seeking backwards being a non-functional operation,
so the file would just continue playing as if there were no seek.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The code now requires a variable to be set if Display Lists are to be
skipped by setting display processor interrupt as the bypass code is
supposed to. Also handle unsupported Ucode by calling the low level RSP
emulator instead.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Reverted 7f3da31b45, and reverted a past
commit of some sort. Now adding URLs and opening files from the Open...
option will obey the preferences for playlist adding, including modifier
keys, if used.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Add safety check to check if a device is actually alive when enumerating
it, and also add nil pointer checks for the device name before trying to
CFRelease it. Fixes a rare crash on device add/remove cycle, such as
Bluetooth headphones.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The total frames count in the iTunSMPB header is the encoded length, so
add the start and end padding to it for the decoder implementation,
which expects this variable to contain the total decodable length
including the start and end padding. Fixes gapless decoding of iTunes
files.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This dictionary was replaced with an inline literal declaration, but
this defines an immutable dictionary. Change it to a mutable copy.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Shifting negative numbers to the left is undefined behavior, so replace
with a multiply operation instead.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Enable HLE processing for USF playback, based on previous commit filling
out the HLE operations list. It should be safe to enable it again now.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Include preliminary overload effect for MP3 and CBFD HLE operations,
based on a pull request from upstream. This should make the HLE pretty
much sound for general use once again.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The resampler wasn't being given enough room to flush its final output,
so a function was added to determine the current output latency, and
more sample data is requested, allowing the full output flush to occur.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
These two changes fix playback issues with either starting in the middle
of the playlist on a really short file terminating immediately instead
of queueing more files (InputNode.m), and issues with starting playback
at all on the end of a playlist on a short file. (OutputCoreAudio.m)
Fixes#246
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Just in case anything using the implementation ever needs to request
less sample data than would be returned by the resampler, it should be
able to return a remainder and keep extra remaining samples, if any.
However, the way Cog currently uses it, it would not be likely to run
into this scenario.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Fixes to the resampler wrapper, such that it will survive some close
encounters with the edge of the buffer, if necessary. Also so it will
obey the buffer size limit for the output buffer.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Sorry about that, everyone. I didn't mean to make it look like I
was freezing out my audience by assuming a portion of them support
the every move of their government.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The lineage of this library was not as obvious to me as it should have
been, considering the country of origin. While the developer has not
publicly stated their position on the invasion of Ukraine, they seem to
be in the anti-vaccine camp, which is disappointing to say the least.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Added the R8Brain notice to the credits html document, and added a link
to the Github repository to the README.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This rename is more in line with what R8Brain does in its example code.
No actual behavioral changes to the code, however.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Report the correct codec name for WavPack files. An info refresh will be
needed for it to take effect on existing playlist entries.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The cache thread should have an autoreleasepool around the release loop,
because it will be freeing Objective C objects periodically.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Promote the Plugin Controller source file to Objective-C++, and add a
simple data cache that holds on to requests for up to 5 seconds after
their last access, for preventing spammed requests from hitting files
over and over. This is apparently really relevant to the CUESheet reader
and its embedded CUESheet handling, as that tends to reread the same
file over and over as it populates the playlist with tracks. The nested
reader can also lead to repeated reading even on files without CUESheets
embedded.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
A variable wasn't being used, except in debug builds. Comment out its
use and only skip over the field in the LAME header.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This should improve performance slightly again, as there were some ARM
code paths that weren't being enabled for ARM64.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
There was a stupid bug in the previous commit I made, which caused local
or seekable MP3 files to crash the player on decode. This fixes that, by
checking that a packet has actually been decoded before touching the
packet info structures. Dumb, dumb, dumb error on my part.
Fixes#244
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Support the weird scenario of format changes mid-stream. Probably
highly unlikely, and likely to break things if it does occur, but
whatever, it might actually happen in some weird file.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The current buffer size argument is used to determine if a buffer should
be allocated on the next run. Just in case something reuses the same
decoder instance.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
There were several warnings due to the capitalization of the header
paths, and due to unused functions that are only required by the text
CUESheet parser, and we're only using the CUESheet generator, which has
been heavily modified to emit NSString output rather than a file on
disk.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
For one thing, improve it so that if the tracknumber field is present,
but zero, it doesn't show the number sign in the spam. For the second,
only show the track artist field if it differs from the album artist.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
No idea if this brings a noticeable improvement, but it probably makes
better sense to only do the division step one time instead of doing it
twice interleaved when processing stereo files, which are the most
common scenario anyway.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Replace libsoxr dylib with a static library, and also build the two
architectures separately, to allow for platform-specific optimizations
to be employed for both. This also reduces the size of the CogAudio
framework by a few hundred kilobytes, as we eliminate unused code paths
better this way.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Now Cog supports freeformat MP3 once again. The plugin has been extended
to include sample accurate seeking, accurate length probing of files
missing headers, and iTunes gapless info reading using libid3tag.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Artwork deduplication should be done with hashes, not by full data
comparison. This should be a lot faster loading artwork from files now,
especially if the playlist already contains a lot of unique artwork.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
If starting playback from a given playlist entry, or selection, then
start shuffle mode from that track. Otherwise, start shuffle from the
beginning of the shuffle list.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
When in shuffle mode, start playback on the first item in the shuffle
list, rather than the selection, or the start of the playlist.
Fixes#241
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Added commands to control playback: play, pause, stop, previous, next.
Also added a spam property to PlaylistEntry, to return the formatted
spam string for the playlist entry, which is currently limited to the
playing item.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
When the option is enabled, and playback comes to a completion, the
player will quit on its own.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This stupid setLevel default was something suggested when making a
window a drag target, and I was observing a setLevel for a window
control, not for a window itself. I should not have set that in the
first place.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Since 10.13 doesn't want to observe the auto sizing attribute of the
field properly, gotta use the tiny font size that the field is already
configured to use.
Should fix#243
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Updated the FLAC library to what is the official release of 1.3.4,
although I already had all the commits from that version prior to this
update.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This small change brings the decoding more in line with what ffplay
does, and allows, for example, John McLaughlin.wma to play without
interruption from the stream warnings throughout the file.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This fixes#126 and brings back basic automation support. The basic
currentEntry object will return an object that can enumerate the track
metadata or the file URL of the currently playing track. More automation
suggestions are welcome, including playlist manipulation, or playback
control.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Xcode touched the Info.plist and fixed these, and I changed the file
type association definitions to print the correct thing in the future.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Apparently, the sort descriptors are going by data members of the array,
not by the column identifiers, or their textual contents.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Unfortunately, the track number column will always bug out and pop the
indicator back over to the Album Artist column. No way around it. The
control is just buggy like that.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This is a more correct method of identifying the supported classes to
coalesce into unique pointers through the storage array. I completely
forgot about this method, oops.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This allows for TagLib to handle artwork reading where the file built-in
readers fail, such as the FFmpeg reader, which would require parsing the
stream data for artwork packets, a really wacky convention to have.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Strings read from the database were not being stashed in the memory
store, which caused things like blank tags instead of correct metadata.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
IN A.D. 2101, WAR WAS BEGINNING. *boom*
Yeah, this was a dumb bug, I didn't realize that AUAudioUnit would just
arbitrarily ignore my configured block size and request a different one.
The AirPods Pro will just request 480 instead of the 512 I ask for, so
let's instead support variable block sizes, and only take up to the last
4096 samples of the chunk fed to the output device.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Significantly reduce the memory footprint of adding tracks to the
playlist, by coalescing the NSString and NSData objects in the info
dictionaries as they are being loaded in the background, into a common
data set which will then be discarded when the whole job is completed.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Added a string dictionary for deduplication of metadata, and actually
initialize both it and the art dictionary on startup, so they actually
work like they should.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Art read from external files supports more formats than previously
listed here. Amend the list accordingly.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Stream metadata could be in any encoding, not necessarily UTF-8. Handle
this in an appropriate way.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The new spectrum mode is linear frequency. Both modes also now have a
lower range of 10Hz, where possible.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Downmixing should no longer be necessary, unless someone actually tries
to emit up to 64 channels, while we support only 32 channels, but really
only 18 channels. Also read the channel layout field from the decoder,
so that the speaker layout will propagate from the files to the player.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The equalizer needs to apply its presets to the new settings variables
every time the preset changes, even when it happens with no dialog open.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
vDSP functions expect their input and output pointers to be aligned to
an even four values. Correct this by aligning all pointers. The
allocated buffers used for one parameter should already be aligned
somewhat, but align the incremented positions used on some of them so
that the vDSP functions don't misbehave. Also align the volume scaler
input by doing scalar math until the pointer is aligned prior to calling
vDSP_vsmul. Also, change 16-bit and 32-bit scale to use vsdiv instead of
vsmul with a really small number already divided into one.
Fixes the test vectors that were sent in extrapolating incorrectly due
to their final blocks having uneven sample counts, resulting in
unaligned pointers.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This doesn't fix an outstanding issue which will be fixed by the next
commit, but it does fulfill a request.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
A bad sample scanner and cleaner will point out in the log whenever a
bad sample, such as infinity, or Not a Number, or even huge values over
±2.0, in case some piece of code, or a decoder, or even a bad file, has
taken over the output.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The original didn't really handle backwards versus forwards differently,
as far as the predictor coefficients should have been, as they probably
should have been reversed for a different direction window.
This didn't fix my problem, though, but did possibly expose something
else to mess with.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
In the rare event that we're somehow playing decimated DSD at full
sample rate instead of resampling, only the start needs to be skipped,
and the end needs the input to the decimator padded to flush it, but
nothing needs to be truncated from the end of the output in that case.
Still, mostly pointless, since next to nobody will be outputting 384 kHz
from their Macs, in any case, much less unprocessed DSD.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
We should be extrapolating right over top of the DSD decimator latency,
rather than in front of it. Yeah, that'll do.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
For streams offering a three way split in their ICY metadata blocks,
support album/artist/title using that three way split. Otherwise do the
usual of artist/title, or blank artist if there's no hyphen to split on.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
For some reason, this sometimes gets set to nil. Fix to refer to the
current track in that case.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Building libogg, libvorbis, libvorbisfile, libFLAC, libopus, and
libopusfile out of tree, to utilize their projects' CMake build scripts,
and also enable any platform optimizations that may have been missing.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Reduce the virtual resolution to match the actual resolution, and set
the analyzere frequency to Nyquist of the audio input, as it seems to
behave as if the entire range of the input FFT bands are up to the
specified frequency, rather than half of it. Otherwise, we lose half of
the frequency range provided by the input data.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The system AIFF reader seems unable to read some really old files, so
enable FFmpeg to do so instead.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Flatten EQ button should remember that the preset is set to "Flat", and
drawing on the equalizer or changing sliders should remember that the
preset is on "Custom".
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Metadata versus properties merging, correctly merge over empty fields if
they are assigned with empty strings or zeroed numbers, instead of only
merging over completely missing fields.
Fixes emailed bug, CUE Sheet metadata reading, primarily.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Support overwriting empty fields of NSNumber or NSString form with
values from the merging dictionary. Correctly overwrite the value from
the first dictionary with values from the second if the first contains
empty strings or zeroed numbers.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Prioritize "cuesheet" Vorbis tag over binary CUESheet tag, as the former
can contain metadata, while the latter cannot.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
For some reason, they were marked "navigational", because I accidentally
chose the Info inspector button as the button to dupe to create them in
the first place.
Fixes#237
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
There is only one appcast to choose from, and it has been this way for
quite some time now, so simply make it final.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Among the many:
- Spaced out the equalizer settings from the preamp slider
- Propery synchronize the bands' state with the stored settings
- Properly store the setting for Custom mode when drawing on the bands
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The quality of the equalizer dialog is now up to par with what we had
before, minus all the crashes.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The reader should have been skipping the properties of CUE sheets when
reading the referenced data for the inner files.
Fixes#235
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Improvement includes greatly reducing the CPU usage by not using an
NSImage based painting system.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Borrowing some DFT code from deadbeef, this implements a simple spectrum
visualization into the main toolbar of the app.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The file metadata should be merged into the CUE Sheet metadata, as we
want the CUE Sheet to take priority, wherever it happens to have fields
set.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
There is a missing effect in the relevant tracks from Conker's Bad Fur
Day, an overdrive effect.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The info inspector xib still referenced the blank zero formatter, left
over from before disc support was added.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
- Fix Vorbis, Opus, and FLAC tag reading
- Fix Vorbis getting a 0 length if passing through the CUE Sheet reader
- Implement support for FLAC binary CUE Sheets
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The warn logging was preventing working USFs from playing due
to warnings occurring during the playback that didn't otherwise
affect the ability to play the files.
For big endian sample formats, endianness can be swapped using Clang
specific byte swap functions, which are present in all supported
versions of Xcode.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Simple upmixing algorithms now use Accelerate framework functions
instead of complex loops, and the HRIR filter now supports forcing
stereo output to any channel output configuration that has at least
front stereo speakers.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
CUE reader was crashing due to nil metadata pointers, which the new
inplace initializer I was using didn't like. Change it to use a mutable
regular dictionary, and only add items if they're not nil.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Now file hint stashes the whole file in memory, so that any other
threads reading the file at the same time will just grab the same memory
block and read it, rather than opening the file repeatedly.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Two were potential memory leaks on file errors, one was a guaranteed
leak when reading metadata.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The same file may be accessed from other threads, thanks to this cache
thing. Synchronize access so that only one thread is reading the file at
a time.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The SID decoder uses a hint cache so that when the library requests the
current file open, it will return the exact file already opened, rather
than opening it again. Unfortunately, I was closing the file regardless,
and sometimes, libsidplayfp will reopen the file multiple times, from
other threads, even.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This update is from my personal fork, and includes synchronization
around two places in ReSIDfp that use static global tables as caches.
Without the synchronization, there were errors in playback and even
crashes.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Art ID should be set on new files when they are stored into the
database, and the album art property should be affected by assigning to
the artId property, since it affects the caching identifier.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Now cache around NSData objects of individual pieces of album art,
unique by their byte contents. And the artwork image cacher will also
use the art ID keys from the database as the cache keys for NSImages,
so they'll not only be only read once per unique image, but also tracks
can have unique artwork per track, if the files so feature it.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Where TagLib is not being employed, use FFmpeg to read tags where
possible. This allows reading tags from files like IFF. It reads it
through properties, otherwise allowing tag readers to function like
usual.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
When decoder is redirected to the internal silence decoder, show an icon
on the playlist indicating a playback error.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Playlist now supports dragging copies of URL references to other apps,
including Finder, and possibly other audio players. The chosen drag
operation is to copy files.
Fixes#75
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The shuffle list builder was encountering errors when some album tags or
empty album tags led to empty lists.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Implement support for DFF, WSD, and IFF formats, and all DSD formats
carried within, using our own DSD decimation method instead of relying
on FFmpeg to do it.
Fixes#165
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Xcode loves to tweak coordinates by fractional values just opening the
darn thing in the resource editor.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Added buttons to remove duplicates and remove dead items, in case anyone
finds themselves needing these options often enough to want to put them
in their toolbar instead of using the menu.
Fixes#225
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Increasing the threshold for the width of the tooltip to the right of
its intended location to a more generous value, makes it appear on the
left side sooner rather than later, but should fix positioning issues.
Fixes#226
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
When feeding packet to decoder, attempt to retry another packet when it
reports invalid data.
Fixes#97
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Instead of rendering the ReplayGain values into the stream on decode, as
it did before. This allows exposing the values to the properties dialog.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Now it should flow playback correctly to the next remaining track after
the block of deleted tracks. And if the user deletes the next queued
track, it will still be queued to flow past the deleted block. If the
user undoes their deletes and restores the tracks, playback will resume
after the originally deleted track.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
These events were split up in handling after this driver fell out of
use. It needed updating with the latest split handling design.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Among the changes, range checking on lots of things, and especially,
the pre-render-loop backlog handler, which rendered samples left over
from the previous call, would possibly over-render by way too much, due
to a stupid backwards subtraction I managed to type into there. This is
totally fixed now.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This resulted in horrible things, the generic N to N upmixer was leaving
unmapped channels as uninitialized memory. This fixes horrible things
happening for people with interfaces with more channels than the source
file, frequently when the source file is stereo, or if the file is mono
and a center channel is present.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The dynamic metadata functions should only activate for unseekable
streams, not seekable streams, and not local files.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
HTTP Reader now supports limited seeking backwards even in streams, so
seek back to file start for repeated file tests, since there are at
least a few inputs that all claim to support things like Ogg containers.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
There were some leftover modifications to the 0.5.x tree I was using,
which were supposed to be speed optimizations, but they're probably
pointless anyway. The NEON optimizations were especially pointless,
since this plugin version isn't used on any macOS version that runs on
Apple Silicon.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
_mm_malloc and _mm_free are apparently based on intrinsic functions,
and only exist on Intel or older macOS targets. So removing them in
favor of posix_memalign.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Now the output is restarted on the current file at the current position
if the output format has changed. This should resolve the issue finally.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This was buggy as hell, and resulted in errors. Now the user should
restart playback if they change output device formats.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Sample format can now change dynamically at play time, and the player
will resample it as necessary, extrapolating edges between changes to
reduce the potential for gaps.
Currently supported formats for this:
- FLAC
- Ogg Vorbis
- Any format supported by FFmpeg, such as MP3 or AAC
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
TrueAudio will now read APE tags, and if I should start writing tags
some day, will prefer creating APE tags if no tags exist.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The ChunkList wasn't clearing the remover entered flag when the chain
was empty. Now it does, so it will shut down correctly.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Code ordering was wrong, it was writing the output samples repeatedly
for each input speaker, now it will only write them once.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
By applying copious amounts of autorelease pools, memory is freed in a
timely manner. Prior to this, buffer objects were freed, but not being
released, and thus accumulating in memory indefinitely, as the original
threads and functions had autorelease pools that scoped the entire
thread, rather than individual function blocks that utilized the new
buffering system. This fixes memory growth caused by playback.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This fixes the dynamic length field not updating correctly after a track
info reload, which breaks the seekbar when reloading the current track.
Fixes#227
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Channel config should not contain duplicate channels, or unsupported
channels. Also fix a memory leak from not freeing the AudioChannelLayout
structure allocated previously.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This implements channel masks for inputs where applicable, namely the
CoreAudio decoder, FFmpeg, FLAC, and WavPack. All others will still use
guessing from the channel number.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This implements the basic output and mixing support for channel config
bits, optionally set by the input plugin.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The volume should have been twice what it was, because I got this scale
wrong. The correct scale for Accelerate inverse FFT is 1/4 per sample,
not 1/8 like I accidentally misread while rewriting a convolver for the
umpteenth time from scratch.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Rewrite attempt number two. Now using array lists of audio chunks, with
each chunk having its format and optionally losslessness stashed along
with it. This replaces the old virtual ring buffer method. As a result
of this, the HRIR toggle now works instantaneously.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Import a feature change that improves decoding speed on Haswell or newer
Intel processors. No effect on Apple Silicon, which doesn't support the
feature under Rosetta 2, and the ARM64 build doesn't need the changes
anyway, as the code already did the right thing.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This fixes a possible crash with seeking operations, especially with
Audio Unit plugins. Fix implemented in foo_midi and imported here.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
After all this rewriting, down or upmixing the audio is now handled with
the lowest latency possible, meaning that toggling the HRIR option now
takes effect immediately.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Tiny files complete fetching within the scope of the open function, so
the URL session task would have completed already. Now the function will
accept the data, and allow reading it.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This is a fixed point implementation identical to Microsoft's original
algorithm. Or at least I assume it's Microsoft's. It was actually
adapted from hdcd_decode.exe, which was adapted from somewhere else.
It's entirely in fixed point math now, so it's fairly deterministic.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
When deleting the currently playing track, stop playback, because the
player engine doesn't like dealing with the current playing track not
actually having a playlist reference to go with it. Better stop playback
instead, as a safety check.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This fixes the ability to configure the MIDI synthesizer properly, after
commit 7e5107d431 was applied.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The timing of block based mode was kind of off. Now it should be just
fine. Thanks to testing on Windows in foo_midi.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This bug prevented zero length or unknown length files, such as FLAC
files with no sample count in the header, or audio streams, from playing
properly, and clipped their output to the 0 samples indicated by the
field. Now it will simply allow wrapped files to decode until they stop
producing output.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The end of input queueing, which can go nuts when there are a lot of
short files, should be terminated when the user asks the player to stop.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Flush the resampler when the source file terminates, so that it outputs
delayed samples properly. This fixes gapless decoding of resampled
files.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Tooltip should appear on the left side when the volume bar is close to
the right side of the screen.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
From now on, all contributions, and all issues and pull requests posted,
must adhere to this document. I would like people to remain civil on my
project, if they possibly can. If they cannot, they will be ejected.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Replace individual virtual buffers with large _mm_malloc blocks at a
time, then dole out chunks of those buffers as the nodes need them.
Should reduce memory contention a little bit.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This seals up a major memory leak of the playback state whenever a chain
is released on stop or on manual track change. CogAudioMulti was
retaining the input node due to its listeners, and InputNode was not
releasing the listeners when asked to stop running. This is fixed now.
Fixes#221
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Now with a slightly more appropriate icon for non-retina displays. I
still want to consider what to do with this, since it still looks a bit
blurry on 1x displays.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This prevents the apply presets function from resaving the preset number
and retriggering itself repeatedly, which would cause a crash.
Fixes#223
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Store custom presets on value changes, on half second intervals, as the
listener observes the user changing the settings.
Fixes#222
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Disable automatic update checking on startup for debug builds. Prevents
a crash from occurring when it attempts to retrieve the version number.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Replace "midi.plugin" with "midiPlugin", as per the value naming
conventions that Apple set out. Migrate the old value if found.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Added a logging method that indicates starting playback of a given URL,
and added a debug build only logging of every metadata load event.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Only crashed with division by zero error on Intel, not on Apple Silicon.
Funny that. Sending the fix upstream, too.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
File channel remapping was incorrectly only working for 1-7 channel
files, not 8 channel files. Fixed that.
PLEASE NOTE: This will be my last commit and build for over a week, I
promised myself I would stop, and this is the last straw. These are the
last two, I promise. No more bug fixes this week, until at least the 7th
of February. Please, I'm begging you.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
7.0 downmix was passing parameters to cblas_scopy backwards, and WAV
files report "host" endian, not "native".
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
We're not using Gitlab's CI anyway, and they don't offer free Mac
build bots at this time, either. It just keeps spamming me with build
failure notices every time I push commits to that mirror.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The patch is now updated to exactly what I sent to the ffmpeg-devel
mailing list for hopeful inclusion in the latest release of FFmpeg.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The old quadra method was broken, too. Now it uses a simple linear
difference sliding scale for the extra points, which seems to work much
better for the 20 kHz band. And the 16 kHz band doesn't get predicted to
heck any more, either.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Added a keyboard shortcut for the equalizer menu item, added a user
contributed button for an equalizer toolbar button, and replaced the
randomize playlist button with something different from the same user.
I had to redo the randomize button, because template PDFs don't support
white cutout shapes, but instead need to be formatted as hollow spaces
in the paths. Naturally, I couldn't figure out how to do this with
Inkscape the right way, so I rendered the original to a 1024x1024
bitmap, then imported that into a new document and traced it. Meh. I
need a better icon anyway, but this looks okay on the toolbar for now.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Track entries are updated when files are added and their metadata is
later loaded. The refresh cycle was failing, because dbIndex was unset
in the new tracks, for some reason. Now it will set this when updating
the track item, assuming it read from the database in the first place.
This fixes metadata being loaded properly on adding tracks to the
playlist, as well as reloading track data manually.
Fixes#218, hopefully.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
... also disable use of AudioToolbox codecs, and use only bundled codecs
and libfdk-aac for AAC input. This is required for HLS at least, as
Apple's system codecs didn't really like the network streams that were
provided by HLS streaming stations.
Also reshuffle the input priorities between Core Audio input and FFmpeg
input, so that they were the way they were before I messed with things a
while back. This puts FFmpeg back at the top, using bundled codecs where
supported.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Also disable AudioToolbox codecs, as they don't really like network
streaming so much. Use bundled codecs instead.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The built-in M3U container parser should not be used for HLS playlists,
so they should end up in the playlist as-is, so that inputs can parse
them in real time.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
For Playlist Entries that are not File URLs, return the full absolute
URL for path queries, so the playlist path column will show the full
URL instead of a useless reduced path string.
Fixes#214.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The thread wait on shutdown had the potential to lock up waiting for the
thread to shut down. Now it should at least spam the semaphores, so that
the thread should progress to shutdown a lot quicker.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
If there's no configured SoundFont bank, or if the selected bank has
gone missing, and the user has configured the player to use the
FluidSynth driver, fall back to the system DLS Synthesizer, which has
its own Roland bank to fall back on if unconfigured.
Also, whether falling back, or already on an AU synthesizer, don't fail
if there's no bank configured or found. DLS doesn't explicitly require a
bank, and most other synthesizers of interest would not require a bank
either.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The file prober in FFmpeg expects that when the read function reaches
end of file, it returns AVERROR_EOF, not zero. Otherwise, it will loop
endlessly until the process is terminated.
Fixes#217.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Add a safety fix for pausing and shutting down, so that we don't call
into AUAudioUnit's stopHardware function unless the stream has already
been started by the output.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
For some incredibly dumb reason, PSF files get into FFmpeg 5.0, then
just sit there and lock up, reading them forever and ever, doing nothing
useful. Add a bodge to detect PSF files by signature and ignore them in
the VGMStream container parser, and all other parts of VGMStream in Cog.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This should fix some coding issues, and also fix some potential memory
leaks in the file verifier, assuming it didn't already release the
files it was pulling the stats from.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Added a link to a downloadable set of HRIR presets, borrowed from the
HeSuVi project, which is on SourceForge, but inside of an executable,
therefore possibly a pain to extract.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The filter wasn't properly freeing its FFT setup state, and also was
unnecessarily null checking the pointers before passing them to the
aligned free function, which already does null checking.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Reduce the timing at which an end of file notification is sent to the
main thread from 16384 bytes to 8192 bytes. This may help with playback
of a lot of really small files, and skipping tracks.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Implement the ability to configure and select an HRIR preset to use with
the HRIR filter, or remove the preset. It will validate the file's
usefulness before setting it for the player to use.
Also, fixed back center channel filtering for 7.0 format audio.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This is needed for HeSuVi no-echo impulses, which are only one channel
per input channel, and mapping uses symmetrical mirroring of the input
set to create the surround effect, since there's no side-to-side delay
in these impulses.
This new virtualizer uses the Accelerate framework to process samples.
I've bundled a HeSuVi impulse for now, and will add an option to select
an impulse in the future. It will validate the selection before sending
it to the actual filter, which outright fails if it receives invalid
input. Impulses will be supported in any arbitrary format that Cog
supports, but let's not go too hog wild, it requires HeSuVi 14 channel
presets.
- Display playlist total duration in units up to weeks and down to just seconds, and only pluralize units as necessary
- Major change: Implemented a SQLite disk backed playlist, track data, and queue storage system, which will be synchronized from the player in real time, and will hopefully survive system or app crashes. Existing plist playlist will be imported on first run, and removed on shutdown.
NPIC can ask for a lot of metadata, but for now, provide it only what (at least I know) PlaylistEntry can provide. The biggest missing one was album art, so this change should be appreciated by those who do use it.
I don't know what it can do with the other metadata though, seeing at least on macOS, it can only do album/artist/track title/artwork.
* Fix look of position time field to match the rest of the UI.
* Fix typo.
* Improve position time display.
* Add days, hours support to position time display.
* Fix "Current Time" toolbar item geometry/layout.
* Don’t enforce leading double-digits in position time display.
* MainMenu.xib touched by Xcode.
* Implement and use MonospacedDigitTextFieldCell.
This way the digits of numbers in playlist columns consisting of mostly digits will be aligned vertically.
* Disable font scaling code without effect.
* Set "Current Time" toolbar item to use MonospacedDigitTextFieldCell.
* Improve SecondsFormatter.
* Merge in SecondsFormatter improvements from Play.
* Move formatter setup into XIB.
* Add CogTests.
These can later be used for integration tests.
* Add SecondsFormatterTests.
Tests are stubbed out.
* Pouring foundation for SecondsFormatterTests.
* Implement -testPositive.
* Replace unsigned with int in SecondsFormatter.
* Implement negative support, tests.
* Rewrite SecondsFormatter in preparation for better readability..
* Rewrite SecondsFormatter for better readability.
* Add negative zero support.
* Improve SecondsFormatter readability.
* Refactor into -stringForTimeInterval: in SecondsFormatter.
* Cleanup.
* Mark TimeField as space-indented.
* Replace custom time formatting code in TimeField with SecondsFormatter.
* Cleanup.
* Improve SecondsFormatter format strings.
* Add internal type for time calculations.
Co-authored-by: Jan Weiß <jan@geheimwerk.de>
Now it should take priority for all supported formats, including MP3, so that reported broken file should play properly now. Not fixing FFmpeg outside of FFmpeg, someone can report the file to FFmpeg if they want to.
- Avoid creating an NSDictionary with NULL context object (https://github.com/kode54/Cog/blob/master/Audio/Chain/InputNode.m#L81 passes NULL as context, so this must be handled in NSDictionary creation
- When calling addObserver, downgrade options from NSNumber * to NSKeyValueObservingOptions (aka NSUInteger)
Not sure why this would be specific to Apple Silicon...
- Restructure main window a bit more
- Remove attempt at SF Symbols icons for now
- Add Now Playing popout to Stacks style main window, tooltip instructs to click to select the current track in playlist
- Disable libFLAC plugin on macOS 10.13 and newer, letting Core Audio handle it instead. Apparently, libFLAC is not really ready for Apple Silicon yet.
If compiled with the macOS 10.14 SDK, MAP_JIT will be defined and passed
as a flag to mmap to allocate memory for the dynarec, but this flag will
cause mmap to fail if running on macOS 10.13 and below; on macOS check
the OS version at runtime, set and cache the appropriate flags for mmap.
- Update BASS and friends to latest versions
- Remove unused unmo3 library
- Add entitlements to Hardened Runtime for unsigned plugins (for
AU MIDI playback), and for executable memory use (for the USF
recompiler)
- TODO: Replace Growl branding with generic notification icon
- Change MIDI flavor default to 'default (auto)'
- Fix MIDI preference page to correctly enable the flavor option only where applicable
- Fix SCVA player to reset existing instances reliably
* id3v1 tags are now displayed in default windows charset rather than always being latin1
* only reading required bits from encoding byte (cures some faulty tag problem)
* faulty utf16 headers without endianness will now display correctly as well
Added File Tree contextual menu (Add to Playlist, Show in Finder, etc.).
File Tree and additions to play list now use Finder sort order.
File Tree Root can be set via its popup menu or drag and drop from File Tree.
Alias names are now shown in File Tree (aliases are still resolved).
Added option to skip reading of cue sheets when adding a folder to play list.
Removed album/artist name from menu thanks to Fiona Apple and some clever person who thought it would be funny to shove the entire album name into the tag.
PluginController now uses the decoder if a properties reader class is not found.
PropertiesReaders should still be created if performance can be improved if code is only reading properties.
# The style used for all options not specifically set in the configuration.
BasedOnStyle: LLVM
# The extra indent or outdent of access modifiers, e.g. public:.
AccessModifierOffset: 0
# If true, aligns escaped newlines as far left as possible. Otherwise puts them into the right-most column.
AlignEscapedNewlinesLeft: false
# If true, aligns trailing comments.
AlignTrailingComments: false
# Allow putting all parameters of a function declaration onto the next line even if BinPackParameters is false.
AllowAllParametersOfDeclarationOnNextLine: false
# Allows contracting simple braced statements to a single line.
AllowShortBlocksOnASingleLine: true
# If true, short case labels will be contracted to a single line.
AllowShortCaseLabelsOnASingleLine: false
# Dependent on the value, int f() { return 0; } can be put on a single line. Possible values: None, Inline, All.
AllowShortFunctionsOnASingleLine: None
# If true, if (a) return; can be put on a single line.
AllowShortIfStatementsOnASingleLine: true
# If true, while (true) continue; can be put on a single line.
AllowShortLoopsOnASingleLine: true
# If true, always break after function definition return types. More truthfully called ‘break before the identifier following the type in a function definition’.
AlwaysBreakAfterDefinitionReturnType: false
# If true, always break before multiline string literals.
AlwaysBreakBeforeMultilineStrings: false
# If true, always break after the template<...> of a template declaration.
AlwaysBreakTemplateDeclarations: true
# If false, a function call’s arguments will either be all on the same line or will have one line each.
#BinPackArguments: true
# If false, a function declaration’s or function definition’s parameters will either all be on the same line or will have one line each.
BinPackParameters: true
# The way to wrap binary operators. Possible values: None, NonAssignment, All.
BreakBeforeBinaryOperators: None
# The brace breaking style to use. Possible values: Attach, Linux, Stroustrup, Allman, GNU.
BreakBeforeBraces: Attach
# If true, ternary operators will be placed after line breaks.
BreakBeforeTernaryOperators: false
# Always break constructor initializers before commas and align the commas with the colon.
BreakConstructorInitializersBeforeComma: false
# The column limit. A column limit of 0 means that there is no column limit.
ColumnLimit: 0
# A regular expression that describes comments with special meaning, which should not be split into lines or otherwise changed.
CommentPragmas: '^ IWYU pragma:'
# If the constructor initializers don’t fit on a line, put each initializer on its own line.
# The number of characters to use for indentation of constructor initializer lists.
ConstructorInitializerIndentWidth: 0
# Indent width for line continuations.
ContinuationIndentWidth: 0
# If true, format braced lists as best suited for C++11 braced lists.
Cpp11BracedListStyle: false
# If true, analyze the formatted file for the most common alignment of & and *. PointerAlignment is then used only as fallback.
DerivePointerAlignment: true
# Disables formatting at all.
DisableFormat: false
# If true, clang-format detects whether function calls and definitions are formatted with one parameter per line.
ExperimentalAutoDetectBinPacking: false
# A vector of macros that should be interpreted as foreach loops instead of as function calls.
#ForEachMacros: ''
# Indent case labels one level from the switch statement. When false, use the same indentation level as for the switch statement. Switch statement body is always indented one level more than case labels.
IndentCaseLabels: true
# The number of columns to use for indentation.
IndentWidth: 4
# Indent if a function definition or declaration is wrapped after the type.
IndentWrappedFunctionNames: false
# If true, empty lines at the start of blocks are kept.
KeepEmptyLinesAtTheStartOfBlocks: false
# Language, this format style is targeted at. Possible values: None, Cpp, Java, JavaScript, Proto.
# Language: None
# The maximum number of consecutive empty lines to keep.
MaxEmptyLinesToKeep: 1
# The indentation used for namespaces. Possible values: None, Inner, All.
NamespaceIndentation: All
# The number of characters to use for indentation of ObjC blocks.
ObjCBlockIndentWidth: 4
# Add a space after @property in Objective-C, i.e. use \@property (readonly) instead of \@property(readonly).
ObjCSpaceAfterProperty: false
# Add a space in front of an Objective-C protocol list, i.e. use Foo <Protocol> instead of Foo<Protocol>.
ObjCSpaceBeforeProtocolList: true
# The penalty for breaking a function call after “call(”.
PenaltyBreakBeforeFirstCallParameter: 1000
# The penalty for each line break introduced inside a comment.
PenaltyBreakComment: 1000
# The penalty for breaking before the first <<.
PenaltyBreakFirstLessLess: 1000
# The penalty for each line break introduced inside a string literal.
PenaltyBreakString: 1000
# The penalty for each character outside of the column limit.
PenaltyExcessCharacter: 1000
# Penalty for putting the return type of a function onto its own line.
PenaltyReturnTypeOnItsOwnLine: 1000
# Pointer and reference alignment style. Possible values: Left, Right, Middle.
PointerAlignment: Left
# If true, a space may be inserted after C style casts.
SpaceAfterCStyleCast: false
# If false, spaces will be removed before assignment operators.
SpaceBeforeAssignmentOperators: true
# Defines in which cases to put a space before opening parentheses. Possible values: Never, ControlStatements, Always.
SpaceBeforeParens: Never
# If true, spaces may be inserted into ‘()’.
SpaceInEmptyParentheses: false
# The number of spaces before trailing line comments (// - comments).
SpacesBeforeTrailingComments: 1
# If true, spaces will be inserted after ‘<’ and before ‘>’ in template argument lists.
SpacesInAngles: false
# If true, spaces may be inserted into C style casts.
SpacesInCStyleCastParentheses: false
# If true, spaces are inserted inside container literals (e.g. ObjC and Javascript array and dict literals).
SpacesInContainerLiterals: false
# If true, spaces will be inserted after ‘(‘ and before ‘)’.
SpacesInParentheses: false
# If true, spaces will be inserted after ‘[‘ and before ‘]’.
SpacesInSquareBrackets: false
# Format compatible with this standard, e.g. use A<A<int> > instead of A<A<int>> for LS_Cpp03. Possible values: Cpp03, Cpp11, Auto.
Standard: Auto
# The number of columns used for tab stops.
TabWidth: 4
# The way to use tab characters in the resulting file. Possible values: Never, ForIndentation, Always.
+(NSArray*)fileTypeAssociations;// array of NSArray of NSString, where first item in array is the type name, the second is the icon name, and the rest are the extensions
+(float)priority;// should be 0.0 ... 1.0, higher means you get selected first, should default to 1.0 unless you know a reason why any of your extensions may behave badly, ie. greedily taking over some file type extension without performing any header validation on it
//For KVO
//For KVO
//- (void)setProperties:(NSDictionary *)p;
-(NSDictionary*)properties;
-(NSDictionary*)metadata;// Only to be implemented for dynamic metadata, send events on change
-(AudioChunk*)readAudio;
-(BOOL)open:(id<CogSource>)source;
-(double)seekToTime:(double)time;//time is in milleseconds, should return the time actually seeked to.
-(int)fillBuffer:(void*)bufofSize:(UInt32)size;
-(long)seek:(long)frame;
-(void)close;
@optional
-(void)dealloc;
-(BOOL)setTrack:(NSURL*)track;
// These are in NSObject, so as long as you are a subclass of that, you are ok.
\t<string>Cog has no use for your calendar information. Why are you trying to open your Calendar with an audio player?</string>\n\
\t<key>NSCameraUsageDescription</key>\n\
\t<string>Cog is an audio player. It will never use your camera. Why is it asking for permission to use your camera?</string>\n\
\t<key>NSContactsUsageDescription</key>\n\
\t<string>Cog has no use for your contacts information. Why are you trying to open your contacts with an audio player?</string>\n\
\t<key>NSLocationUsageDescription</key>\n\
\t<string>Cog has no use for your location information. Something is obviously wrong with the application.</string>\n\
\t<key>NSMainNibFile</key>\n\
\t<string>MainMenu</string>\n\
\t<key>NSMicrophoneUsageDescription</key>\n\
\t<string>Cog is an audio player. It does not, however, record audio. Why is it asking for permission to use your microphone?</string>\n\
\t<key>NSPhotoLibraryUsageDescription</key>\n\
\t<string>Cog is an audio player. Why are you trying to access your Photos Library with an audio player?</string>\n\
\t<key>NSPrincipalClass</key>\n\
\t<string>MediaKeysApplication</string>\n\
\t<key>NSRemindersUsageDescription</key>\n\
\t<string>Cog has no use for your reminders. Why are you trying to access them with an audio player?</string>\n\
\t<key>NSDownloadsFolderUsageDescription</key>\n\
\t<string>We may request related audio files from this folder for playback purposes. We will only play back files you specifically add, unless you enable the option to add an entire folder. Granting permission either for individual files or for parent folders ensures their contents will remain playable in future sessions.</string>\n\
\t<key>NSDocumentsFolderUsageDescription</key>\n\
\t<string>We may request related audio files from this folder for playback purposes. We will only play back files you specifically add, unless you enable the option to add an entire folder. Granting permission either for individual files or for parent folders ensures their contents will remain playable in future sessions.</string>\n\
\t<key>NSDesktopFolderUsageDescription</key>\n\
\t<string>We may request related audio files from this folder for playback purposes. We will only play back files you specifically add, unless you enable the option to add an entire folder. Granting permission either for individual files or for parent folders ensures their contents will remain playable in future sessions.</string>\n\
\t<key>NSMotionUsageDescription</key>\n\
\t<string>Cog optionally supports motion tracking headphones for head tracked positional audio, using its own low latency positioning model.</string>\n\