Merge pull request #1622 from awiouy/librespot

librespot: initial addon
This commit is contained in:
Christian Hewitt 2017-06-20 10:00:52 +04:00 committed by GitHub
commit 97fa217f54
14 changed files with 727 additions and 1 deletions

View File

@ -0,0 +1,38 @@
################################################################################
# This file is part of LibreELEC - https://libreelec.tv
# Copyright (C) 2017-present Team LibreELEC
#
# LibreELEC is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# LibreELEC is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with LibreELEC. If not, see <http://www.gnu.org/licenses/>.
################################################################################
PKG_NAME="pyalsaaudio"
PKG_VERSION="0.8.4"
PKG_LICENSE="PSF"
PKG_SITE="http://larsimmisch.github.io/pyalsaaudio/"
PKG_URL="https://files.pythonhosted.org/packages/source/${PKG_NAME:0:1}/$PKG_NAME/$PKG_NAME-$PKG_VERSION.tar.gz"
PKG_DEPENDS_TARGET="toolchain Python distutilscross:host alsa-lib"
PKG_LONGDESC="ALSA bindings"
make_target() {
export LDSHARED="$CC -shared"
export PYTHONXCPREFIX="$SYSROOT_PREFIX/usr"
python setup.py build --cross-compile
}
makeinstall_target() {
python setup.py install --root=$INSTALL --prefix=/usr
find $INSTALL/usr/lib -name "*.py" -exec rm -rf "{}" ";"
rm -rf $INSTALL/usr/lib/python*/site-packages/*.egg-info \
$INSTALL/usr/lib/python*/site-packages/*/tests
}

View File

@ -0,0 +1,81 @@
################################################################################
# This file is part of LibreELEC - https://libreelec.tv
# Copyright (C) 2017-present Team LibreELEC
#
# LibreELEC is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# LibreELEC is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with LibreELEC. If not, see <http://www.gnu.org/licenses/>.
################################################################################
PKG_NAME="rust"
PKG_VERSION="1.18.0"
PKG_ARCH="any"
PKG_LICENSE="MIT"
PKG_SITE="https://www.rust-lang.org"
PKG_URL=""
PKG_DEPENDS="toolchain"
PKG_SECTION="devel"
PKG_LONGDESC="Rust is a systems programming language that runs blazingly fast, prevents segfaults, and guarantees thread safety."
PKG_IS_ADDON="no"
PKG_AUTORECONF="no"
unpack() {
:
}
configure_target() {
:
}
make_target() {
export CARGO_HOME="$ROOT/$TOOLCHAIN/.cargo"
export RUSTUP_HOME="$CARGO_HOME"
export PATH="$CARGO_HOME/bin:$PATH"
rm -rf "$CARGO_HOME"
curl https://sh.rustup.rs -sSf | sh -s -- --no-modify-path -y
rustup default "$PKG_VERSION"
case "$TARGET_ARCH" in
aarch64)
RUST_TRIPLE="aarch64-unknown-linux-gnu"
;;
arm)
RUST_TRIPLE="arm-unknown-linux-gnueabihf"
;;
x86_64)
RUST_TRIPLE="x86_64-unknown-linux-gnu"
;;
esac
if [ "$TARGET_ARCH" != "x86_64" ]; then
rustup target add "$RUST_TRIPLE"
fi
cat <<EOF >"$CARGO_HOME/config"
[target.$RUST_TRIPLE]
linker = "$CC"
EOF
cat <<'EOF' >"$CARGO_HOME/env"
export CARGO_HOME="$ROOT/$TOOLCHAIN/.cargo"
export CARGO_TARGET_DIR="$ROOT/$PKG_BUILD/.$TARGET_NAME"
export PATH="$CARGO_HOME/bin:$PATH"
export RUSTUP_HOME="$CARGO_HOME"
mkdir -p "$CARGO_TARGET_DIR"
EOF
echo "CARGO_BUILD=\"cargo build --release --target $RUST_TRIPLE\"" \
>>"$CARGO_HOME/env"
}
makeinstall_target() {
:
}

View File

@ -0,0 +1,2 @@
100
- Initial addon

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View File

@ -0,0 +1,64 @@
################################################################################
# This file is part of LibreELEC - https://libreelec.tv
# Copyright (C) 2017-present Team LibreELEC
# Copyright (C) 2017 Shane Meagher (shanemeagher)
#
# LibreELEC is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# LibreELEC is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with LibreELEC. If not, see <http://www.gnu.org/licenses/>.
################################################################################
PKG_NAME="librespot"
PKG_VERSION="2259188"
PKG_REV="100"
PKG_ARCH="any"
PKG_LICENSE="prop."
PKG_SITE="https://github.com/plietar/$PKG_NAME/"
PKG_URL="https://github.com/plietar/$PKG_NAME/archive/$PKG_VERSION.zip"
PKG_DEPENDS_TARGET="toolchain avahi pyalsaaudio rust"
PKG_SECTION="service"
PKG_LONGDESC="Librespot ($PKG_VERSION) plays Spotify through LibreELEC using the opensource librespot library using a Spotify app as a remote."
PKG_AUTORECONF="no"
PKG_IS_ADDON="yes"
PKG_ADDON_NAME="Librespot"
PKG_ADDON_TYPE="xbmc.service"
PKG_MAINTAINER="Anton Voyl (awiouy)"
configure_target() {
. "$ROOT/$TOOLCHAIN/.cargo/env"
export PKG_CONFIG_ALLOW_CROSS=0
strip_lto
}
make_target() {
cd src
$CARGO_BUILD --no-default-features --features "alsa-backend with-avahi"
}
makeinstall_target() {
:
}
addon() {
mkdir -p "$ADDON_BUILD/$PKG_ADDON_ID/bin"
cp "$PKG_BUILD/.$TARGET_NAME"/*/release/librespot \
"$ADDON_BUILD/$PKG_ADDON_ID/bin"
mkdir -p "$ADDON_BUILD/$PKG_ADDON_ID/lib"
cp "$(get_build_dir avahi)/avahi-compat-libdns_sd/.libs/libdns_sd.so.1" \
"$ADDON_BUILD/$PKG_ADDON_ID/lib"
mkdir -p "$ADDON_BUILD/$PKG_ADDON_ID/wizard"
cp "$(get_build_dir pyalsaaudio)/.install_pkg/usr/lib/python2.7/site-packages/alsaaudio.so" \
"$ADDON_BUILD/$PKG_ADDON_ID/wizard/"
}

