0.99.4

* fixed bug where `musikcubed` could crash while stopping.
* added `dark mode` awareness to Windows build.
* added `PortAudio` output driver.
* added support for Haiku OS.

--------------------------------------------------------------------------------

0.99.3

* fixed a bug on Windows builds where certain accented characters would not be
  correctly parsed when input via keyboard.
* updated accented character mappings for improved fuzzy search.

--------------------------------------------------------------------------------

0.99.2

* fixed an issue when scanning tags that could result in corrupted metadata.

--------------------------------------------------------------------------------

0.99.1

* fixed indexer issues related to last modified file time; some code was
  using 32-bit integers for timestamp comparison, leading to incorrect
  re-indexing.
* fixed some issues related to modifying and saving playlists in browse mode.
* fixed issues when searching for metadata with accented characters.
* fixed issue with FfmpegDecoder that was preventing .wma files (and possibly
  other formats) from playing properly.
* updated to taglib 1.13. vendor the library by default on unix platforms,
  and use pre-compiled version on windows. (also: remove source bundle).
* updated some default key bindings to be more cross-terminal-emulator
  compatible.
* updated ru_RU localization (@adem4ik)
* fixed Windows startup crash that was affecting some users
* merged upstream PDCurses changes.
* cleaned up vendoring for libopenmpt and libgme.
* fixed OpenBSD compile.

--------------------------------------------------------------------------------

0.99.0

* completely removed boost as a dependency across all projects; this is a
  huge milestone in the project, and will make it much easier to distribute
  stable builds moving forward.
* fixed issues with usernames on Windows that contain non-latin characters
* fixed issues displaying paths with non-latin characters in some parts of
  the app.
* fixed issue with directory scanning that may lead to incomplete indexing
* fixed issue where user's home directory may not be resolved correctly.
* reverted ViewPager2 changes in `musikdroid`, as there is a bug that is
  preventing fragments from getting re-initialized properly during the resume
  cycle.
* updated Simplified Chinese translation (@UM-Li)
* added Czech translation (@khagaroth)
* upgraded to c++-17 runtime

--------------------------------------------------------------------------------

0.98.1

* fixed album art extraction for xiph comments.
* fixed PulseAudio compile issue.
* fixed `musikdroid` app notification on Android 13 devices.
* fixed ancient metadata indexer crash when trimming whitespace from strings.
* fixed `pipewireout` to have more sensible default buffer sizes, and add the
  ability for the user to configure them.
* updated `musikdroid` dependencies and tooling, fixed a few warnings.
* merged latest upstream `PDCurses` code for Windows builds.
* sending `musikcubed` a SIGUSR1 will trigger a library rescan.
* fixed a bug when querying tracks by category with a filter.
* fixed a `musikdroid` bug that could cause the BrowseFragment to get into
  a bad state where search would no longer work.

--------------------------------------------------------------------------------

0.98.0

* added the ability to click the browse and tracklist headers to change filter
  options
* added the ability to click transport metadata to display a context menu with
  a list of actions for the current track/artist/album
* added the ability to search/filter in browse view; press `^F` to toggle the
  feature on and off.
* fixed a bug that could cause tracks to sort incorrectly if some tracks in
  the album have a disc number specified and others don't.
* added the ability to use `libelogind` or `basu` instead of `libsystemd` for
  the `mpris` plugin (@robertgzr)
* fixed ape decoding.
* some warning cleanups when using `wsprintw` (@trofi)
* further improvements to build system to remove OS-specific conditionals in
  favor of library detection
* added color output to various important cmake messages, making it much easier
  to spot check configuration issues.
* added support for the `piggy` debug tool to help with log collection and
  remote app monitoring. disabled by default.
* updated Windows build to use Visual Studio 2022
* updated Linux/macOS dependencies for standalone *nix builds: boost 1.79.0,
  openssl 3.0.2 (1.1.1n for rpi), curl 7.83.0, ffmpeg 5.0.1, libopenmtp 0.6.2
* updated sqlite to 3.39.0

--------------------------------------------------------------------------------

0.97.0

* no functional changes to the app
* finished re-architecture of build and app packing infrastructure to support
  "standalone"/"portable" builds for non-Windows platforms. these changes allow
  us to build a much smaller set of binaries for distribution that are more
  universally compatible across different versions of macOS and Linux
  distributions.

--------------------------------------------------------------------------------

0.96.13

* macOS and Linux only release that fixes standalone binaries.

--------------------------------------------------------------------------------

0.96.11

* added support for ffmpeg5 libraries.
* upgraded to ffmpeg5 for Windows builds.
* fixed WasapiOut to use high-quality, built-in resampler.
* added `allow_decoder_resampling` to WasapiOut to disable the high-quality,
  built-in resampler and rely on plugin resampling instead.
* fixed dialog background rendering in certain versions of ncurses.
* fixed duration calculation for float-encoded wav files.
* added additional PipeWire output debugging.
* rewrote build system and packaging scripts.

--------------------------------------------------------------------------------

0.96.10

* fixed `-rpath` for macOS build.
* fixed race condition in WasapiOut that caused the app to crash.

--------------------------------------------------------------------------------

0.96.9

* fixed `-rpath` to use `$ORIGIN` instead of `./` to appease `Feodra 35`.

--------------------------------------------------------------------------------

0.96.8

* updated `FfmpegDecoder` to perform resampling internally when `WasapiOutput`
  is in use; it's internal resampler seems to be much higher quality than the
  one used by WASAPI by default.
* fix data directory resolution logic wrt to XDG_CONFIG_HOME (@robertgzr)
* ensure TrackSearchLayout refreshes during metadata indexing (@ravensiris)
* fixed album duration calculation fencepost error (@PythonTryHard)
* added Spanish (es_ES) translation (@orestescm76)
* added support for Android Studio 4.2
* updated CMake scripts to be compatible with Homebrew installations that
  are rooted outside of /usr/local
* ensure static libraries are only resolved with necessary (@t123yh)
* fixed OpenBSD build
* fixed a PipeWire bug where volume may not get set properly.
* updated Scrobble logic to only post if at least 25% of the active track
  has been played.
* fixed a bug where user may be unable to nativate to the lyrics view
* fixed a low-level bug that could prevent layout update events from
  propagating up the view hierarchy.
* fixed a bug where the notification tray icon was not drawing properly on
  windows builds.
* fixed musikdroid notification falling out of sync with the currently playing track.

0.96.7

--------------------------------------------------------------------------------

* re-compile for Windows; Windows Defender was unhappy with the original
  binaries.

0.96.6

--------------------------------------------------------------------------------

* fixed some drawing issues with overlays/dialogs with certain versions of
  ncurses.
* added category-level (e.g. album, artist, etc) durations in browse and
  search views.
* upgraded the Windows builds to use ffmpeg 4.4, and removed usages of some
  deprecated APIs in FfmpegDecoder and FfmpegEncoder.
* fixed bugs where .wav files with embedded album art would play loud static
  for a second or two before the correct audio.
* added the ability to automatically resume playback on startup via new
  "advanced" setting called "ResumePlaybackOnStartup".
* fixed various minor bugs while browsing by directory.
* fixed bug where files with "long" filenames on Windows were not properly
  supported.
* added de_DE translation (dertuxmalwieder)
* updated default "change sort order" hotkey to ensure it doesn't conflict with
  some common terminal emulator defaults in UNIX environments.
* removed snap support. the default sandboxing rules were causing more problems
  than it was worth; even though it was possible to work around them, users were
  still getting confused.
* added an initial PipeWire output plugin; included by default on Ubuntu 21.04
  and Feodra 34.
* fixed some build issues where opting out of bundled TagLib didn't work
  properly.
* updated CMake build scripts to fail fast if required libraries are not found.
* updated error logging to exclude ffmpeg end-of-file warning, it was just
  polluting things.
* ongoing warning cleanups against more modern compilers.

--------------------------------------------------------------------------------

0.96.5

* ensure we statically link against the brew version of ncurses on macOS when
  building pre-compiled artifacts

--------------------------------------------------------------------------------

0.96.4

