Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 13 Oct 2017 17:42:53 +0000 (UTC)
From:      Tobias Kortkamp <tobik@FreeBSD.org>
To:        ports-committers@freebsd.org, svn-ports-all@freebsd.org, svn-ports-head@freebsd.org
Subject:   svn commit: r452024 - in head/multimedia/kodi: . files
Message-ID:  <201710131742.v9DHgr3k020042@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: tobik
Date: Fri Oct 13 17:42:53 2017
New Revision: 452024
URL: https://svnweb.freebsd.org/changeset/ports/452024

Log:
  multimedia/kodi: Add sndio backend
  
  This is essentially a backport of [1] which was already merged and
  will hopefully be part of the next Kodi release.
  
  [1] https://github.com/xbmc/xbmc/pull/11962
  
  PR:		220231
  Approved by:	mickael.maillot@gmail.com (maintainer timeout, 3 months)

Added:
  head/multimedia/kodi/files/extra-patch-sndio   (contents, props changed)
Modified:
  head/multimedia/kodi/Makefile

Modified: head/multimedia/kodi/Makefile
==============================================================================
--- head/multimedia/kodi/Makefile	Fri Oct 13 17:25:50 2017	(r452023)
+++ head/multimedia/kodi/Makefile	Fri Oct 13 17:42:53 2017	(r452024)
@@ -94,7 +94,7 @@ PLIST_SUB=	ARCH=${KODI_ARCH_${ARCH}}
 OPTIONS_SUB=	yes
 OPTIONS_DEFINE=	AIRPLAY AIRTUNES AVAHI CEC DOCS \
 		LIBBLURAY LIRC MYSQL NFS NONFREE PULSEAUDIO RTMP \
-		SFTP SMB VAAPI VDPAU WEBSERVER
+		SFTP SNDIO SMB VAAPI VDPAU WEBSERVER
 OPTIONS_SINGLE=		RPI
 OPTIONS_SINGLE_RPI=	RPI1 RPI2
 
@@ -152,6 +152,10 @@ RPI2_CONFIGURE_ON=	--with-platform=raspberry-pi2
 
 RTMP_LIB_DEPENDS=	librtmp.so:multimedia/librtmp
 RTMP_CONFIGURE_ENABLE=	rtmp
+
+SNDIO_LIB_DEPENDS=	libsndio.so:audio/sndio
+SNDIO_CONFIGURE_ENABLE=	sndio
+SNDIO_EXTRA_PATCHES=	${PATCHDIR}/extra-patch-sndio
 
 SMB_USES=		samba:lib
 SMB_CONFIGURE_ENABLE=	samba

