Merge branch 'master' into clangen/upstream-pdcurses

This commit is contained in:
casey langen 2020-04-10 21:47:19 -07:00
commit 23b274bce9
22 changed files with 325 additions and 49 deletions

View File

@ -45,7 +45,20 @@ jobs:
steps:
- checkout
- run: apt-get update
- run: apt-get install -y build-essential clang cmake libboost-thread1.67-dev libboost-system1.67-dev libboost-filesystem1.67-dev libboost-date-time1.67-dev libboost-atomic1.67-dev libboost-chrono1.67-dev libogg-dev libvorbis-dev libavutil-dev libavformat-dev libswresample-dev libncursesw5-dev libasound2-dev libpulse-dev pulseaudio libmicrohttpd-dev libmp3lame-dev libcurl4-openssl-dev libev-dev libssl-dev libtag1-dev
- run: apt-get install -y build-essential clang cmake libboost-thread1.67-dev libboost-system1.67-dev libboost-filesystem1.67-dev libboost-date-time1.67-dev libboost-atomic1.67-dev libboost-chrono1.67-dev libogg-dev libvorbis-dev libavutil-dev libavformat-dev libswresample-dev libncursesw5-dev libasound2-dev libpulse-dev pulseaudio libmicrohttpd-dev libmp3lame-dev libcurl4-openssl-dev libev-dev libssl-dev libtag1-dev libsystemd-dev
- run: cmake -DGENERATE_DEB=1 -DDEB_ARCHITECTURE=amd64 -DDEB_PLATFORM=ubuntu -DDEB_DISTRO=eoan -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Release .
- run: make -j2
- run: make package
- run: mkdir -p /root/debs && mv /root/project/*.deb /root/debs/
- store_artifacts:
path: /root/debs/
build_ubuntu_focal:
docker:
- image: ubuntu:focal
steps:
- checkout
- run: apt-get update
- run: apt-get install -y build-essential clang cmake libboost-thread1.71-dev libboost-system1.71-dev libboost-filesystem1.71-dev libboost-date-time1.71-dev libboost-atomic1.71-dev libboost-chrono1.71-dev libogg-dev libvorbis-dev libavutil-dev libavformat-dev libswresample-dev libncursesw5-dev libasound2-dev libpulse-dev pulseaudio libmicrohttpd-dev libmp3lame-dev libcurl4-openssl-dev libev-dev libssl-dev libtag1-dev libsystemd-dev
- run: cmake -DGENERATE_DEB=1 -DDEB_ARCHITECTURE=amd64 -DDEB_PLATFORM=ubuntu -DDEB_DISTRO=eoan -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Release .
- run: make -j2
- run: make package
@ -126,6 +139,7 @@ workflows:
- build_ubuntu_cosmic: *workflow_filters
- build_ubuntu_disco: *workflow_filters
- build_ubuntu_eoan: *workflow_filters
- build_ubuntu_focal: *workflow_filters
- build_fedora_26: *workflow_filters
- build_fedora_27: *workflow_filters
- build_fedora_28: *workflow_filters

View File

@ -237,12 +237,19 @@ file(GLOB locales "src/musikcube/data/locales/*.json")
file(COPY ${locales} DESTINATION bin/locales)
install(FILES ${locales} DESTINATION share/musikcube/locales)
if (CMAKE_SYSTEM_NAME MATCHES "Linux")
file(GLOB_RECURSE linux_share_applications "src/musikcube/data/linux/share/applications/*")
install(FILES ${linux_share_applications} DESTINATION share/applications/)
file(GLOB_RECURSE linux_share_icons_48 "src/musikcube/data/linux/share/icons/hicolor/48x48/apps/*")
install(FILES ${linux_share_icons_48} DESTINATION share/icons/hicolor/48x48/apps/)
endif()
# libmusikcore sshared library
if (CMAKE_SYSTEM_NAME MATCHES "Darwin")
install(FILES "bin/libmusikcore.dylib" DESTINATION share/musikcube)
else ()
else()
install(FILES "bin/libmusikcore.so" DESTINATION share/musikcube)
endif ()
endif()
# executable and shell script for musikcube
install(
@ -307,6 +314,9 @@ if (GENERATE_DEB MATCHES "1")
set(DEB_AVUTIL_VERSION "56")
set(DEB_AVFORMAT_VERSION "58")
set(DEB_SWRESAMPLE_VERSION "3")
elseif (DEB_DISTRO MATCHES "focal")
set(DEB_BOOST_VERSION "1.71.0")
set(DEB_MICROHTTPD_VERSION "12")
elseif (DEB_DISTRO MATCHES "xenial")
set(DEB_BOOST_VERSION "1.58.0")
set(DEB_MICROHTTPD_VERSION "10")
@ -349,5 +359,5 @@ add_custom_command(TARGET postbuild POST_BUILD COMMAND cmake .)
# strip binaries in release mode
if (CMAKE_BUILD_TYPE MATCHES Release)
message(STATUS "stripping binaries...")
add_custom_command(TARGET postbuild POST_BUILD COMMAND ./strip-nix.sh)
add_custom_command(TARGET postbuild POST_BUILD COMMAND "${CMAKE_SOURCE_DIR}/strip-nix.sh")
endif()

51
install-deps.sh Executable file
View File

@ -0,0 +1,51 @@
#!/bin/bash
OS=`uname`
if [ $OS == "Linux" ]; then
echo "detected linux"
if [ -x "$(command -v lsb_release)" ]; then
DISTRO=`lsb_release -cs`
echo "detected ${DISTRO}"
case $DISTRO in
"focal")
sudo apt-get install build-essential clang cmake libboost-thread1.71-dev libboost-system1.71-dev libboost-filesystem1.71-dev libboost-date-time1.71-dev libboost-atomic1.71-dev libboost-chrono1.71-dev libogg-dev libvorbis-dev libavutil-dev libavformat-dev libswresample-dev libncursesw5-dev libasound2-dev libpulse-dev pulseaudio libmicrohttpd-dev libmp3lame-dev libcurl4-openssl-dev libev-dev libtag1-dev libsystemd-dev
;;
"cosmic" | "disco" | "eoan")
sudo apt-get install build-essential clang cmake libboost-thread1.67-dev libboost-system1.67-dev libboost-filesystem1.67-dev libboost-date-time1.67-dev libboost-atomic1.67-dev libboost-chrono1.67-dev libogg-dev libvorbis-dev libavutil-dev libavformat-dev libswresample-dev libncursesw5-dev libasound2-dev libpulse-dev pulseaudio libmicrohttpd-dev libmp3lame-dev libcurl4-openssl-dev libev-dev libtag1-dev libsystemd-dev
;;
"bionic")
sudo apt-get install build-essential clang cmake libboost-thread1.65-dev libboost-system1.65-dev libboost-filesystem1.65-dev libboost-date-time1.65-dev libboost-atomic1.65-dev libboost-chrono1.65-dev libogg-dev libvorbis-dev libavutil-dev libavformat-dev libswresample-dev libncursesw5-dev libasound2-dev libpulse-dev pulseaudio libmicrohttpd-dev libmp3lame-dev libcurl4-openssl-dev libev-dev libtag1-dev libsystemd-dev
;;
"artful")
sudo apt-get install build-essential clang cmake libboost-thread1.63-dev libboost-system1.63-dev libboost-filesystem1.63-dev libboost-date-time1.63-dev libboost-atomic1.63-dev libboost-chrono1.63-dev libogg-dev libvorbis-dev libavutil-dev libavformat-dev libswresample-dev libncursesw5-dev libasound2-dev libpulse-dev pulseaudio libmicrohttpd-dev libmp3lame-dev libcurl4-openssl-dev libev-dev libtag1-dev libsystemd-dev
;;
esac
fi
if [ -f "/etc/fedora-release" ]; then
DISTRO=`cat /etc/fedora-release`
echo "detected ${DISTRO}"
sudo dnf install gcc-c++ make cmake boost-devel libogg-devel libvorbis-devel ffmpeg-devel ncurses-devel zlib-devel alsa-lib-devel pulseaudio-libs-devel libcurl-devel libmicrohttpd-devel lame-devel libev-devel taglib-devel libsystemd-devel
fi
if [ -f "/etc/arch-release" ] || [ -f "/etc/manjaro-release" ]; then
sudo pacman -S libogg libvorbis libmicrohttpd ffmpeg lame cmake ncurses boost pulseaudio libpulse alsa-lib curl libev taglib
fi
if [ -f "/etc/SUSE-brand" ]; then
echo "detected SUSE"
sudo zypper install libcurl-devel libmicrohttpd-devel libboost_thread1_71_0-devel libboost_system1_71_0-devel libboost_filesystem1_71_0-devel libboost_date_time1_71_0-devel libboost_atomic1_71_0-devel libboost_chrono1_71_0-devel cmake ncurses-devel libogg-devel libvorbis-devel ffmpeg-3-libavcodec-devel ffmpeg-3-libswresample-devel ffmpeg-3-libavformat-devel ffmpeg-3-libavutil-devel libmp3lame-devel pulseaudio libpulse-devel alsa-devel zlib-devel libressl-devel libev-devel libtag-devel systemd-devel
fi
fi
if [ $OS == "Darwin" ]; then
echo "detected macos"
brew install cmake boost libogg libvorbis ffmpeg libmicrohttpd lame libev taglib
fi
if [ $OS == "FreeBSD" ]; then
echo "detected freebsd"
pkg install boost-all curl libvorbis libogg libmicrohttpd ffmpeg alsa-lib cmake sndio libev taglib bash
portsnap fetch
portsnap extract
cd /usr/ports/audio/lame
make reinstall
fi
if [ $OS == "OpenBSD" ]; then
echo "detected openbsd"
pkg_add git cmake ffmpeg boost sndio libev libmicrohttpd taglib
fi

View File

@ -8,7 +8,7 @@ Summary: A cross-platform, terminal-based audio engine, library, player and serv
Source0: https://github.com/clangen/musikcube/archive/%{version}.tar.gz#/%{name}-%{version}.tar.gz
License: BSD-3-Clause
Packager: David Muckle <dvdmuckle@dvdmuckle.xyz>
BuildRequires: gcc-c++ cmake boost-devel libogg-devel libvorbis-devel ffmpeg-devel ncurses-devel zlib-devel alsa-lib-devel pulseaudio-libs-devel openssl-devel libcurl-devel libmicrohttpd-devel lame-devel libev-devel taglib-devel make
BuildRequires: gcc-c++ cmake boost-devel libogg-devel libvorbis-devel ffmpeg-devel ncurses-devel zlib-devel alsa-lib-devel pulseaudio-libs-devel openssl-devel libcurl-devel libmicrohttpd-devel lame-devel libev-devel taglib-devel systemd-devel make
Requires: boost libogg libvorbis ffmpeg-libs ncurses zlib alsa-lib pulseaudio-libs openssl libcurl libmicrohttpd lame libev taglib
%description

View File

@ -0,0 +1,13 @@
[Desktop Entry]
Version=1.0
Type=Application
Name=musikcube
GenericName=musikcube
Comment=terminal-based music player
Exec=musikcube %U
TryExec=musikcube
Icon=musikcube
Terminal=true
Categories=AudioVideo;Player;Audio;
StartupNotify=false
StartupWMClass=musikcube

Binary file not shown.

After

Width:  |  Height:  |  Size: 801 B

100
snap/snapcraft.yaml Normal file
View File

@ -0,0 +1,100 @@
name: musikcube # you probably want to 'snapcraft register <name>'
version: 0.85.0
summary: a terminal-based music player, metadata indexer, and server
description: |
musikcube is a fully functional terminal-based music player, library, and
streaming audio server that runs natively on Windows, macOS, and Linux. It
also runs well on a Raspberry Pi with a custom DAC (e.g. IQaudIO DAC+,
HiFiBerry DAC+ and others), and can output 24bit/192k audio comfortably.
grade: stable
confinement: strict
base: core18
parts:
desktop-glib-musikcube:
source: https://github.com/ubuntu/snapcraft-desktop-helpers.git
source-subdir: glib-only/
plugin: make
build-packages:
- libglib2.0-dev
stage-packages:
- libglib2.0-bin
musikcube:
after:
- desktop-glib-musikcube
plugin: cmake
configflags:
- -DCMAKE_BUILD_TYPE=Release
source: https://github.com/clangen/musikcube.git
build-packages:
- build-essential
- clang
- cmake
- libboost-thread1.65-dev
- libboost-system1.65-dev
- libboost-filesystem1.65-dev
- libboost-date-time1.65-dev
- libboost-atomic1.65-dev
- libboost-chrono1.65-dev
- libogg-dev
- libvorbis-dev
- libavutil-dev
- libavformat-dev
- libswresample-dev
- libncursesw5-dev
- libasound2-dev
- libpulse-dev
- libmicrohttpd-dev
- libmp3lame-dev
- libcurl4-openssl-dev
- libev-dev
- libtag1-dev
- libsystemd-dev
- libssl-dev
stage-packages:
- libboost-thread1.65.1
- libboost-system1.65.1
- libboost-chrono1.65.1
- libboost-filesystem1.65.1
- libboost-date-time1.65.1
- libmicrohttpd12
- libcurl4
- libogg0
- libvorbis0a
- libvorbisfile3
- libncursesw5
- libasound2
- libpulse0
- libmp3lame0
- libev4
- libavcodec-extra
- libavutil55
- libavformat57
- libswresample2
- libsystemd0
- libtag1v5
apps:
musikcube:
desktop: share/applications/musikcube.desktop
command: desktop-launch $SNAP/share/musikcube/musikcube
environment:
LD_LIBRARY_PATH: $LD_LIBRARY_PATH:$SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/pulseaudio
ALSA_CONFIG_PATH: /snap/$SNAPCRAFT_PROJECT_NAME/current/usr/share/alsa/alsa.conf
LANG: C.UTF-8
plugs:
- home
- removable-media
- pulseaudio
- network
- network-bind
- audio-playback
- alsa
- desktop
slots:
- mpris
layout:
/usr/share/alsa:
bind: $SNAP/usr/share/alsa

View File

@ -129,6 +129,10 @@ void DirectoryLayout::SetDirectory(const std::string& directory) {
this->Refresh(true);
}
std::string DirectoryLayout::GetDirectory() {
return this->adapter->GetCurrentPath();
}
void DirectoryLayout::OnVisibilityChanged(bool visible) {
LayoutBase::OnVisibilityChanged(visible);
if (visible) {

View File

@ -62,7 +62,8 @@ namespace musik {
virtual void OnVisibilityChanged(bool visible);
virtual bool KeyPress(const std::string& key);
virtual void SetDirectory(const std::string& directory);
void SetDirectory(const std::string& directory);
std::string GetDirectory();
protected:
virtual void OnLayout();

View File

@ -159,7 +159,7 @@ void LibraryLayout::ShowBrowse(const std::string& category) {
if (category.size()) {
this->browseLayout->SwitchCategory(category);
}
this->lastBrowseCategoryType = category;
REMEMBER(keys::LastLibraryView, type::Browse);
}
@ -167,7 +167,6 @@ void LibraryLayout::ShowCategorySearch() {
SHOULD_REFOCUS(this->categorySearchLayout)
? this->categorySearchLayout->FocusInput()
: this->ChangeMainLayout(this->categorySearchLayout);
REMEMBER(keys::LastLibraryView, type::CategoryFilter);
}
@ -180,11 +179,13 @@ void LibraryLayout::ShowTrackSearch() {
}
void LibraryLayout::ShowDirectories(const std::string& directory) {
this->directoryLayout->SetDirectory(directory);
if (directory.size()) {
this->directoryLayout->SetDirectory(directory);
REMEMBER(keys::LastBrowseDirectoryRoot, directory);
}
this->ChangeMainLayout(this->directoryLayout);
this->lastBrowseCategoryType = MagicConstants::DirectoryCategoryType;
REMEMBER(keys::LastLibraryView, type::Directory);
REMEMBER(keys::LastBrowseDirectoryRoot, directory);
}
void LibraryLayout::InitializeWindows() {
@ -349,7 +350,7 @@ IWindowPtr LibraryLayout::GetFocus() {
result = this->visibleLayout->GetFocus();
}
return result;
return result;
}
bool LibraryLayout::SetFocus(cursespp::IWindowPtr window) {
@ -445,7 +446,12 @@ bool LibraryLayout::KeyPress(const std::string& key) {
return true;
}
else if (Hotkeys::Is(Hotkeys::NavigateLibraryBrowse, key)) {
this->ShowBrowse();
if (this->lastBrowseCategoryType == MagicConstants::DirectoryCategoryType) {
this->ShowDirectories();
}
else {
this->ShowBrowse();
}
return true;
}
else if (Hotkeys::Is(Hotkeys::NavigateLibraryFilter, key)) {

View File

@ -97,7 +97,7 @@ namespace musik {
void ShowCategorySearch();
void ShowTrackSearch();
void ShowDirectoryChooser();
void ShowDirectories(const std::string& directory);
void ShowDirectories(const std::string& directory = "");
void ChangeMainLayout(std::shared_ptr<cursespp::LayoutBase> newLayout);
void OnLayoutChanged();
@ -115,6 +115,7 @@ namespace musik {
std::shared_ptr<TrackSearchLayout> trackSearchLayout;
std::shared_ptr<cursespp::LayoutBase> visibleLayout;
cursespp::ShortcutsWindow* shortcuts;
std::string lastBrowseCategoryType;
};
}
}

View File

@ -516,6 +516,7 @@ void PlayQueueOverlays::ShowAddCategoryOverlay(
adapter->AddEntry(_TSTR("playqueue_overlay_add_to_start_of_queue"));
adapter->AddEntry(_TSTR("playqueue_overlay_add_to_end_in_queue"));
adapter->AddEntry(_TSTR("playqueue_overlay_add_as_next_in_queue"));
adapter->AddEntry(_TSTR("playqueue_overlay_add_hotswap_queue"));
adapter->SetSelectable(true);
size_t selectedIndex = 0;
@ -542,6 +543,11 @@ void PlayQueueOverlays::ShowAddCategoryOverlay(
showAddCategorySelectionToPlaylistOverlay(
messageQueue, library, fieldColumn, fieldValue, fieldId);
}
else if (index == adapter->GetEntryCount() - 1) {
auto tracks = queryTracksByCategory(
library, fieldColumn, fieldValue, fieldId);
playback.HotSwap(*tracks);
}
else {
handleAddCategorySelectionToPlayQueue(
playback, library, fieldColumn, fieldValue, fieldId, index - 1);

View File

@ -223,11 +223,12 @@ struct musik::cube::TransportDisplayCache {
if (updatedTotal != secondsTotal) {
secondsTotal = updatedTotal;
if (secondsTotal <= 0 && secondsTotal != INT_MIN) {
std::string duration =
this->track->GetString(constants::Track::DURATION);
if (duration.size()) {
secondsTotal = std::stoi(duration);
if (this->track) {
std::string duration =
this->track->GetString(constants::Track::DURATION);
if (duration.size()) {
secondsTotal = std::stoi(duration);
}
}
}

View File

@ -0,0 +1,13 @@
[Desktop Entry]
Version=1.0
Type=Application
Name=musikcube
GenericName=musikcube
Comment=terminal-based music player
Exec=musikcube %U
TryExec=musikcube
Icon=musikcube
Terminal=true
Categories=AudioVideo;Player;Audio;
StartupNotify=false
StartupWMClass=musikcube

Binary file not shown.

After

Width:  |  Height:  |  Size: 801 B

View File

@ -159,6 +159,7 @@
"playqueue_overlay_add_to_start_of_queue": "add to beginning of play queue",
"playqueue_overlay_add_to_end_in_queue": "add to end of play queue",
"playqueue_overlay_add_as_next_in_queue": "add as next in play queue",
"playqueue_overlay_add_hotswap_queue": "hotswap with play queue",
"playqueue_overlay_add_to_playlist": "add to playlist",
"playqueue_overlay_select_playlist_title": "select a playlist",

View File

@ -165,6 +165,7 @@ AlsaOut::~AlsaOut() {
}
void AlsaOut::CloseDevice() {
LOCK("CloseDevice()");
if (this->pcmHandle) {
std::cerr << "AlsaOut: closing PCM handle\n";
snd_pcm_close(this->pcmHandle);
@ -417,12 +418,17 @@ void AlsaOut::WriteLoop() {
}
}
WRITE_BUFFER(this->pcmHandle, next, samplesPerChannel); /* sets 'err' */
{
LOCK("WRITE_BUFFER()");
if (this->pcmHandle) {
WRITE_BUFFER(this->pcmHandle, next, samplesPerChannel); /* sets 'err' */
if (err == -EINTR || err == -EPIPE || err == -ESTRPIPE) {
if (!snd_pcm_recover(this->pcmHandle, err, 1)) {
/* try one more time... */
WRITE_BUFFER(this->pcmHandle, next, samplesPerChannel);
if (err == -EINTR || err == -EPIPE || err == -ESTRPIPE) {
if (!snd_pcm_recover(this->pcmHandle, err, 1)) {
/* try one more time... */
WRITE_BUFFER(this->pcmHandle, next, samplesPerChannel);
}
}
}
}
@ -493,20 +499,22 @@ void AlsaOut::SetFormat(IBuffer *buffer) {
this->InitDevice();
int err = snd_pcm_set_params(
this->pcmHandle,
PCM_FORMAT,
PCM_ACCESS_TYPE,
this->channels,
this->rate,
1, /* allow resampling */
500000); /* 0.5s latency */
if (this->pcmHandle) {
int err = snd_pcm_set_params(
this->pcmHandle,
PCM_FORMAT,
PCM_ACCESS_TYPE,
this->channels,
this->rate,
1, /* allow resampling */
500000); /* 0.5s latency */
if (err > 0) {
std::cerr << "AlsaOut: set format error: " << snd_strerror(err) << std::endl;
}
else {
this->SetVolume(this->volume);
if (err > 0) {
std::cerr << "AlsaOut: set format error: " << snd_strerror(err) << std::endl;
}
else {
this->SetVolume(this->volume);
}
}
std::cerr << "AlsaOut: device format initialized from buffer\n";

View File

@ -188,6 +188,7 @@ static int get_metadata(sd_bus* bus, const char* path, const char *iface,
// append fields
sd_msg_append_dict(reply, "mpris:trackid", metadata.trackid.c_str(), 'o');
sd_msg_append_dict(reply, "mpris:length", &metadata.length, 'x');
sd_msg_append_dict(reply, "mpris:artUrl", metadata.albumArt.c_str(), 's');
sd_msg_append_strlist_dict(reply, "xesam:artist", metadata.artist.c_str());
sd_msg_append_dict(reply, "xesam:title", metadata.title.c_str(), 's');
sd_msg_append_dict(reply, "xesam:album", metadata.album.c_str(), 's');

View File

@ -4,12 +4,14 @@
#include <map>
#include <vector>
#include <functional>
#include <core/sdk/IEnvironment.h>
extern "C" {
#include <unistd.h>
}
thread_local char localBuffer[1024];
std::string thumbnailPath;
thread_local char localBuffer[4096];
static MPRISRemote remote;
static const std::map<MPRISProperty, const std::vector<const char*>> MPRISPropertyNames =
@ -25,6 +27,12 @@ static std::string GetMetadataString(ITrack* track, const char* key)
return std::string(localBuffer);
}
static std::string GetThumbnailPath(ITrack* track)
{
int64_t thumbnailId = track->GetInt64(track::ThumbnailId);
return thumbnailPath + std::to_string(thumbnailId) + ".jpg";
}
static class MPRISPlugin : public IPlugin {
public:
MPRISPlugin() { }
@ -39,6 +47,13 @@ static class MPRISPlugin : public IPlugin {
int SdkVersion() { return musik::core::sdk::SdkVersion; }
} plugin;
extern "C" void SetEnvironment(IEnvironment* environment) {
if (environment) {
environment->GetPath(PathLibrary, localBuffer, sizeof(localBuffer));
thumbnailPath = std::string(localBuffer) + "/thumbs/";
}
}
extern "C" IPlugin* GetPlugin() {
return &plugin;
}
@ -101,7 +116,7 @@ void MPRISRemote::MPRISDeinit() {
void MPRISRemote::MPRISEmitChange(MPRISProperty prop) {
if (bus) {
char** strv = (char**)(&MPRISPropertyNames.at(prop));
char** strv = (char**)(MPRISPropertyNames.at(prop).data());
std::unique_lock<decltype(sd_mutex)> lock(sd_mutex);
sd_bus_emit_properties_changed_strv(bus, "/org/mpris/MediaPlayer2",
"org.mpris.MediaPlayer2.Player",
@ -181,6 +196,7 @@ struct MPRISMetadataValues MPRISRemote::MPRISGetMetadata() {
metadata.discNumber = curTrack->GetInt32(track::DiscNum);
metadata.trackNumber = curTrack->GetInt32(track::TrackNum);
metadata.length = curTrack->GetInt64(track::Duration)*1000*1000;
metadata.albumArt = GetThumbnailPath(curTrack);
metadata.available = true;
}
}

View File

@ -27,6 +27,7 @@ struct MPRISMetadataValues {
std::string title;
std::string album;
std::string albumArtist;
std::string albumArt;
std::string genre;
std::string comment;
uint32_t trackNumber;

View File

@ -242,6 +242,7 @@ void PulseOut::OpenDevice(musik::core::sdk::IBuffer* buffer) {
this->rate != buffer->SampleRate() ||
this->channels != buffer->Channels())
{
int errorCode = 0;
this->CloseDevice();
pa_sample_spec spec;
@ -249,9 +250,8 @@ void PulseOut::OpenDevice(musik::core::sdk::IBuffer* buffer) {
spec.channels = buffer->Channels();
spec.rate = buffer->SampleRate();
std::cerr << "PulseOut: opening device\n";
std::string deviceId = this->GetPreferredDeviceId();
std::cerr << "PulseOut: opening device " << deviceId << "\n";
/* output to preferred device id, as specified in prefs */
this->audioConnection = pa_blocking_new(
@ -263,7 +263,11 @@ void PulseOut::OpenDevice(musik::core::sdk::IBuffer* buffer) {
&spec,
nullptr,
nullptr,
0);
&errorCode);
if (!this->audioConnection) {
std::cerr << "PulseOut: failed to open device. errorCode=" << errorCode << "\n";
}
if (!this->audioConnection && deviceId.size()) {
/* fall back to default if preferred is not found */
@ -276,7 +280,11 @@ void PulseOut::OpenDevice(musik::core::sdk::IBuffer* buffer) {
&spec,
nullptr,
nullptr,
0);
&errorCode);
if (!this->audioConnection) {
std::cerr << "PulseOut: failed to open default device. errorCode=" << errorCode << "\n";
}
}
if (this->audioConnection) {

View File

@ -158,10 +158,15 @@ pa_blocking* pa_blocking_new(
pa_blocking *p;
int error = PA_ERR_INTERNAL, r;
fprintf(stderr, "pulse_blocking_stream: CHECK_VALIDITY server\n");
CHECK_VALIDITY_RETURN_ANY(rerror, !server || *server, PA_ERR_INVALID, NULL);
fprintf(stderr, "pulse_blocking_stream: CHECK_VALIDITY dir\n");
CHECK_VALIDITY_RETURN_ANY(rerror, dir == PA_STREAM_PLAYBACK || dir == PA_STREAM_RECORD, PA_ERR_INVALID, NULL);
fprintf(stderr, "pulse_blocking_stream: CHECK_VALIDITY device\n");
CHECK_VALIDITY_RETURN_ANY(rerror, !dev || *dev, PA_ERR_INVALID, NULL);
fprintf(stderr, "pulse_blocking_stream: CHECK_VALIDITY spec\n");
CHECK_VALIDITY_RETURN_ANY(rerror, ss && pa_sample_spec_valid(ss), PA_ERR_INVALID, NULL);
fprintf(stderr, "pulse_blocking_stream: CHECK_VALIDITY channel map\n");
CHECK_VALIDITY_RETURN_ANY(rerror, !map || (pa_channel_map_valid(map) && map->channels == ss->channels), PA_ERR_INVALID, NULL)
p = pa_xnew0(pa_blocking, 1);
@ -170,33 +175,43 @@ pa_blocking* pa_blocking_new(
p->sink_id = -1;
p->hw_volume = -1;
if (!(p->mainloop = pa_threaded_mainloop_new()))
if (!(p->mainloop = pa_threaded_mainloop_new())) {
fprintf(stderr, "pulse_blocking_stream: failed to create main loop\n");
goto fail;
}
if (!(p->context = pa_context_new(pa_threaded_mainloop_get_api(p->mainloop), name)))
if (!(p->context = pa_context_new(pa_threaded_mainloop_get_api(p->mainloop), name))) {
fprintf(stderr, "pulse_blocking_stream: failed to create context\n");
goto fail;
}
pa_context_set_state_callback(p->context, context_state_cb, p);
if (pa_context_connect(p->context, server, 0, NULL) < 0) {
fprintf(stderr, "pulse_blocking_stream: failed to connect context\n");
error = pa_context_errno(p->context);
goto fail;
}
pa_threaded_mainloop_lock(p->mainloop);
if (pa_threaded_mainloop_start(p->mainloop) < 0)
if (pa_threaded_mainloop_start(p->mainloop) < 0) {
fprintf(stderr, "pulse_blocking_stream: failed to start main loop\n");
goto unlock_and_fail;
}
for (;;) {
pa_context_state_t state;
state = pa_context_get_state(p->context);
if (state == PA_CONTEXT_READY)
if (state == PA_CONTEXT_READY) {
fprintf(stderr, "pulse_blocking_stream: context is ready\n");
break;
}
if (!PA_CONTEXT_IS_GOOD(state)) {
fprintf(stderr, "pulse_blocking_stream: context is bad\n");
error = pa_context_errno(p->context);
goto unlock_and_fail;
}
@ -206,6 +221,7 @@ pa_blocking* pa_blocking_new(
}
if (!(p->stream = pa_stream_new(p->context, stream_name, ss, map))) {
fprintf(stderr, "pulse_blocking_stream: failed to create stream\n");
error = pa_context_errno(p->context);
goto unlock_and_fail;
}
@ -227,6 +243,7 @@ pa_blocking* pa_blocking_new(
|PA_STREAM_AUTO_TIMING_UPDATE);
if (r < 0) {
fprintf(stderr, "pulse_blocking_stream: failed to connect stream to output device\n");
error = pa_context_errno(p->context);
goto unlock_and_fail;
}
@ -236,10 +253,13 @@ pa_blocking* pa_blocking_new(
state = pa_stream_get_state(p->stream);
if (state == PA_STREAM_READY)
if (state == PA_STREAM_READY) {
fprintf(stderr, "pulse_blocking_stream: stream is ready\n");
break;
}
if (!PA_STREAM_IS_GOOD(state)) {
fprintf(stderr, "pulse_blocking_stream: stream is bad\n");
error = pa_context_errno(p->context);
goto unlock_and_fail;
}
@ -249,13 +269,14 @@ pa_blocking* pa_blocking_new(
}
pa_threaded_mainloop_unlock(p->mainloop);
fflush(stderr);
return p;
unlock_and_fail:
pa_threaded_mainloop_unlock(p->mainloop);
fail:
fflush(stderr);
if (rerror)
*rerror = error;
pa_blocking_free(p);