* added mouse wheel support to non-Windows platforms.
* fixed some difficult-to-reproduce issues that could corrupt layout.
* optimized app resize logic so its simpler and more performant.
* fixed issues with terminal emulators on macOS that support REP (e.g. kitty)
  by linking against the less buggy, homebrew-provided version of ncurses.
* upgraded to the most recent version of Android Studio tooling for the
  musikdroid app.
* fixed a bug where track numbers would not be correct after loading a session
  where the last viewed content was a playlist.
* ongoing warning cleanups against more modern compilers.

--------------------------------------------------------------------------------

0.96.3

* fixed a bug that could cause terminal output to get corrupted when switching
  songs (@the-eater)
* fixed a bug that was preventing the update check from displaying a dialog on
  completion.
* fixed now playing readout ellipsizing.
* fixed a bug where `last.fm` scrobbles may get posted twice per track.
* added a hotkey to clear the play queue; press `shift+x` in the play queue
  window.
* fixed `HttpClient` user agent to distinguish between `win32` and `win64`

--------------------------------------------------------------------------------

0.96.2

* fixed a crash in HttpClient that was only manifesting on some architectures
  and compilers.
* fixed a bug where UI may be updated from a background thread, leading to
  undefined behavior.

--------------------------------------------------------------------------------

0.96.1

* additional fixes for older versions of libcurl (< 7.2.0)
* relax client/server version matching to exclude patch version (e.g. versions
  0.96.0 and 0.96.1 are considered compatible, but 0.96 and 0.97 are not)
* upgraded libmicrohttpd to 0.9.71 on macOS and fixed static build

--------------------------------------------------------------------------------

0.96.0

* improved input latency, especially related to mouse events.
* updated zh_CN localization (Siheyuan98)
* added support for older versions of libcurl (< 7.2.0)
* added an advanced setting to ignore client/server version mismatches when
  connecting to remote libraries
* added the server version to the user facing error that is displayed on
  remote library version mismatch.
* added the app version to the bottom of the settings screen.
* fixed milkdrop plugin build

--------------------------------------------------------------------------------

0.95.0

* added support for searching by regex; press `M-m` in track or filter views to
  toggle between regex and legacy searching. while regex is enabled, the search
  box will have a blue (instead of red) border.