View File

@ -0,0 +1,222 @@
From a825f84d9d00b196232fcccc5b5e441654c4e5a0 Mon Sep 17 00:00:00 2001
From: shanemeagher <shanemeagher@outlook.com>
Date: Fri, 9 Jun 2017 22:43:54 +0800
Subject: [PATCH] Build librespot with avahi support for Discovery
rust-mdns is still the default and can be specified explicitly with --with-rust-mdns switch.
Added --with-avahi switch to build librespot to use avahi for discovery using dns-sd package.
---
Cargo.lock | 10 ++++++++++
Cargo.toml | 7 +++++--
contrib/Dockerfile | 3 +++
contrib/docker-build-avahi.sh | 24 ++++++++++++++++++++++++
src/authentication/discovery.rs | 27 ++++++++++++++++++++++++++-
src/lib.rs | 6 +++++-
6 files changed, 73 insertions(+), 4 deletions(-)
create mode 100755 contrib/docker-build-avahi.sh
diff --git a/Cargo.lock b/Cargo.lock
index 30fafca..eff0925 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -6,6 +6,7 @@ dependencies = [
"base64 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
"bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "dns-sd 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"error-chain 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -144,6 +145,15 @@ dependencies = [
]
[[package]]
+name = "dns-sd"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
name = "dtoa"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
index 5d64719..c543e92 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -52,7 +52,8 @@ alsa = { git = "https://github.com/plietar/rust-alsa", optional = tru
portaudio-rs = { version = "0.3.0", optional = true }
libpulse-sys = { git = "https://github.com/astro/libpulse-sys", optional = true }
-mdns = { git = "https://github.com/plietar/rust-mdns" }
+mdns = { git = "https://github.com/plietar/rust-mdns", optional = true }
+dns-sd = { version = "~0.1.3", optional = true }
error-chain = { version = "0.9.0", default_features = false }
futures = "0.1.8"
@@ -71,8 +72,10 @@ portaudio-backend = ["portaudio-rs"]
pulseaudio-backend = ["libpulse-sys"]
with-tremor = ["tremor"]
+with-rust-mdns = ["mdns"]
+with-avahi = ["dns-sd"]
-default = ["portaudio-backend"]
+default = ["portaudio-backend","with-rust-mdns"]
[package.metadata.deb]
maintainer = "nobody"
diff --git a/contrib/Dockerfile b/contrib/Dockerfile
index 68a39b7..f6aec14 100644
--- a/contrib/Dockerfile
+++ b/contrib/Dockerfile
@@ -4,6 +4,8 @@
#
# The resulting image can be used to build librespot for linux x86_64, armhf and armel.
# $ docker run -v /tmp/librespot-build:/build librespot-cross
+# To build librespot with avahi support
+# $ docker run -v /tmp/librespot-build:/build librespot-cross /src/contrib/docker-build-avahi.sh
#
# The compiled binaries will be located in /tmp/librespot-build
#
@@ -23,6 +25,7 @@ RUN apt-get update
RUN apt-get install -y curl git build-essential crossbuild-essential-arm64 crossbuild-essential-armel crossbuild-essential-armhf crossbuild-essential-mipsel
RUN apt-get install -y libasound2-dev libasound2-dev:arm64 libasound2-dev:armel libasound2-dev:armhf libasound2-dev:mipsel
+RUN apt-get install -y libavahi-compat-libdnssd-dev libavahi-compat-libdnssd-dev:arm64 libavahi-compat-libdnssd-dev:armel libavahi-compat-libdnssd-dev:armhf libavahi-compat-libdnssd-dev:mipsel
RUN curl https://sh.rustup.rs -sSf | sh -s -- -y
ENV PATH="/root/.cargo/bin/:${PATH}"
diff --git a/contrib/docker-build-avahi.sh b/contrib/docker-build-avahi.sh
new file mode 100755
index 0000000..c25b248
--- /dev/null
+++ b/contrib/docker-build-avahi.sh
@@ -0,0 +1,24 @@
+#!/usr/bin/env bash
+set -eux
+
+cargo build --release --no-default-features --features "alsa-backend with-avahi"
+cp /usr/lib/x86_64-linux-gnu/libdns_sd.so.1 /build/release
+
+export PKG_CONFIG_ALLOW_CROSS=0
+
+export PKG_CONFIG_PATH=/usr/lib/aarch64-unknown-linux-gnu/pkgconfig
+cargo build --release --target aarch64-unknown-linux-gnu --no-default-features --features "alsa-backend with-avahi"
+cp /usr/lib/aarch64-linux-gnu/libdns_sd.so.1 /build/aarch64-unknown-linux-gnu/release
+
+export PKG_CONFIG_PATH=/usr/lib/arm-linux-gnueabi/pkgconfig
+cargo build --release --target arm-unknown-linux-gnueabi --no-default-features --features "alsa-backend with-avahi"
+cp /usr/lib/arm-linux-gnueabi/libdns_sd.so.1 /build/arm-unknown-linux-gnueabi/release
+
+export PKG_CONFIG_PATH=/usr/lib/arm-linux-gnueabihf/pkgconfig
+cargo build --release --target arm-unknown-linux-gnueabihf --no-default-features --features "alsa-backend with-avahi"
+cp /usr/lib/arm-linux-gnueabihf/libdns_sd.so.1 /build/arm-unknown-linux-gnueabihf/release
+
+export PKG_CONFIG_PATH=/usr/lib/mipsel-linux-gnu/pkgconfig
+cargo build --release --target mipsel-unknown-linux-gnu --no-default-features --features "alsa-backend with-avahi"
+cp /usr/libmipsel-linux-gnu/libdns_sd.so.1 /build/mipsel-unknown-linux-gnu/release
+
diff --git a/src/authentication/discovery.rs b/src/authentication/discovery.rs
index 8c5b005..d385294 100644
--- a/src/authentication/discovery.rs
+++ b/src/authentication/discovery.rs
@@ -7,7 +7,6 @@ use futures::sync::mpsc;
use futures::{Future, Stream, BoxFuture, Poll, Async};
use hyper::server::{Service, NewService, Request, Response, Http};
use hyper::{self, Get, Post, StatusCode};
-use mdns;
use num_bigint::BigUint;
use rand;
use std::collections::BTreeMap;
@@ -20,6 +19,12 @@ use url;
use authentication::Credentials;
use util;
+#[cfg(feature = "with-rust-mdns")]
+use mdns;
+
+#[cfg(feature = "with-avahi")]
+use dns_sd::DNSService;
+
#[derive(Clone)]
struct Discovery(Arc<DiscoveryInner>);
struct DiscoveryInner {
@@ -202,7 +207,10 @@ impl NewService for Discovery {
pub struct DiscoveryStream {
credentials: mpsc::UnboundedReceiver<Credentials>,
+ #[cfg(feature = "with-rust-mdns")]
_svc: mdns::Service,
+ #[cfg(feature = "with-avahi")]
+ _svc: DNSService,
task: Box<Future<Item=(), Error=io::Error>>,
}
@@ -212,8 +220,13 @@ pub fn discovery(handle: &Handle, device_name: String, device_id: String)
let (discovery, creds_rx) = Discovery::new(device_name.clone(), device_id);
let listener = TcpListener::bind(&"0.0.0.0:0".parse().unwrap(), handle)?;
+
+ #[cfg(feature = "with-rust-mdns")]
let addr = listener.local_addr()?;
+ #[cfg(feature = "with-avahi")]
+ let port = listener.local_addr().unwrap().port();
+
let http = Http::new();
let handle_ = handle.clone();
let task = Box::new(listener.incoming().for_each(move |(socket, addr)| {
@@ -221,13 +234,25 @@ pub fn discovery(handle: &Handle, device_name: String, device_id: String)
Ok(())
}));
+ #[cfg(feature = "with-rust-mdns")]
let responder = mdns::Responder::spawn(&handle)?;
+
+ #[cfg(feature = "with-rust-mdns")]
let svc = responder.register(
"_spotify-connect._tcp".to_owned(),
device_name,
addr.port(),
&["VERSION=1.0", "CPath=/"]);
+ #[cfg(feature = "with-avahi")]
+ let svc = DNSService::register(Some(&*device_name),
+ "_spotify-connect._tcp",
+ None,
+ None,
+ port,
+ &["VERSION=1.0", "CPath=/"])
+ .unwrap();
+
Ok(DiscoveryStream {
credentials: creds_rx,
_svc: svc,
diff --git a/src/lib.rs b/src/lib.rs
index 2a50249..b1b77ef 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -19,7 +19,6 @@ extern crate crypto;
extern crate getopts;
extern crate hyper;
extern crate linear_map;
-extern crate mdns;
extern crate num_bigint;
extern crate num_integer;
extern crate num_traits;
@@ -50,6 +49,11 @@ extern crate portaudio_rs;
#[cfg(feature = "libpulse-sys")]
extern crate libpulse_sys;
+#[cfg(feature = "with-rust-mdns")]
+extern crate mdns;
+
+#[cfg(feature = "with-avahi")]
+extern crate dns_sd;
#[macro_use] mod component;
pub mod album_cover;

View File

@ -0,0 +1,48 @@
diff -Naur librespot/src/audio_file.rs librespot.nocache/src/audio_file.rs
--- librespot/src/audio_file.rs 2017-06-14 00:14:21.000000000 +0200
+++ librespot.nocache/src/audio_file.rs 2017-06-20 00:35:14.060020000 +0200
@@ -3,7 +3,7 @@
use futures::Stream;
use futures::sync::{oneshot, mpsc};
use futures::{Poll, Async, Future};
-use futures::future::{self, FutureResult};
+use futures::future::FutureResult;
use std::cmp::min;
use std::fs;
use std::io::{self, Read, Write, Seek, SeekFrom};
@@ -129,15 +129,9 @@
impl AudioFileManager {
pub fn open(&self, file_id: FileId) -> AudioFileOpen {
- let cache = self.session().cache().cloned();
-
- if let Some(file) = cache.as_ref().and_then(|cache| cache.file(file_id)) {
- debug!("File {} already in cache", file_id);
- return AudioFileOpen::Cached(future::ok(file));
- }
-
debug!("Downloading file {}", file_id);
+ #[allow(unused_variables)]
let (complete_tx, complete_rx) = oneshot::channel();
let (headers, data) = request_chunk(&self.session(), file_id, 0).split();
@@ -151,18 +145,6 @@
complete_tx: Some(complete_tx),
};
- let session = self.session();
- self.session().spawn(move |_| {
- complete_rx.map(move |mut file| {
- if let Some(cache) = session.cache() {
- cache.save_file(file_id, &mut file);
- debug!("File {} complete, saving to cache", file_id);
- } else {
- debug!("File {} complete", file_id);
- }
- }).or_else(|oneshot::Canceled| Ok(()))
- });
-
AudioFileOpen::Streaming(open)
}
}

View File

@ -0,0 +1,99 @@
#!/bin/sh
################################################################################
# This file is part of LibreELEC - https://libreelec.tv
# Copyright (C) 2017-present Team LibreELEC
#
# LibreELEC is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# LibreELEC is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with LibreELEC. If not, see <http://www.gnu.org/licenses/>.
################################################################################
. /etc/os-release
. /etc/profile
oe_setup_addon service.librespot
activate_card() {
if [ -e "/proc/asound/$1" ]; then
return
fi
case "$LIBREELEC_ARCH" in
RPi*.arm)
if [ "$1" = "ALSA" ]; then
dtparam audio=on
sleep 1
fi
;;
*)
echo "Unable to activate card $1 on $LIBREELEC_ARCH"
exit
;;
esac
}
if [ ! "$(cat /proc/asound/pcm 2> /dev/null)" ]; then
case "$LIBREELEC_ARCH" in
RPi*.arm)
activate_card "ALSA"
;;
*)
echo "Unable to activate an audio interface on $LIBREELEC_ARCH"
exit
;;
esac
fi
case "$ls_o" in
*:CARD=*)
card="${ls_o##*:CARD=}"
card="${card%%,*}"
activate_card "$card"
index="$(readlink /proc/asound/$card)"
index="${index##*card}"
;;
hw:*,*)
echo "The hw:d,s specification is unreliable, use device:CARD=card instead"
index="${ls_o##hw:}"
index="${index%%,*}"
card="card$index"
activate_card "$card"
;;
*)
if [ -n "$ls_o" ]; then
echo "Unknown playback device specification $ls_o"
fi
;;
esac
if [ -n "$ls_b" -a "$ls_b" != "-" ]; then
bitrate="--bitrate $ls_b"
fi
if [ -n "$ls_o" ]; then
device="--device $ls_o"
fi
if [ -n "$ls_p" -a -n "$ls_u" ]; then
discovery="--disable-discovery --password $ls_p --username $ls_u"
fi
case "$LIBREELEC_ARCH" in
RPi*.arm)
[ "$(readlink /proc/asound/ALSA)" == "card$index" ] && [ "$pcm_3" ] &&
amixer -c "$index" cset name="PCM Playback Route" "$pcm_3"
;;
esac
librespot $bitrate \
--cache "$ADDON_HOME/cache" \
$device \
$discovery \
--name "Librespot@$HOSTNAME"