Added: head/multimedia/kodi/files/extra-patch-sndio
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/multimedia/kodi/files/extra-patch-sndio	Fri Oct 13 17:42:53 2017	(r452024)
@@ -0,0 +1,542 @@
+diff --git configure.ac configure.ac
+index 47eb1d9e33..c61564bb0e 100644
+--- configure.ac
++++ configure.ac
+@@ -315,6 +315,12 @@ AC_ARG_ENABLE([pulse],
+   [use_pulse=$enableval],
+   [use_pulse=auto])
+ 
++AC_ARG_ENABLE([sndio],
++  [AS_HELP_STRING([--enable-sndio],
++  [enable sndio support (default is auto)])],
++  [use_sndio=$enableval],
++  [use_sndio=auto])
++
+ AC_ARG_ENABLE([ssh],
+   [AS_HELP_STRING([--disable-ssh],
+   [disable SSH SFTP support (default is enabled)])],
+@@ -1210,6 +1216,22 @@ else
+   USE_PULSE=0
+ fi
+ 
++# sndio
++if test "x$use_sndio" != "xno"; then
++   USE_SNDIO=0
++   AC_CHECK_HEADER(sndio.h, HAVE_SNDIO="yes", HAVE_SNDIO="no")
++   if test "x$HAVE_SNDIO" = "xyes"; then
++       AC_CHECK_LIB(sndio, sio_open, HAVE_SNDIO="yes", HAVE_SNDIO="no", [])
++       if test "x$HAVE_SNDIO" = "xyes"; then
++            LIBS="$LIBS -lsndio"
++            USE_SNDIO=1
++            AC_DEFINE([HAVE_SNDIO],[1],[sndio enabled])
++       fi
++   fi
++else
++   USE_SNDIO=0
++fi
++
+ # avahi
+ if test "$use_avahi" = "yes"; then
+   AC_CHECK_LIB([avahi-common], [main],,
+@@ -1924,6 +1946,12 @@ else
+   final_message="$final_message\n  PulseAudio:\tNo"
+ fi
+ 
++if test "$use_sndio" = "yes"; then
++  final_message="$final_message\n  Sndio Support:\tYes"
++else
++  final_message="$final_message\n  Sndio Support:\tNo"
++fi
++
+ # Google Test Framework
+ if test "$configure_gtest" = "yes"; then
+   AC_MSG_NOTICE($gtest_enabled)
+@@ -2247,6 +2275,8 @@ AC_SUBST(USE_AIRPLAY)
+ AC_SUBST(USE_OPENMAX)
+ AC_SUBST(USE_PULSE)
+ AC_SUBST(HAVE_LIBPULSE)
++AC_SUBST(USE_SNDIO)
++AC_SUBST(HAVE_SNDIO)
+ AC_SUBST(USE_ALSA)
+ AC_SUBST(USE_TEXTUREPACKER)
+ AC_SUBST(TEXTUREPACKER)
+diff --git xbmc/cores/AudioEngine/AESinkFactory.cpp xbmc/cores/AudioEngine/AESinkFactory.cpp
+index d7b05cdbfe..617b5dba83 100644
+--- xbmc/cores/AudioEngine/AESinkFactory.cpp
++++ xbmc/cores/AudioEngine/AESinkFactory.cpp
+@@ -36,6 +36,9 @@
+   #if defined(HAS_ALSA)
+     #include "Sinks/AESinkALSA.h"
+   #endif
++  #if defined(HAS_SNDIO)
++    #include "Sinks/AESinkSNDIO.h"
++  #endif
+   #if defined(TARGET_FREEBSD)
+     #include "Sinks/AESinkOSS.h"
+   #endif
+@@ -77,6 +80,9 @@
+   #if defined(HAS_ALSA)
+         driver == "ALSA"        ||
+   #endif
++  #if defined(HAS_SNDIO)
++        driver == "SNDIO"       ||
++  #endif
+   #if defined(TARGET_FREEBSD)
+         driver == "OSS"         ||
+   #endif
+@@ -116,11 +122,15 @@ IAESink *CAESinkFactory::TrySink(std::string &driver, std::string &device, AEAud
+     sink = new CAESinkDARWINIOS();
+ #elif defined(TARGET_DARWIN_OSX)
+     sink = new CAESinkDARWINOSX();
+-#elif defined(TARGET_LINUX) || defined(TARGET_FREEBSD)
++#elif defined(TARGET_LINUX) || defined(TARGET_FREEBSD) || defined(TARGET_OPENBSD)
+  #if defined(HAS_PULSEAUDIO)
+     if (driver == "PULSE")
+       sink = new CAESinkPULSE();
+  #endif
++ #if defined(HAS_SNDIO)
++    if (driver == "SNDIO")
++        sink = new CAESinkSNDIO();
++ #endif
+  #if defined(HAS_ALSA)
+     if (driver == "ALSA")
+       sink = new CAESinkALSA();
+@@ -236,6 +246,10 @@ void CAESinkFactory::EnumerateEx(AESinkInfoList &list, bool force)
+     if (envSink == "PULSE")
+       CAESinkPULSE::EnumerateDevicesEx(info.m_deviceInfoList, force);
+     #endif
++    #if defined(HAS_SNDIO)
++    if (envSink == "SNDIO")
++        CAESinkSNDIO::EnumerateDevicesEx(info.m_deviceInfoList, force);
++    #endif
+     #if defined(HAS_ALSA)
+     if (envSink == "ALSA")
+       CAESinkALSA::EnumerateDevicesEx(info.m_deviceInfoList, force);
+@@ -264,6 +278,17 @@ void CAESinkFactory::EnumerateEx(AESinkInfoList &list, bool force)
+   }
+   #endif
+ 
++  #if defined(HAS_SNDIO)
++  info.m_deviceInfoList.clear();
++  info.m_sinkName = "SNDIO";
++  CAESinkSNDIO::EnumerateDevicesEx(info.m_deviceInfoList, force);
++  if(!info.m_deviceInfoList.empty())
++  {
++      list.push_back(info);
++      return;
++  }
++  #endif
++
+   #if defined(HAS_ALSA)
+   info.m_deviceInfoList.clear();
+   info.m_sinkName = "ALSA";
+diff --git xbmc/cores/AudioEngine/Makefile.in xbmc/cores/AudioEngine/Makefile.in
+index 7aab111f81..788786e2d1 100644
+--- xbmc/cores/AudioEngine/Makefile.in
++++ xbmc/cores/AudioEngine/Makefile.in
+@@ -55,6 +55,9 @@ SRCS += Sinks/AESinkOSS.cpp
+ ifeq (@USE_PULSE@,1)
+ SRCS += Sinks/AESinkPULSE.cpp
+ endif
++ifeq (@USE_SNDIO@,1)
++SRCS += Sinks/AESinkSNDIO.cpp
++endif
+ endif
+ 
+ SRCS += DSPAddons/ActiveAEDSP.cpp
+diff --git xbmc/cores/AudioEngine/Sinks/AESinkSNDIO.cpp xbmc/cores/AudioEngine/Sinks/AESinkSNDIO.cpp
+new file mode 100644
+index 0000000000..879b9a90a3
+--- /dev/null
++++ xbmc/cores/AudioEngine/Sinks/AESinkSNDIO.cpp
+@@ -0,0 +1,313 @@
++/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*- */
++/*
++ *      Copyright (C) 2010-2013 Team XBMC
++ *      http://xbmc.org
++ *
++ *  This Program 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, or (at your option)
++ *  any later version.
++ *
++ *  This Program 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 XBMC; see the file COPYING.  If not, see
++ *  <http://www.gnu.org/licenses/>.
++ *
++ */
++
++#include "system.h"
++#ifdef HAS_SNDIO
++#include "AESinkSNDIO.h"
++#include "cores/AudioEngine/Utils/AEUtil.h"
++#include "utils/log.h"
++
++#include <sys/param.h>
++
++#ifndef nitems
++#define nitems(x) (sizeof((x))/sizeof((x)[0]))
++#endif
++
++static enum AEChannel channelMap[] =
++{
++  AE_CH_FL,
++  AE_CH_FR,
++  AE_CH_BL,
++  AE_CH_BR,
++  AE_CH_FC,
++  AE_CH_LFE,
++  AE_CH_SL,
++  AE_CH_SR,
++};
++
++struct sndio_formats
++{
++  AEDataFormat fmt;
++  unsigned int bits;
++  unsigned int bps;
++  unsigned int sig;
++  unsigned int le;
++  unsigned int msb;
++};
++
++static struct sndio_formats formats[] =
++{
++  { AE_FMT_S32LE, 32, 4, 1, 1, 1 },
++  { AE_FMT_S32BE, 32, 4, 1, 0, 1 },
++
++  { AE_FMT_S24LE4, 24, 4, 1, 1, 0 },
++  { AE_FMT_S24BE4, 24, 4, 1, 0, 0 },
++  { AE_FMT_S24LE4, 24, 4, 1, 1, 1 },
++  { AE_FMT_S24BE4, 24, 4, 1, 0, 1 },
++
++  { AE_FMT_S24LE3, 24, 3, 1, 1, 0 },
++  { AE_FMT_S24BE3, 24, 3, 1, 0, 0 },
++  { AE_FMT_S24LE3, 24, 3, 1, 1, 1 },
++  { AE_FMT_S24BE3, 24, 3, 1, 0, 1 },
++
++  { AE_FMT_S16LE, 16, 2, 1, 1, 1 },
++  { AE_FMT_S16LE, 16, 2, 1, 1, 0 },
++  { AE_FMT_S16BE, 16, 2, 1, 0, 1 },
++  { AE_FMT_S16BE, 16, 2, 1, 0, 0 },
++
++  { AE_FMT_U8, 8, 1, 0, 0, 0 },
++  { AE_FMT_U8, 8, 1, 0, 0, 1 },
++  { AE_FMT_U8, 8, 1, 0, 1, 0 },
++  { AE_FMT_U8, 8, 1, 0, 1, 1 },
++};
++
++static AEDataFormat lookupDataFormat(int bits, int bps, int sig, int le, int msb)
++{
++  for (size_t i = 0; i < nitems(formats); i++)
++  {
++    if (bits == formats[i].bits &&
++        bps == formats[i].bps &&
++        sig == formats[i].sig &&
++        le == formats[i].le &&
++        msb == formats[i].msb)
++    {
++      return formats[i].fmt;
++    }
++  }
++  return AE_FMT_INVALID;
++}
++
++void CAESinkSNDIO::AudioFormatToPar(AEAudioFormat& format)
++{
++  sio_initpar(&par);
++
++  par.rate = format.m_sampleRate;
++  par.xrun = SIO_IGNORE;
++  par.pchan = format.m_channelLayout.Count();
++
++  for (size_t i = 0; i < nitems(formats); i++)
++  {
++    if (formats[i].fmt == format.m_dataFormat)
++    {
++      par.bits = formats[i].bits;
++      par.sig = formats[i].sig;
++      par.le = formats[i].le;
++      par.msb = formats[i].msb;
++      par.bps = formats[i].bps;
++      return;
++    }
++  }
++
++  /* Default to AE_FMT_S16LE */
++  par.bits = 16;
++  par.bps = SIO_BPS(16);
++  par.sig = 1;
++  par.le = 1;
++  par.msb = 0;
++}
++
++bool CAESinkSNDIO::ParToAudioFormat(AEAudioFormat& format)
++{
++  AEDataFormat dataFormat = lookupDataFormat(par.bits, par.bps, par.sig, par.le, par.msb);
++  if (dataFormat == AE_FMT_INVALID)
++  {
++    CLog::Log(LOGERROR, "CAESinkSNDIO::ParToAudioFormat - invalid data format");
++    return false;
++  }
++
++  if (par.pchan > nitems(channelMap))
++  {
++    CLog::Log(LOGERROR, "CAESinkSNDIO::ParToAudioFormat - too many channels: %d", par.pchan);
++    return false;
++  }
++
++  CAEChannelInfo info;
++  for (unsigned int i = 0; i < par.pchan; i++)
++      info += channelMap[i];
++  format.m_channelLayout = info;
++  format.m_dataFormat = dataFormat;
++  format.m_sampleRate = par.rate;
++  format.m_frameSize = par.bps * par.pchan;
++  format.m_frames = par.bufsz / format.m_frameSize;
++
++  return true;
++}
++
++CAESinkSNDIO::CAESinkSNDIO()
++{
++  m_hdl = nullptr;
++}
++
++CAESinkSNDIO::~CAESinkSNDIO()
++{
++  Deinitialize();
++}
++
++bool CAESinkSNDIO::Initialize(AEAudioFormat &format, std::string &device)
++{
++  if ((m_hdl = sio_open(SIO_DEVANY, SIO_PLAY, 0)) == nullptr)
++  {
++    CLog::Log(LOGERROR, "CAESinkSNDIO::Initialize - Failed to open device");
++    return false;
++  }
++
++  AudioFormatToPar(format);
++  if (!sio_setpar(m_hdl, &par) ||
++      !sio_getpar(m_hdl, &par) ||
++      !ParToAudioFormat(format))
++  {
++    CLog::Log(LOGERROR, "CAESinkSNDIO::Initialize - could not negotiate parameters");
++    return false;
++  }
++
++  played = written = 0;
++
++  sio_onmove(m_hdl, CAESinkSNDIO::OnmoveCb, this);
++
++  if (!sio_start(m_hdl))
++  {
++    CLog::Log(LOGERROR, "CAESinkSNDIO::Initialize - sio_start failed");
++    return false;
++  }
++
++  return true;
++}
++
++void CAESinkSNDIO::Deinitialize()
++{
++  if (m_hdl != nullptr)
++  {
++    sio_close(m_hdl);
++    m_hdl = nullptr;
++  }
++}
++
++void CAESinkSNDIO::Stop()
++{
++  if (!m_hdl)
++    return;
++
++  if (!sio_stop(m_hdl))
++    CLog::Log(LOGERROR, "CAESinkSNDIO::Stop - Failed");
++
++  written = played = 0;
++}
++
++void CAESinkSNDIO::OnmoveCb(void *arg, int delta) {
++  CAESinkSNDIO* self = static_cast<CAESinkSNDIO*>(arg);
++  self->played += delta;
++}
++
++void CAESinkSNDIO::GetDelay(AEDelayStatus& status)
++{
++  unsigned int frameSize = par.bps * par.pchan;
++  double delay = 1.0 * ((written / frameSize) - played) / par.rate;
++  status.SetDelay(delay);
++}
++
++unsigned int CAESinkSNDIO::AddPackets(uint8_t **data, unsigned int frames, unsigned int offset)
++{
++  if (!m_hdl)
++    return INT_MAX;
++
++  unsigned int frameSize = par.bps * par.pchan;
++  size_t size = frames * frameSize;
++  void *buffer = data[0] + offset * frameSize;
++  size_t wrote = sio_write(m_hdl, buffer, size);
++  written += wrote;
++  return wrote / frameSize;
++}
++
++void CAESinkSNDIO::Drain()
++{
++  if(!m_hdl)
++    return;
++
++  if (!sio_stop(m_hdl) || !sio_start(m_hdl))
++    CLog::Log(LOGERROR, "CAESinkSNDIO::Drain - failed");
++
++  written = played = 0;
++}
++
++void CAESinkSNDIO::EnumerateDevicesEx(AEDeviceInfoList &list, bool force)
++{
++  struct sio_hdl *hdl;
++  struct sio_cap cap;
++
++  if ((hdl = sio_open(SIO_DEVANY, SIO_PLAY, 0)) == nullptr)
++  {
++    CLog::Log(LOGERROR, "CAESinkSNDIO::EnumerateDevicesEx - sio_open");
++    return;
++  }
++
++  if (!sio_getcap(hdl, &cap))
++  {
++    CLog::Log(LOGERROR, "CAESinkSNDIO::EnumerateDevicesEx - sio_getcap");
++    return;
++  }
++
++  sio_close(hdl);
++  hdl = nullptr;
++
++  for (unsigned int i = 0; i < cap.nconf; i++)
++  {
++    CAEDeviceInfo info;
++    sio_cap::sio_conf conf = cap.confs[i];
++
++    info.m_deviceName = SIO_DEVANY;
++    info.m_displayName = "sndio";
++    info.m_displayNameExtra = "#" + std::to_string(i);
++    info.m_deviceType = AE_DEVTYPE_PCM;
++
++    unsigned int maxchan = 0;
++    for (unsigned int j = 0; j < SIO_NCHAN; j++)
++    {
++      if (conf.pchan & (1 << j))
++        maxchan = MAX(maxchan, cap.pchan[j]);
++    }
++
++    maxchan = MIN(maxchan, nitems(channelMap));
++    for (unsigned int j = 0; j < maxchan; j++)
++      info.m_channels += channelMap[j];
++
++    for (unsigned int j = 0; j < SIO_NRATE; j++)
++    {
++      if (conf.rate & (1 << j))
++      {
++        info.m_sampleRates.push_back(cap.rate[j]);
++      }
++    }
++
++    for (unsigned int j = 0; j < SIO_NENC; j++)
++    {
++      if (conf.enc & (1 << j))
++      {
++        AEDataFormat format = lookupDataFormat(cap.enc[j].bits, cap.enc[j].bps, cap.enc[j].sig, cap.enc[j].le, cap.enc[j].msb);
++        if (format != AE_FMT_INVALID)
++          info.m_dataFormats.push_back(format);
++      }
++    }
++
++    list.push_back(info);
++  }
++}
++
++#endif
+diff --git xbmc/cores/AudioEngine/Sinks/AESinkSNDIO.h xbmc/cores/AudioEngine/Sinks/AESinkSNDIO.h
+new file mode 100644
+index 0000000000..55719cd305
+--- /dev/null
++++ xbmc/cores/AudioEngine/Sinks/AESinkSNDIO.h
+@@ -0,0 +1,57 @@
++/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*- */
++#pragma once
++/*
++ *      Copyright (C) 2010-2013 Team XBMC
++ *      http://xbmc.org
++ *
++ *  This Program 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, or (at your option)
++ *  any later version.
++ *
++ *  This Program 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 XBMC; see the file COPYING.  If not, see
++ *  <http://www.gnu.org/licenses/>.
++ *
++ */
++
++#include "cores/AudioEngine/Interfaces/AESink.h"
++#include "cores/AudioEngine/Utils/AEDeviceInfo.h"
++#include <stdint.h>
++#include <sndio.h>
++
++#include "threads/CriticalSection.h"
++
++class CAESinkSNDIO : public IAESink
++{
++public:
++  virtual const char *GetName() { return "sndio"; }
++
++  CAESinkSNDIO();
++  virtual ~CAESinkSNDIO();
++
++  virtual bool Initialize(AEAudioFormat &format, std::string &device);
++  virtual void Deinitialize();
++
++  virtual void Stop();
++  virtual void GetDelay(AEDelayStatus& status);
++  virtual double GetCacheTotal() { return 0.0; }
++  virtual unsigned int AddPackets(uint8_t **data, unsigned int frames, unsigned int offset);
++  virtual void Drain();
++  static void EnumerateDevicesEx(AEDeviceInfoList &list, bool force = false);
++private:
++  void AudioFormatToPar(AEAudioFormat& format);
++  bool ParToAudioFormat(AEAudioFormat& format);
++  static void OnmoveCb(void *arg, int delta);
++
++  struct sio_hdl *m_hdl;
++  struct sio_par par;
++  ssize_t played;
++  ssize_t written;
++};
++
+diff --git xbmc/system.h xbmc/system.h
+index d426ade093..ed01ab53fd 100644
+--- xbmc/system.h
++++ xbmc/system.h
+@@ -172,6 +172,9 @@
+ #ifdef HAVE_LIBPULSE
+ #define HAS_PULSEAUDIO
+ #endif
++#ifdef HAVE_SNDIO
++#define HAS_SNDIO
++#endif
+ #ifdef HAVE_ALSA
+ #define HAS_ALSA
+ #endif



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201710131742.v9DHgr3k020042>