* relaxed search to ignore accents. for example: 'À', 'Á`, 'Â`, etc are all
  considered equivalent to the english 'A', and vice versa.
* fixed a bug where remote library ports greater than 32767 caused the app to
  crash.

--------------------------------------------------------------------------------

0.94.0

* added support for remote libraries (i.e connecting to a musikcube app or
  daemon running on a different machine) to the terminal client:
  - updated nearly all queries against the database in the app to be
    asynchronous. this was not necessary before because most local DB queries
    are extremely fast; however, when queries are sent over the network that may
    not be the case. there are still a small handful of queries made on the UI
    thread, but all of the really egregious ones have been fixed.
  - added a new `ISerializableQuery` interface that defines how a query can be
    serialized and deserialized. all queries now implement this interface.
  - defined a new `SendRawQuery` method to `IMetadataProxy` that is used by the
    server to send serialized queries to `musikcore`, and then respond with
    serialized results to the calling client.
  - added `WebSocketClient` that is used to connect to a `musikcube` server and
    authenticate. it takes serialized queries from the client and sends them to
    the server, then parses responses and unpacks the serialized result.
  - added a new `RemoteLibrary` implementation of `ILibrary`. it serializes
    queries and sends them to the server via `WebSocketClient`. once complete,
    `WebSocketClient` hands the serialized result back to `RemoteLibrary`, which
    then deserializes the result into the original query and notifies the caller.
  - added `MasterLibrary` in the same vein as `MasterTransport`. it's more a
    less a `pimpl` that allows us to switch the selected library under the hood
    without a majority of the app knowing or caring.
  - revamped the settings screen to allow selecting between local and remote
    libraries.
  - added a new screen that is displayed when a remote library is disconnected,
    and shows some diagnostic information.
  - added a new banner on the top of the app when connected to a remote library.
  - added buffering states to Stream/Transport/PlaybackService and friends.
  - updated the transport window to display buffering status when appropriate.
* fixed a number of bugs in `cursespp` related to nested layout focusing.
* fixed buggy visibility change events in `cursespp::Window` and removed old
  hacked-up code that was working around the problems in the app layer.
* fixed a handful of `KeyPress()` propagation bugs across the app.
* found and fixed a handful of bugs in `HttpDataStream` that have been laying
  dormant, waiting to be exercised.
* fixed bugs related to `LruDiskCache` parsing and pruning.
* fixed potential memory leaks in GmeDataStream and OpenMptDataStream
* fixed some weird edge-casey command bar focus issues.
* finally renamed `src/core` to `src/musikcore`
* added a ja_JP locale (trackiss)
* updated ru_RU locale (adem4ik)
* fixed a bug where on-demand mp3 transcoding wasn't working properly. (other
  formats were fine)
* rearranged the settings window to ensure everything fits properly in an 80x24
  terminal
* fixed some bugs in `MessageQueue` by now requiring explicit `IMessageTarget`
  registration and unregistration for all messages. there was a small time
  window (read: race condition) where it was possible to attempt to dispatch
  messages to a destroyed target.
* fixed a handful of components that were running their initial queries twice
  or more as they were being initialized.
* updated copyright date across all source files
* upgraded a number of tools and dependencies:
  - migrated to VS2019 for Windows musikcube builds
  - migrated to Android Studio 4.1 for musikdroid builds
  - upgraded `websocketpp` and `json.hpp` and moved them out of `src/plugins`
    and into `src/3rdparty` so they can be used by the main app.
  - upgraded to boost 1.74.0
  - upgraded to openssl 1.1.1h
* fixed a bug in the indexer that could prevent custom sources from getting
  interrupted correctly.
* fixed a bug in libmicrothttpd version detection.
* fixed a bug where switching to a different output device while paused would
  cause playback to resume.
* moved all shell scripts to their own subdirectory so they don't pollute the
  root.
* fixed an old bug in `LocalLibrary` that could cause query result callbacks
  to fire twice.
* added the ability to limit the number of simultaneous audio transcoders in
  the server.
* added support for Ubuntu Groovy
* various other minor fixes that were exposed by making queries asynchronous by
  default.

--------------------------------------------------------------------------------

0.93.1

server:
* fixed compile error on some platforms caused by updated libmicrohttpd APIs

--------------------------------------------------------------------------------

0.93.0

musikcube:
* added a new decoder based on `libopenmpt` to support playing mod/tracker
  files.
* fixed a bug when browsing directories that contain entries from custom
  `IndexerSource` plugins.
* fixed directory scanning bugs related to NFS (and potentially other
  filesystem) volumes.
* fixed a nasty race condition in the MPRIS plugin that could cause the app to
  crash on certain events.
* compile against the source version of taglib to get a number of important
  bug fixes that haven't been released yet.
* fixed a memory leak in the GME plugin when aborting a directory scan
* fixed a bug that could cause advanced setting integer values to not save
  properly.
* reduced Indexer log spew.
* removed more unnecessary boost cruft in the Indexer
* fixed an Indexer bug that could result in tracks not getting added to the
  library.
* fixed a bug where the Indexer couldn't always be interrupted while scanning.
* upgraded snap from core18 to core20.

musikdroid:
* upgrade to Android Studio 4.0 and related tooling

--------------------------------------------------------------------------------

0.92.1

server:
* fixed a bug where HTTP authentication was not functioning properly and could
  allow unauthenticated clients to download tracks.

--------------------------------------------------------------------------------

0.92.0

musikcube:
* fixed bug in the ffmpeg decoder where
* added three new hotkeys:
  - `M-P`: start playback from the top of the current list of tracks
  - `]`: jump to the next group in the current track list
  - `[`: jump to the previous group in the current track list
* added the ability to disable terminal title upgrades in `advanced settings`
* updated ru_RU localization (adem4ik)
* optimized png files (adem4ik)
* added zn_CN localization (Siheyuan98)
* fixed a bug where binary stripping was broken for out of tree builds
* added the ability to disable binary stripping via DISABLE_STRIP=true flag
* fixed `archive-win.sh` to use unix line endings

musikdroid:
* fixed a bug when downloading tracks without metadata, or metadata that
  contains invalid path characters.
* fixed a bug where track downloads may get corrupted, and/or assigned an
  incorrect file extension
* fixed a bug where FLAC decoding would crash the app
* upgraded to the latest version of Android Studio
* upgraded various dependencies

server:
* added new `X-musikcube-File-Extension` HTTP response header that clients can
  use as a hint when naming downloaded files.

--------------------------------------------------------------------------------

0.90.1

(windows-only release)

musikcube:
* fixed crash in win32 server caused by an incorrectly-compiled zlib

--------------------------------------------------------------------------------

0.90.0

musikcube:
* included a new `musikcube-cmd.exe` binary that can be run from a standard
  command-line session in Windows,  including cmd.exe, PowerShell, Windows
  Terminal, or ConEmu.
* added an OpenBSD port (castagnini)
* added the ability to build as a `snap` package.
* fixed build issues for platforms with ncurses and tinfo split (tobbez)
* fixed an issue where percent signs in the transport weren't getting properly
  escaped (the-eater)
* fixed an issue where we may not properly detect UTF8 terminals in some cases
* added true color support for macOS Terminal.app (previously was only
  supported in iTerm)
* fixed a handful of directory browsing bugs reported by (pcapiod)
* fixed a bug where we weren't always properly reporting track metadata in the
  MPRIS plugin.
* added a way to add an `audd.io` API key, if you have one, to fetch lyrics
* updated session data to be stored in its own config file
* merged upstream PDCurses changes to fix a handful of minor bugs and better
  support Windows Terminal
* fixed a couple null pointer dereferences, and a couple instances where we
  were using variables before they were initialized (detected with valgrind)
* fixed some weird redraw issues on some platforms with ncurses 6.2
* fixed some bugs where we weren't always compiling the MPRIS plugin for our
  binary packages
* fixed a number of ALSA and PulseAudio bugs when devices are not available
  or there is resource contention

musikcore:
* added a very basic C API for interacting with the SDK. see `musikcore_c.h`
  and the companion project `core_c_demo`.
* fixed an old bug in the `indexer` that would report an incorrect updated file
  count.
* added the ability to build a standalone `musikcore.dll` on Windows that can
  be used with the new C API for easy integration with other languages or
  environments.
* fixed a bug where we may crash when playing 0-length files.
* fixed an old bug where playback state would get out of sync if the user seeked
  while paused.
* cleaned up SDK constants

musikdroid:
* updated crash report tracking to use Firebase Crashlytics
* upgraded ExoPlayer
* upgrade to Android Studio 3.6

server:
* tweaked the threading model to better support multiple concurrent connections
* fixed a bug where we may attempt to transcode the same file multiple times
  simultaneously; now if there's a transcode for a shared resource in progress
  we'll just wait until the original operation completes

--------------------------------------------------------------------------------

0.83.0

musikcube:
* #309: fixed a minor CMake configuration bug that could cause some formats
  (e.g. `opus`) to not get recognized on some platforms (e.g. `linux`).

--------------------------------------------------------------------------------

0.82.0

musikcube:
* Fixed a small bug that could cause dialogs to get partially obscured on
  certain versions of curses.

--------------------------------------------------------------------------------

0.81.0

musikcube:
* Added an `advanced setting` to hide the star rating column

musikcore:
* #308: audio decoding doesn't work with older versions of `ffmpeg`
* #307: database initialization issue (hectorm)
* #304: Updated `ru_RU` localization (adem4ik)

--------------------------------------------------------------------------------

0.80.0

musikcube:
* Added `zh_CN` localization (Siheyuan98)
* Fixed #287: Window size not properly restored in Windows build
* Fixed #276: Added the ability to rate tracks via `r` shortcut in all track
  list views.
* Fixed #260: Added the ability to sort track list results via `^S"` in search
  and browse views
* Fixed #173: Show song artist and title in the terminal titlebar
* Fixed #299: Windows drives disappear in directory browser after checking/
  unchecking "show dotfiles" option.
* Fixed #257: Added an option to hide the command bar when not in command mode
* Backported `SchemaOverlay` from upstream `cursespp` and use it in
  `PluginsOverlay`.
* Added an `advanced settings` to the settings view and re-arranged things a
  bit.

musikcore:
* Fixed #290: A brand new transcoder implementation powered by ffmpeg that
  supports `ogg`, `opus`, `aac`, `flac`, `wavepack`, and `wma` files. `mp3`
  transcoding is still handled by `libmp3lame`.
* Fixed a bug in `FfmpegDecoder` that could result in a pre-mature / incorrect
  `EOF` error.
* Fixed #294: we weren't properly querying the local DB for lyrics.
* Fixed #293: bug parsing disc number in AAC files.
* Fixed #298: bug decoding APE files. changes also include a complete refactor
  and overhaul of the `FfmpegDecoder` plugin to use modern, non-deprecated
  ffmpeg APIs.
* Fixed #160: added support for WAV and AIF files.
* Fixed #133: properly label and sort blank / empty category names as
  `[unknown]` and ensure they are returned at the bottom of their respective
  lists.

musikdroid:
* Allow for transcoder format selection in `musikdroid`'s settings screen.
  (Part of #290)
* Upgraded `musikdroid` to use the latest stable Android Studio and other
  dependencies (ExoPlayer, AndroidX, etc), plus a bunch of compiler warning
  fixes.
* Fixed #296: notification not dismissed on stopping playback on some devices
  running Android 10

--------------------------------------------------------------------------------

0.70.1

musikcube:
* new MPRIS plugin for controlling playback on Linux (brunosmmm)
* 64-bit binaries for Windows (note: Milkdrop only supports 32-bit)
* ru_RU update (adem4ik)
* it_IT update (alexpovel)
* chocolately install instructions (majkinetor)
* FreeBSD install instructions (0mp)
* Dependency upgrades on Windows (libcurl, PDCurses, libogg, LAME, ffmpeg)
* A couple small tweaks / fixes to widget focus behavior
* Raspberry Pi 4 support
* Debian Buster support
* Ubuntu Eoan support

musikdroid:
* Code cleanup and refactors with clearer names for major subsystems
* Dependency upgrades and migration to AndroidX

--------------------------------------------------------------------------------

0.65.2

musikcube:
* updated `ru_RU` locale (adem4ik)

musikcore:
* renamed some classes:
  * `ISimpleDataProvider` -> `IMetadataProxy`
  * `LocalSimpleDataProvider` -> `LocalMetadataProxy`

musikdroid:
* renamed some classes:
  * `IDataProvider` -> `IMetadataProxy`
  * `RemoteDataProvider` -> `RemoteMetadataProxy`
  * `DataProviderMixin` -> `MetadataProxyMixin`

--------------------------------------------------------------------------------

0.65.1

musikcube:
* manually patched `websocketpp` to fix boost 1.70 compatibility. this allows
  us to compile on macOS again. for more information, see here:
  https://github.com/zaphoyd/websocketpp/pull/814

--------------------------------------------------------------------------------

0.65.0

musikcube:
* added lyrics support (powered by audd.io)! access lyrics for the currently
  playing song by pressing ^L.
* removed vcredist runtime requirement on windows
* added support for Ubuntu Disco
* added support for Fedora 30

musikdroid:
* added a new "offline" tab to the browse screen
* moved settings and other overflow options to the left side of the main
  screen's toolbar.
* added settings > advanced > diagnostics screen to show app runtime, wakelock
  acquisition time and status, and service status.
* added a "download" option for song rows -- this can be used to download songs
  for ringtones, or for playback in offline players.
* added the ability to seek playback on secondary screens
* removed some old settings that are no longer useful
* updated to AndroidX

--------------------------------------------------------------------------------

0.64.1

win32 and android only release

musikcube:
* fixed a bug where notification tray icon wasn't getting set properly.

musikdroid:
* work around android platform bug where, on some devices, pressing pause
  on a headset, followed by resume within a couple seconds, will not work
  properly.

--------------------------------------------------------------------------------

0.64.0

musikcube:
* migrated *nix data directory from $HOME/.musikcube to $HOME/.config/musikcube
* fixed a bug in the Windows build where non-Latin character input was not
  working properly in all cases.
* added a search "hint" in filter and category library views
* fixed some super old bugs related to global focus tracking in cursespp
* fixed cursespp::TextInput::SetHint()
* redirect stderr output to ~/.config/musikcube/stderr.txt instead of /dev/null.
  bonus: works on win32 now, too.
* merged upstream PDCurses into our own custom fork (win32 only)
* updated ru_RU translation (adem4ik)
* fixed the `gruvbox_dark` theme's focused text input color

musikdroid:
* fixed a crash when trying to randomize a play queue of exactly 2 tracks.

--------------------------------------------------------------------------------

0.63.0

musikcube:
* fixed a bug in `pulseout` where we were unable to recover from restarting the
  `pulseaudio` daemon without restarting the app (or switching output plugins)
* fixed bug where `opus` files with an `ogg` extension weren't being detected
  propertly. added scaffolding for fixing this for other formats in the future.
* fixed a Win32 file permission bug in `gmedecoder`
* fixed FreeBSD user agent when performing update check
* updated ru_RU translation (adem4ik)
* fixed a missing sndio #include (Kistelini)

musikdroid:
* changed general music browse experience to be tab-based with with modern
  scrolling behaviors. this results in fewer clicks to find music and more
  screen real estate.
* fixed elusive bug that would cause lock screen controls to stop functioning
  sometimes, on some devices.
* massive cleanup and refactor to old code, making it more modular and easier
  to compose.

--------------------------------------------------------------------------------

0.62.2

macOS only release.

musikcube:
* added missing `gnutls` dependency to project for homebrew builds
* compile `libmicrohttpd` from source for binary distributions on macOS

--------------------------------------------------------------------------------

0.62.0

musikcube:
* fixed a crash in `CoreAudioOut` when parsing unnamed output devices
  (Porco-Rosso)
* fixed a crash in `macosmediakeys` initialization (Porco-Rosso)
* fixed a bug where long path names could crash on Linux systems (the-eater)
* removed bash dependency from wrapper scripts (hectorm)

musikcubed:
* added `--foreground` command line argument that instructions the daemon to
  not not `fork()`, and run in the foreground instead.

--------------------------------------------------------------------------------

0.61.0

musikcube:
* added chiptunes support via Game_Music_Emu! supported formats include: vgm,
  gym, spc, sap, nsfe, nsf, ay, gbs, hes, and kss
* added `macmediakeys` plugin; macOS users can play/pause/resume/skip tracks
  using the media keys on the keyboard.
* substantially improved metadata indexing performance for large collections
* ensure all utf8 strings are sanitized immediately before inserting them into
  the database. this wasn't being done properly before, and could lead to weird
  crashes when trying to display metadata.
* added the ability to disable album artist -> artist metadata fallback.
  set `DisableAlbumArtistFallback` to `false` in `~/.settings.json` (the-eater)
* many additional small indexer bug fixes

musikcore:
* added the concept of "infinite" streams

sdk:
* `IIndexerSource::Scan()` now receives a list of source paths
* added `IIndexerSource::NeedsTrackScan()`. implementations may override this
  and return false to provide a hint to the indexer engine that the plugin
  does not need to receive a callback to update each individual track
* added `IIndexerWriter::CommitProgress()`. by default the indexer creates and
  commits a single transaction per source; plugins can manually commit progress
  using this method.
* added `IIndexerWriter::GetLastModifiedTime()` so plugins can query the last
  modified date for a track by `externalId`.

--------------------------------------------------------------------------------

0.60.2

FreeBSD only release.

musikcube:
* *finally* fixed the FreeBSD scrollbar crash. yeesh.
* fixed a bug in the `sndio` output plugin that may cause the first few buffers
of audio data to be discarded when manually changing tracks.

--------------------------------------------------------------------------------

0.60.1

musikcube:
* fixed m4a playback
* added support for aac and alac playback
* refactored `sndio` output to be more resilient against buggy drivers
* added support for ALSA in FreeBSD via `-DENABLE_ALSA=true` CMake switch.

musikdroid:
* fixed crash on startup on some versions of Android. ugh.

--------------------------------------------------------------------------------

0.60.0

musikcube:
* added an equalizer! press `ctrl+e` to activate and configure.
* removed most default decoder plugins and replaced them with one powered by
  `ffmpeg`. this adds support for `opus`, `wavepack`, `musepack` and
  `windows media audio` files.
* added a new `enable transparency support` in settings that can be enabled by
  users who have a terminal with a transparent/translucent background.
* added the ability to customize the key used to quit the app. it is currently
  not exposed in the ui, but it can be changed by editing
  `~/.musikcube/settings.json` and updating the `AppQuitKey`.
* scrapped and re-implemented the debug log viewer, accessible via `ctrl+~`
* added feodra 29 support. (dvdmuckle)
* fixed configuration script bugs that were causing breakage in FreeBSD
* improved indexer speed by not re-extracting album art if it has already
  been extracted for the album the track belongs to.
* migrated to non-bundled `taglib` for macOS and most Linux distributions
* fixed a ton of minor ui bugs.
* updated win32 dependencies: libressl, libcurl, libboost, and pdcurses.

musikdroid:
* updated to compile against the latest tooling.
* added the ability to change equalizer settings on the server from the
  `remote management` screen.
* added the ability to specify title ellipsis mode (beginning/middle/end).

server:
* added `get_equalizer_settings` and `set_equalizer_settings`.

sdk:
* added a new `IDebug` interface plugins can request via `SetDebug` to write
  log information to the standard location, just like the rest of the app.
* added `ITagStore::ContainsThumbnail()`.

--------------------------------------------------------------------------------

0.51.0

musikcube:
* added a new "gruvbox" theme (https://github.com/morhetz/gruvbox)
* added the ability to graphically configure plugin properties via new SDK
  `ISchema` interface.
* added the ability to right click entries to display their context menu
* updated the Russian translation (adem4ik)
* fixed a bug where shutdown may be delayed while the indexer is running
* fixed a couple strings that were not properly localized
* fixed a bug that could cause overlays to not always properly disappear
* fixed a bug in the win32 milkdrop distribution where the preferred default
  font wasn't getting included

musikdroid:
* updated to compile against Android Studio 3.1.4

server:
* fixed a crash while querying play queue tracks that have b`een removed from
  the library.

sdk:
* added the ability for plugins to provide configuration schemas that can be
  configured by the user in the gui. see `sdk/ISchema.h`

--------------------------------------------------------------------------------

0.50.0

musikcube:
* added last.fm scrobbling support (settings > last.fm)
* added a built-in hotkey viewer and editor (settings > key bindings)
* added basic mouse handling support -- click / double click / mouse wheel
  works mostly the way you'd expect
* added an Italian translation (anonik9900)
* added a Russian translation (adem4ik)
* added a "proportional seek" functionality (benterris)
* fixed a bug where the "Source Code Pro" font was not being included in the
  win32 build with milkdrop.
* added support for Ubuntu Bionic
* added support for Fedora 28
* added windows theme support so the menu bar draws nicer
* updated PDCurses (windows build)
* retired binary distribution for Raspbian Jessie (Stretch still supported!)

musikdroid:
* fixed a handful of random crashes that showed up in fabric.io

server:
* fixed a bug where the same playback overview may be broadcast multiple
  times.
* fixed a bug where `set_volume` was not returning a response
* fixed a couple bugs where negative limits may be returned

sdk:
* added a simple HttpClient wrapper around libcurl that can be used by plugins

--------------------------------------------------------------------------------

0.42.0

musikcube:
* added the ability to browse by directory! add music directories to the list
  of `indexed paths` in the settings screen, then press `d` in browse view to
  browse.
* added a new setting to save session on exit. when enabled, musikcube will
  remember the last selected view and the current playback context, and restore
  everything on next app start.
* better first-run experience for new Windows users:
  - included "Source Code Pro Medium" font, and use it by default.
  - updated the default font size to be a bit larger.
  - hid the main menu bar with "Font" and "Paste" buttons; this functionality
    is still available by clicking the musikcube icon in the upper left portion
    of the window.
* added scrollbar support to ListOverlay

musikdroid:
* added the ability to automatically transfer playback from mobile to server
  when headset (or bluetooth device) is disconnected.

--------------------------------------------------------------------------------

0.40.0

musikcube:
* `^R` now displays an indexer dialog that allows the user to choose between a
  quick scan and full metadata rebuild.
* made checkboxes prettier.
* fixed playlist track numbers -- they should always be sequential, not pulled
  from metadata.

musikcubed:
* `NEW!`: run musikcube as a daemon on macOS, Linux and BSD.

musikdroid:
* added remote server configuration! users can now change output drivers and
  devices, ReplayGain and preamp settings, transport type, and schedule the
  metadata indexer from `musikdroid`. see: toolbar menu > remote management.
* promoted `playlists` to main screen, and moved the `play queue` button to
  stand out a bit more.
* added the ability to query albums by extended metadata categories, including
  "composer", "producer", "year" and more. see: toolbar menu > categories.
* removed legacy playback engines. only `ExoPlayer Gapless` is supported now.
* show a warning if the server is running an older api version.
* fixed a crash when streaming play queue contains one file, and "random" is on.

musikcore:
* added the following functionality to IEnvironment:
  - query output devices and drivers
  - select the system's default output device and driver
  - re-index and re-build library metadata
  - get/set preamp and ReplayGain settings
  - get/set transport type (gapless, crossfade)
* switching output devices, transport, and ReplayGain settings no longer
  abruptly stop playback. there may generally be a short pause, but playback
  will continue where it left off.
* removed `musikglue` project. move functionalilty into `musikcore`.
* bumped sdk version to 14

server:
* messages for new IEnvironment updates (see above)
  - `run_indexer`
  - `list_output_drivers`
  - `set_default_output_driver`
  - `get_gain_settings`
  - `set_gain_settings`
  - `get_transport_type`
  - `set_transport_type`
* play queue snapshotting; remote clients can use this functionality to help
  transfer playback context from server to client.
  - `snapshot_play_queue`
  - `invalidate_play_queue_snapshot`
  - `play_snapshot_tracks`
* all messages that start playback can now be passed a `time` parameter, which
  will seek initial playback to the specified time (in seconds).
* `query_play_queue_tracks` now accepts an optional parameter called `type`;
  allowed values are `live` (default) and `snapshot`.
* bumped api version to 14

--------------------------------------------------------------------------------

0.35.0

infastructure:
* automated Linux builds via CircleCI! (dvdmuckle)

musikcube:
* added ReplayGain support. settings > replay gain to configure. when support
  is active, and ReplayGain is applied, a green "RG" symbol will appear in
  the transport view next to the volume slider.
* added initial support for FreeBSD using sndio. big thanks to gregf for the
  support and troubleshooting.
* added scroll indicators to list windows (disabled on FreeBSD for now)
* exposed extended metadata -- browse by new fields like year, composer,
  language, etc. press `6` in library > browse view.
* fixed a couple bugs in the metadata indexer -- extended metadata properties
  were not always getting scanned and stored properly.
* fixed build paths so app can be built against MacPorts. (reynhout)
* fixed a bug where themes were getting clobbered after every reinstall on some
  platforms. users can now put their custom themes in `~/.musikcube/themes`.
* made overlay title text alignment consistent across (center horizontal).

musikcore:
* database and query updates to support track, category, and album queries
  with multiple predicates. (e.g. all artists with composer=X AND year=Y).
* new `sndio` output plugin. this is the default output for FreeBSD, and is
  optional (disabled by default) on Linux.
* new `ffmpeg_decoder` plugin. not enabled by default, but will probably
  eventually replace nomad, ogg, mp4, and flac plugins.

server:
* api support for multi-predicate queries.

musikdroid:
* fixed bug where non-transcoded audio would not always play properly.

--------------------------------------------------------------------------------

0.31.0

musikcube:
* added support for Ubuntu Artsy
* added preliminary audio encoders (MP3, OGG/Vorbis)
* fixed and exposed album-level artwork. previously it was track-only.

musikdroid:

* gapless playback (for supported media)! enable in settings > playback
  engine > "ExoPlayer Gapless (experimental)"
* playlist create / rename / update / delete support
* album art is now displayed in album rows when browsing
* context menus on most screens with the ability to switch between related
  content (e.g. albums by this artist, artists in this genre, etc)
* added a simple "spotlight" tutorial for new users that explains switching
  between remote and streaming playback modes.
* major refactor to the entire code base, including the following:
  - a brand new data layer interface based on RxJava. this should position
    the app for lots of new, fun stuff in the future.
  - a new dependency injection implementation
  - a view component layer for sharing functionality across screens
* updated Glide from v3 -> v4
* updated to Android Studio 3.0.1 and related tooling
* fixed notification icon color

sdk:

* removed all Destroy() methods, standardized on Release() across the board
* added the following to ISimpleDataProvider:
  - QueryCategoryWithPredicate()
  - SavePlaylistWithIds()
  - SavePlaylistWithExternalIds()
  - SavePlaylistWithTrackList()
  - AppendToPlaylistWithIds()
  - AppendToPlaylistWithExternalIds()
  - AppendToPlaylistWithTrackList()
  - RemoveTracksFromPlaylist()
  - RenamePlaylist()
  - DeletePlaylist()
* added new interfaces:
  - IValue
  - IEncoder
  - IEncoderFactory
* removed interfaces:
  - IRetainedTrack
  - IRetainedTrackWriter
* renamed interfaces
  - IMetadataMap -> IMap
  - IMetadataMapList -> IMapList
  - IMetadataReader -> ITagReader
  - ITrackWriter -> ITagStore
  - IMetadataValue -> IValue
  - IMetadataValueList -> IValueList

server:

* renamed project from `websocket_remote` to `server`, and promoted to a
  top-level component in the workspace
* added correct LAME headers after transcoding to fix gapless playback of
  encoded files.
* added the following messages to the websocket server:
  - save_playlist
  - rename_playlist
  - delete_playlist
  - append_to_playlist
  - remove_tracks_from_playlist
  - query_tracks_by_external_ids
* renamed the following track fields:
  - visual_genre_id -> genre_id
  - visual_artist_id -> artist_id
* added the ability to query album art by id
* fixed HttpServer to ignore non-GET verbs
* added "predicated category queries", i.e. "all the albums for this artist" or
  "all the artists in this genre", etc.
* added "artist" and "artistId" to album response (previously it was only
  return "albumArtist" and "albumArtistId")
* fixed bugs related to HTTP "Range" header parsing and generation
* fixed a bug in the websocket functionality that was returning invalid
  "invalid_request" responses... yeah.

--------------------------------------------------------------------------------

0.26.0

* added the ability to rebind UP, DOWN, LEFT, RIGHT, PAGE_UP, PAGE_DOWN, END and
  HOME keys to allow for VIM-style key bindings
* fixed a focus related bug when switching between main views

--------------------------------------------------------------------------------

0.25.2

musikcube:

* upgraded to a new version of the windows sdk (10.0.15063.0)
* added some missing checks in WideCharToMultiByte (and MultiByteToWideChar)
  that could result in access violations on windows
* added a hidden setting for enabling indexer logging (set IndexerLogEnabled in
  settings.json)

musikdroid:

* added the ability to rename connection presets
* fixed a crash in SystemService related to unregistered intents
* upgraded to android studio beta 5

--------------------------------------------------------------------------------

0.25.1

musikcube:

* fixed a bug in FlacDecoder::Exhausted that was causing issues with the
  server's transcoder.

--------------------------------------------------------------------------------

0.25.0

musikcube:

* fixed a crash in the m4a decoder
* updated some linux dependencies
* added a build for raspbian stretch

musikdroid:

* fixed playback notification so it works properly with Android O
* updated settings ui to include a way to save and load connections
* fixed a couple random crashes that surfaced in fabric
* removed android-specific dagger cruft; just use vanilla dagger
* updated support library and build tooling versions

--------------------------------------------------------------------------------

0.24.0

musikcube:

* added the ability for the user to select the output device (i.e. soundcard
  or port) audio will be rendered to. previously we always used the system's
  default device.
* fixed some transcoder and cdda bugs that prevented streaming cd audio to
  remote (e.g. android) clients.
* fixed a (potential) memory leak in the indexer when extracting album artwork
* matthiaskrgr pointed out some memory leaks, and KTRosenberg fixed them.

musikdroid:

* fixed (potential) crash when trying to display the update check dialog.

low-level:

* fixed a bug in CddaDataStream where the active reader would not have exclusive
  access to the output device.
* added new SDK interfaces for enumerating audio devices that are available to
  output drivers.

--------------------------------------------------------------------------------

0.23.0

musikcube:

* fixed album artist support for FLAC, OGG, and M4A files. users with existing
  libraries that are having problems should re-import their files.
* fixed CDDB lookup for mixed-mode discs in Windows
* fixed a bug in the low-level audio processing that could leak memory until
  the playing track completed
* allow M-ENTER to also activate the context menu for album header rows.
(ENTER still works as well)
* fixed the NullOut plugin -- it was not taking channel count into account when
  calculating buffer duration
* added support for Manjaro Linux

musikdroid:

* fixed a crash in SystemService::onStartCommand where the Intent's "action"
  was not being null-checked.
* suppressed a strange crash related to the Room library not initializing the
  database properly

--------------------------------------------------------------------------------

0.22.0

musikcube:

* fixed compile issues and startup crashes on Fedora, ArchLinux and openSUSE
* fixed a bug where playback speed may be incorrect for audio files that do
  not have exactly two channels.
* fixed a crash that could occur in the WASAPI output plugin for audio streams
  with very low sampling rates
* fixed crash when parsing "TCOP" id3v2 tag (ilitirit-za)
* fixed double-wide character truncation and ellipsizing (stephanwilliams)
* added a new setting to disable startup update checks
* sync'd PDCurses with the upstream repo

musikdroid:

* fixed a couple (relatively obscure) crashes
* updated build environment to Android Studio Canary 8 with Support Libraries
  26.0.0 (final)

low-level:

* fixed the way we define C++ flags in CMakeLists.txt so it works across more
  platforms, e.g. FreeBSD (geier)
* fixed GetApplicationDirectory() null termination error (mkilgore)
* updated the way we calculate audio buffer sizes and counts to ensure there
  is always enough headroom for audio with very low sampling rates
* updated the mpg123 decoder so it compiles and runs again against the latest
  version of the library and musikcube sdk.

--------------------------------------------------------------------------------

0.21.1

* updated a few of the symbols used for drawing things like dropdowns and
  checkmarks so they work with a wider variety of fonts

--------------------------------------------------------------------------------

0.21.0

* musikbox binary renamed to musikcube. build scripts, documentation, website
  and everything else updated accordingly.

--------------------------------------------------------------------------------

0.20.2

* "add tracks", "add category", and "select playlist" context menus now remember
  the last selected item for 60 seconds. this makes adding multiple things to
  the same playlist (or play queue) much easier.
* fixed startup crash on older versions of macos

--------------------------------------------------------------------------------

0.20.1

* arrow keys can now select items in the shortcuts window while focused.

--------------------------------------------------------------------------------

0.20.0

* added play queue "hot-swap". you can now swap a different list of tracks
  into an active play queue without disrupting playback. if the hot-swap
  action finds the playing track in the new list, it'll be automatically
  selected as the active track. focus a tracklist and press `M-a` to hot-swap.
* fixed a bug that was causing extended track metadata to be parsed incorrectly
  examples include bitrate, channels, lyrics, etc.
* fixed a bug where the category list view may jump around a bit during the
  indexing process.

--------------------------------------------------------------------------------

0.19.2

* start the metadata indexer immediately after adding or removing paths from
  the settings view. this functionality was previously disabled due to
  performance issues and a bug with the indexer. these problems have all been
  addressed.

--------------------------------------------------------------------------------

0.19.1

* re-introduced the multi-threaded indexer! this makes metadata scanning quite
  a bit faster on some systems
* fixed a bug where the selected item in browse view may change during the
  indexing process if more music is added to the library

--------------------------------------------------------------------------------

0.19.0

* fixed a bug where the wrong (or multiple) items may be highlighted in browse
  view if they all have the same name
* fixed a bug where seeking while paused wouldn't update the ui properly in
  some cases, leaving the paused animation running while audio was playing

--------------------------------------------------------------------------------

0.18.0

user-facing:

* added first-class support for browse playlists:
  - press `5` in library browse view to switch to playlists
  - press `M-r` to rename the selected playlist
  - press `M-s` to save the selected playlist
  - highlight the left pane, and press `DEL` (`BACKSPACE` on macos) to delete
    the selected playlist
  - press `M-up` (`CTRL-UP` on macos) to move the selected track up
  - press `M-down` (`CTRL-DOWN` on macos) to move the selected track down
  - highlight the right pane, and press `DEL` (`BACKSPACE` on macos) to delete
    the selected track from the playlist
* added view titles in library browse mode, now playing, and search views
* added auto-update check functionality to notify users when a new version is
  available. also added manual update check to settings
* rearranged some items on the settings screen
* removed "playback mode" from musikdroid settings screen. we have a quick
  toggle now!

low-level:
* ported musikdroid to kotlin. goodbye, java.

--------------------------------------------------------------------------------

0.17.2

user-facing:

* fixed a bug where usernames with non-latin characters may cause the
  `websocket_remote` and `httpdatastream` plugins to crash during startup.
* fixed startup issues on windows computers that do not have the visual c++ 14
  runtime installed.

--------------------------------------------------------------------------------

0.17.0

* added code to win32 build that ensures only a single instance is running
* fixed auto-dpi scaling in windows so `musikbox` displays properly out of the
  box on high dpi (4k) displays
* added the ability to browse and play cached tracks in `musikdroid` while
  offline.
* fixed a bug that was preventing the transcoder cache from functioning properly
* integrated `fabric.io` into `musikdroid` for crash reporting
* added new "empty" and "offline" view states to all screens in `musikdroid`
* fixed a couple `musikdroid` crashes in playback-related code

low-level:

* updated to boost 1.64.0
* started converting some `musikdroid` sources to `kotlin`
* added missing `track_num` field to track resources in `websocket_remote`
* fixed local cache filename generation in `musikdroid`

--------------------------------------------------------------------------------

0.16.0

user-facing:
* added a toggle in the `musikdroid` toolbar for quickly switching between
  remote and streaming mode
* removed volume and seek buttons; replaced with a seekbar, current and
  total time indicators.
* revamped loading indicators to be less jarring

low-level:

* integrated with a customized version of the `AndroidVideoCache` library to
  (hopefully) improve caching reliability.
* improved battery usage in `musikdroid`'s `SystemService`
* fixed bug where `websocket_remote` was not letting clients know when seeking
  has occurred.
* deliberately under-estimate calculated `Content-Length` header when doing
  on-demand transcoding. http clients seem to be more ok with this, as compared
  to over-estimating.
* fixed a bug where `websocket_remote` audio server would incorrectly return a
  216 status instead of a 200, confusing clients

--------------------------------------------------------------------------------

0.15.0

user-facing:

* added `server settings` configuration panel to the settings screen
* added `minimize to tray` and `start minimized` options to the windows build
* a handful of small `musikdroid` bug fixes, mostly related to audio focus
  and ducking.
* documented the `websocket_remote` api on the wiki

low-level:

* added authentication support to the the `websocket_remote` audio server
* found and fixed a handful of missing `websocket_remote` metadata responses
* added the ability to hot-reload plugins
* modified `IPlugin` -- every plugin must now supply a unique `guid`
* fixed a bug in Transcoder if the number of cache files was set to 0
* fixed a number of bugs that could result in undefined behavior or crashes if
  views are drawn outside of their parents (or screen) bounds
* fixed a bug where input fields may stop drawing properly if the value entered
  by the user exceeds the window bounds

--------------------------------------------------------------------------------

0.14.0

user-facing:

* `musikdroid` enhancements:
  - `pause` when headphones are disconnected
  - `double tap` headset button to go to next track
  - `triple tap` headset button to go to prev track
  - added album art to lock screen controls
  - added the ability to control streaming disk cache size
* `websocket_remote` plugin:
  - added Cache-Control headers to responses
* `core`:
  - found a really bad bug in the way we handle tracks in playlists. the fix
    requires a rebuild of the tracks metadata, which will clear playlists, but
    ensures this will never happen again in the future.

low-level:

* cleaned up more SDK interfaces, removed support for uint64 and uint32 types,
  only support int64 and int32.
* fixed bugs in playlist track handling; playlist contents can now survive track
  table rebuilds!

--------------------------------------------------------------------------------

0.13.0

user-facing:

* added on-demand audio transcoding (downsampling) to the http server. users
  can configure transcoding in the `musikdroid` client.
* fixed a bug in album id handling to properly support multiple albums with the
  same name by different artists (this was only half working before).
* added ssl support to the `musikdroid` client, and instructions on the wiki
  for enabling ssl on the server-side.
* added `buffering` indicators to `musikdroid`.

low-level:

* added missing IBuffer::Destroy method, and added IEnvironment::GetBuffer so
  plugins can decode audio data.

--------------------------------------------------------------------------------

0.12.1

user-facing:

* huge update to `musikdroid` -- it is now able to stream music  from any
  `musikbox` installation! see settings > playback mode.
* added cddb (actually, freedb) lookup for audio CDs
* added new "add to beginning of play queue" and "play album" context menu
  options

low-level:

* fixed database upsert logic to be faster and more reliable

--------------------------------------------------------------------------------

0.12.0

user-facing:

* fixed bug where "sync on startup" was not working properly
* fixed musikdroid bug where ui may get drawn in a weird state if the playing
  track has an empty album name.
* fixed a bug in CddaIndexerSource that may cause tracks to linger in the
  library longer than they should if the drive letter changed.
* added an http server to the `websocket_remote` plugin to serve audio data.
  this completes most work required to support external, thin clients.
  metadata can be queried via websocket, audio streamed over http. powered by
  libmicrohttpd.

low-level:

* added HttpDataStream! finally! uses libcurl and libressl. audio data can now
  be played over http/https!
* performance optimizations to metadata indexing -- drop indexes before a full
  resync, then re-add them after.
* playlist tracks are now stored by external ids! this means tracks added from
  third party indexer sources can be added to playlists and persisted across
  rescans.
* IIndexerSources can be interrupted, and failed sources can have their changes
  rolled back.
* upgraded to Windows 10 SDK and VS141 tooling

--------------------------------------------------------------------------------

0.11.0

user-facing:

* added a new cd playback plugin based on new infrastructure. audio cds will
  be detected and added to the library as [audio cd] and can be played like
  any other tracks. (note: win32 only for now)
* added the ability to toggle between seek and scrub playback modes
* fixed a couple localized strings
* fixed a bug that could cause the currently selected item in the play queue
  to jump around or be incorrect.

low-level:

* added IIndexerSource interface: plugins will be able to implement this
  interface to add tracks to the library that will be indexed and
  maintained like all other tracks
* added IIndexerWriter interface: IIndexerSource plugins will use this
  interface to add/remove/update track info with the main app
* added IIndexerNotifier: interface used to notify the app that it needs
  to be re-indexed.
* added "source_id" , "external_id", and "visible" column to the tracks
  table, with appropriate indexes.
* fixed a really old indexer bug where the reported number of file scanned
  was not accurate. Strange this wasn't noticed before.
* added "SetIndexerNotifier" injection method
* fixed a bug in TrackMetadataQuery -- it was unnecessarily relying upon
  the paths table, which was causing query errors when the table was
  empty.
* use a cache for local file paths instead of requiring an async round
  trip when adding/removing
* remove use of manual "ANALYZE", it was causing strange performance
  degradation issues. Instead, move to a set of PRAGMAs that instructs
  sqlite to run these optimizations when necessary.
* updated ::GetInt32 and ::GetUint32 return types to be explicit as to play
  more nicely with clang -- may as well, we're updating the SDK version
  anyway.
* added a simple capabilities model to the playback infrastructure. This
  is used to detect whether or not streams can be prefetched. For example,
  CDDA cannot because of seek times while playing tracks.

--------------------------------------------------------------------------------

0.10.2

* fixed clang 7.3 compile error (macOS mavericks should work again)

--------------------------------------------------------------------------------

0.10.1

user-facing:

* added the ability to select album name headers in track lists. doing so will
  bring up a context menu with the ability to jump to the album or enqueue the
  album's tracks for playback. this also had a nice side effect of making
  scrolling more fluid!
* added jumping to album/artist/genre to the selected track context menu
* fixed a really old bug that could cause lists to automatically scroll to weird
  places if the window or view is resized
* directory browser now remembers which directories were previously selected,
  making up navigation in the settings view smoother
* added a "list_header_highlighted_background" and
  "list_header_highlighted_foreground" color theme variables
* tweaked the win32 icon so it looks a bit better on the taskbar

low-level:

* added "broadcast" message support to IMessageQueue and implementers. allows
  for pub/sub like functionality
* added some new SDK interface methods to ITrack and IMetadataMap for retrieving
  values other than strings (uint64, int64, uint32, int32, double)
* added localization support for "dimensions". this allows for per-locale sizing
  of ui components
* fixed some old bugs in Window.cpp that could cause visibility changed
  notifications to be raised unnecessarily
* added a custom PDCurses/win32a patch to further reduce CPU load and context
  switching while draining the message pump

--------------------------------------------------------------------------------

0.10.0

* added GeekShadow's fr_FR locale
* fixed a bug in locale loading
* fixed a bug in nomad decoder if file load fails
* updated `Player` <-> `Stream` interaction so it's possible to interrupt long,
  blocking reads (e.g. if an http stream loader existed)

--------------------------------------------------------------------------------

0.9.5

* added localization support
* added support for user-defined themes (solarized dark and light included as
  examples)
* patched PDCurses/win32a to support the standard *nix 256 color palette

--------------------------------------------------------------------------------

0.9.4

* added a "syncing metadata" banner that is displayed while the indexer is
  scanning metadata
* added a "sync metadata on startup" option to the settings view
* moved the hotkey tester to its own dedicated dialog to free up some valuable
  screen real estate in the settings view
* fixed `PulseOut` plugin volume adjustment to work better across a wider
  range of audio cards. this should also improve crossfade quality
* fixed a very old bug that was sometimes causing delayed redraws or flickering
  during layout in complex views

--------------------------------------------------------------------------------

0.9.3

win32 only release:

* updated `WASAPI` output plugin to disable endpoint routing by default. it
  causes a crash in some rare cases that i don't seem to be able to work
  around. i see similar crashes in firefox and some other apps that use this
  feature.
* updated `DirectSound` output volume adjustment to be as close to the `WASAPI`
  `WaveOut` plugins as possible
* changed compiler optimizations to favor fast code, instead of small code,
  plus a few other small tweaks to (hopefully) improve performance.

--------------------------------------------------------------------------------

0.9.2

* added an icon to the windows and android builds (not great, but better than
  nothing!)
* fixed a bug in the `nomad` (mp3) plugin where sample rate wasn't being
  handled appropriately. songs were sometimes playing too fast or slow.
* fixed a bug in the websockets plugin for certain metadata in locales that
  use commas instead of periods for decimal points
* added compression support to the `websocket_remote` plugin and the
  `musikdroid` android app
* fixed a crash when trying to manipulate an empty play queue in specific
  contexts
* fixed the win32 global volume up / volume down hotkeys to be consistent with
  the main app and `websocket_remote` behavior.
* changed data directory from "~/.mC2" to "~/.musikcube". the app will
  automatically perform this rename on startup.

--------------------------------------------------------------------------------

0.9.1

* added an app icon on win32 and android builds
* added proper support for using and switching between different audio sample
  formats. 24/192k works across all platforms now.
* fixed `DirectSoundOut` pause to work properly again
* added support for statically linking dependencies. for now we can supply
  macOS binaries that don't require homebrew! let's try to keep it that way.
* updated some defaults -- rescan metadata on startup by default, and restrict
  to two processing threads.
* fixed a crash when trying to change tracks in an empty playlist queue

--------------------------------------------------------------------------------

0.9.0

user-facing:

* added new `musikdroid` android remote control! super useful with a Raspberry
  Pi. run musikbox in the background and control it from your phone.
* added a new `websocket_remote` plugin that allows any client capable of
  communciating with websockets the ability to control playback and query
  metadata!
* added settings UI for enabling/disabling plugins within the app!
* added more granular volume control when adjusting below 10%
* fixed a crash on shutdown while in track search view

low-level:

* added new sdk interfaces:
  - `ISimpleDataProvider`: can be used to query tracks, albums, artists, genres
  - `IMetadataValue` and `IMetadataValueList`: lists of metadata values and ids
  - `IMetadataMap` and `IMetadataMapList`: maps of values for resource ids
  - `IPreferences` for reading and writing preferences
* updated sdk interfaces:
  - `ITrack`: added `getId()`
  - `IPlaybackService`: the ability to modify or replace the play queue
  - `ITrackList`: added const correctness
  - renamed `IMetadataWriter` to `ITrackWriter`
* added the ability for plugins to register to receive `IPreferences` and
  `ISimpleDataProvider` interfaces via `SetPreferences()` and
  `SetSimpleDataProvider`, respectively. see `websocket_remote` for an example
* fixed up `PluginFactory` to store and provide more metadata about plugins
  when querying them.
* fixed a deadlock in `PlaybackService` when changing tracks from
  `IPlaybackRemote` plugins.
* fixed another WASAPI audio endpoint routing bug
* fixed some win32 project settings to allow profile guided optimizations (was
  broken for some plugins)
* fixed 'deprecated' compiler warnings on macOS
* seed the random number generator at startup

--------------------------------------------------------------------------------

0.8.0

user-facing:

* added support for Raspberry Pi running Raspbian!
* added preliminary support for playlist editing. all editing is currently
  in the play queue view.
    - `ALT+s`: save the current play queue to a named playlist
    - `ALT+l`: load a previously saved playlist
    - `ALT+x`: delete a playlist
    - `ALT+r`: rename a playlist
* added the ability to delete (BACKSPACE on mac, DEL on win32/linux) and reorder
  (ALT+UP/ALT+DOWN win32/mac, CTRL+UP/CTRL+DOWN linux ) selected items in the
  play queue.
* added better color fallback for non-mutable 256 termianl color palettes
* added the ability to enqueue selected tracks, albums, artists, or other
  resources to the play queue by pressing ALT+ENTER.
* fixed a crash when trying to play a track that has been removed from the
  database
* fixed (maybe) an impossible-to-reproduce bug in PulseAudio where the output
  volume was not getting properly initialized
* removed "esc focuses shortcut bar" setting. no longer useful.

low-level:

* fixed cursespp child view coordinates to be relative to their parents
* cleaned up global focus model in cursespp
* added IPlaybackService::GetPlayingTrack() to get an IRetainedTrack pointer
  to the currently playing track; bumped SdkVersion to 2.

--------------------------------------------------------------------------------

0.7.3

reduce CPU usage during playback in macOS CoreAudioOut
include the null output plugin in macOS and Linux builds.

--------------------------------------------------------------------------------

0.7.2

mostly performance and architecture changes:

* created new 'src/glue' package that contains code that can be optionally
  included and reused by other applications, but is too high-level for
  src/core
* cpu reduction and code simplification in 'Stream' and 'Player'
* cpu reduction in 'MessageQueue'
* reduced locking in 'Player' and 'MessageQueue'
* tweaked music library interface to optionally deliver results to a specified
  'IMessageQueue'
* moved 'PlaybackService' and 'TrackList' into 'core'
* optimized floating point sample scaling in the 'nomad' mp3 decoder
* reduced cpu overhead when redrawing the transport view
* added bare-bones, 'proof of concept' win32 application that includes 'core'
  and 'glue' to present a very basic music player in just a few lines of code.
* added a NullOut, an output plugin that doesn't write to the sound card. useful
  for development and testing purposes.

bug fixes:

* fixed default output plugin selection logic
* fixed a crash in WASAPI stream routing

--------------------------------------------------------------------------------

0.7.1

user-facing:

* fixed the flac decoder. oops.
* changed focus behavior in search view -- pressing return in the edit field
  will now focus the tracklist after starting playback
* added sdk and plugin versioning. the plugin loader will only load plugins
  with a supported version.

low-level

* removed pre-buffering code from Player, let Stream worry about that
* moved from boost to std for most threading (boost still used in the indexer)
* removed some unused boost dependencies from CMakeLists.txt
* various small optimizations to help reduce CPU overhead in MessageQueue and
  Player.

--------------------------------------------------------------------------------

0.7.0

a big release with lots of changes to low-level machinery.

user-facing:

* added a new "crossfade" playback mode that can be used instead of "gapless".
  users can change this functionality in the settings view.
* fixed audio artifacts in WasapiOut and DirectSoundOut when pausing and
  resuming playback multiple times very quickly.
* fixed a really bad bug where dialogs could not be easily dismissed in some
  cases. this included the first-run dialog! yikes.

low-level:

* added Latency() and Drain() methods to the IOutput interface
* reduced CPU load in some output plugins by being less aggressive about keeping
  the output buffers 100% full all the time. 75%+ fill rate should be
  sufficient.
* generalized MessageQueue and moved it out of app, and into core so it can be
  reused for other functionality (e.g. crossfading)
* added support for "mix points" in Player -- get a callback as soon as a
  specific playback position is hit!
* fixed DirectSoundOut to fall back to software mixing if hardware mixing is
  unavailable
* fixed DirectSoundOut to start playback immediately, instead of sometimes
  requiring the buffer to be completely full

--------------------------------------------------------------------------------

0.6.2

* added a DirectSound output plugin for the win32 build.

--------------------------------------------------------------------------------

0.6.1

* replaced mpg123 decoder with MAD. gapless playback for a much wider variety of
  mp3s!
* optimized indexing process by maintaining an in-memory database id cache. uses
  a bit more memory (temporarily, during indexing) but improves indexing speed.

--------------------------------------------------------------------------------

0.6.0

* added the ability to have multiple output plugins, and the ability switch
  between them in settings
* added a new default output plugin for win32 (WASAPI) and linux (PulseAudio)
* changed a bunch of low-level ui code to substantially reduce layout passes and
  redraws
* made a few small changes to the main ui, including basic listview headers if
  the window grows large enough

--------------------------------------------------------------------------------

0.5.0

user-facing:

* remember volume and repeat settings across app launches
* improved visualizer quality
* reduced download size by a couple megabytes

low-level:

* optimized Stream and Player communication. more direct, less locking. no more
  weird deferred cleanup
* removed fftw3 dependency in favor of kiss_fft. much smaller download now
* added a proper windowing algorithm to audio samples before they are handed to
  the fft process
* fixed audio de-interleaving issue which lead to funky fft results in some
  cases
* included a new spectrum visualizer sample called GdiVis (win32 only for now)
* overhauled some parts of the audio engine to ensure buffer size is consistent
  during playback. this makes visualization quality better, and should make it
  easier to integrate with things like JACK and PulseAudio.

--------------------------------------------------------------------------------

0.4.1

* fixed the transport readout to be more legible
* fixed a crash in NowPlayingLayout when the window became too small
* improved the IPlaybackService and IPlaybackRemote interfaces, and introduced a
  new IRetainedTrack type.
* upgraded build environment to visual studio 2017

--------------------------------------------------------------------------------

0.4.0

* updated transport focus behavior to be less confusing -- it was previously too
  easy to accidentally focus the transport.
* added mute functionality. focus the volume control and press enter or just
  press m while browsing your library.
* added new IPlaybackRemote and IPlaybackService sdk interfaces to support
  writing plugins that can control playback and be notified of playback events.

--------------------------------------------------------------------------------

0.3.5

* various small visualizer-related fixes.

--------------------------------------------------------------------------------

0.3.4

* visualizer support! press v to show the picker! a couple samples (Milkdrop2
  and projectM) are included below. unzip these to your musikbox\plugins
  directory.
* fixed a nasty unicode conversion bug.
* various other small fixes

--------------------------------------------------------------------------------

0.2.2

* small improvements to the transport view, including the display of the volume
  percentage next to the volume slider.

--------------------------------------------------------------------------------

0.2.1

* initial "public" release