View File

@ -0,0 +1,35 @@
################################################################################
# This file is part of LibreELEC - https://libreelec.tv
# Copyright (C) 2017-present Team LibreELEC
#
# LibreELEC is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# LibreELEC is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with LibreELEC. If not, see <http://www.gnu.org/licenses/>.
################################################################################
import subprocess
import xbmc
import xbmcaddon
class Monitor(xbmc.Monitor):
def __init__(self, *args, **kwargs):
xbmc.Monitor.__init__(self)
self.id = xbmcaddon.Addon().getAddonInfo('id')
def onSettingsChanged(self):
subprocess.call(['systemctl', 'restart', self.id])
if __name__ == '__main__':
Monitor().waitForAbort()

View File

@ -0,0 +1,72 @@
# Kodi Media Center language file
# Addon Name: librespot
msgid ""
msgstr ""
msgctxt "#30100"
msgid "Configuration"
msgstr ""
msgctxt "#30101"
msgid "ALSA"
msgstr ""
msgctxt "#30102"
msgid "Configuration wizard"
msgstr ""
msgctxt "#30103"
msgid "Playback device"
msgstr ""
msgctxt "#30104"
msgid "Playback route"
msgstr ""
msgctxt "#30105"
msgid "auto detect"
msgstr ""
msgctxt "#30106"
msgid "headphone jack"
msgstr ""
msgctxt "#30107"
msgid "HDMI"
msgstr ""
msgctxt "#30108"
msgid "Spotify"
msgstr ""
msgctxt "#30109"
msgid "Username"
msgstr ""
msgctxt "#30110"
msgid "Password"
msgstr ""
msgctxt "#30111"
msgid "Discovery mode (set username and password to disable)"
msgstr ""
msgctxt "#30112"
msgid "Bit rate"
msgstr ""
msgctxt "#30113"
msgid "-"
msgstr ""
msgctxt "#30114"
msgid "90"
msgstr ""
msgctxt "#30115"
msgid "160"
msgstr ""
msgctxt "#30116"
msgid "320"
msgstr ""

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<settings>
<category label="30100" >
<setting label="30101" type="lsep" />
<setting label="30102" type="action" action="RunScript(/storage/.kodi/addons/service.librespot/wizard/wizard.py)" />
<setting label="30103" type="text" id="ls_o" default="" />
<setting label="30104" type="enum" id="pcm_3" lvalues="30105|30106|30107" visible="eq(-1,default:CARD=ALSA)|eq(-1,sysdefault:CARD=ALSA)" />
<setting label="30108" type="lsep" />
<setting label="30109" type="text" id="ls_u" />
<setting label="30110" type="text" id="ls_p" option="hidden" visible="!eq(-1,)" />
<setting label="30111" type="bool" id="ls_d" default="true" enable="false" visible="eq(-1,)|eq(-2,)" />
<setting label="30112" type="labelenum" id="ls_b" lvalues="30113|30114|30115|30116" />
</category>
</settings>

View File

@ -0,0 +1,11 @@
[Unit]
Description=librespot
After=network-online.target
Requires=network-online.target
[Service]
ExecStart=/bin/sh /storage/.kodi/addons/service.librespot/bin/librespot.start
Restart=on-failure
[Install]
WantedBy=kodi.target

View File

@ -0,0 +1,39 @@
################################################################################
# This file is part of LibreELEC - https://libreelec.tv
# Copyright (C) 2017-present Team LibreELEC
#
# LibreELEC is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# LibreELEC is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with LibreELEC. If not, see <http://www.gnu.org/licenses/>.
################################################################################
import alsaaudio as alsa
import xbmcaddon
import xbmcgui
if __name__ == '__main__':
addon = xbmcaddon.Addon('service.librespot')
dialog = xbmcgui.Dialog()
strings = addon.getLocalizedString
while True:
pcms = alsa.pcms()[1:]
if len(pcms) == 0:
dialog.ok(strings(30211), strings(30212))
break
pcmx = dialog.select(strings(30113), pcms)
if pcmx == -1:
break
pcm = pcms[pcmx]
addon.setSetting('ls_o', pcm)
break

View File

@ -67,7 +67,7 @@ PKG_CONFIGURE_OPTS_TARGET="py_cv_mod_gtk_=yes \
--disable-manpages \
--disable-xmltoman \
--disable-tests \
--disable-compat-libdns_sd \
--enable-compat-libdns_sd \
--disable-compat-howl \
--with-xml=expat \
--with-avahi-user=avahi \
@ -101,6 +101,7 @@ post_makeinstall_target() {
rm -f $INSTALL/usr/bin/avahi-bookmarks
rm -f $INSTALL/usr/bin/avahi-publish*
rm -f $INSTALL/usr/bin/avahi-resolve*
rm -f $INSTALL/usr/lib/libdns_sd*
mkdir -p $INSTALL/usr/share/services
cp -P $PKG_DIR/default.d/*.conf $INSTALL/usr/share/services