From b2db87122a2b4d59413629359009b93ec8d64d78 Mon Sep 17 00:00:00 2001 From: Arne Morten Kvarving Date: Tue, 13 May 2014 13:20:50 +0200 Subject: [PATCH] add support for audio decoder addons --- Kodi.xcodeproj/project.pbxproj | 10 ++ addons/kodi.audiodecoder/addon.xml | 7 + language/English/strings.po | 5 +- project/VS2010Express/XBMC.vcxproj | 1 + project/VS2010Express/XBMC.vcxproj.filters | 3 + xbmc/addons/Addon.cpp | 2 + xbmc/addons/AddonManager.cpp | 6 + xbmc/addons/AudioDecoder.cpp | 135 ++++++++++++++++++ xbmc/addons/AudioDecoder.h | 76 ++++++++++ xbmc/addons/IAddon.h | 1 + xbmc/addons/Makefile | 1 + xbmc/addons/addon-bindings.mk | 4 +- xbmc/addons/include/kodi_audiodec_dll.h | 60 ++++++++ xbmc/addons/include/kodi_audiodec_types.h | 101 +++++++++++++ xbmc/cores/paplayer/CodecFactory.cpp | 37 ++++- xbmc/filesystem/FileDirectoryFactory.cpp | 22 +++ xbmc/music/tags/MusicInfoTagLoaderFactory.cpp | 21 ++- 17 files changed, 484 insertions(+), 8 deletions(-) create mode 100644 addons/kodi.audiodecoder/addon.xml create mode 100644 xbmc/addons/AudioDecoder.cpp create mode 100644 xbmc/addons/AudioDecoder.h create mode 100644 xbmc/addons/include/kodi_audiodec_dll.h create mode 100644 xbmc/addons/include/kodi_audiodec_types.h diff --git a/Kodi.xcodeproj/project.pbxproj b/Kodi.xcodeproj/project.pbxproj index baf6cce74aea1..407a4ef9471f8 100644 --- a/Kodi.xcodeproj/project.pbxproj +++ b/Kodi.xcodeproj/project.pbxproj @@ -223,6 +223,9 @@ 395C2A1F1A9F96A700EBC7AD /* ContextItemAddon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 395C2A1D1A9F96A700EBC7AD /* ContextItemAddon.cpp */; }; 395C2A201A9F96A700EBC7AD /* ContextItemAddon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 395C2A1D1A9F96A700EBC7AD /* ContextItemAddon.cpp */; }; 395C2A211A9F96A700EBC7AD /* ContextItemAddon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 395C2A1D1A9F96A700EBC7AD /* ContextItemAddon.cpp */; }; + 395C2A241AA4C32100EBC7AD /* AudioDecoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 395C2A221AA4C32100EBC7AD /* AudioDecoder.cpp */; }; + 395C2A251AA4C32100EBC7AD /* AudioDecoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 395C2A221AA4C32100EBC7AD /* AudioDecoder.cpp */; }; + 395C2A261AA4C32100EBC7AD /* AudioDecoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 395C2A221AA4C32100EBC7AD /* AudioDecoder.cpp */; }; 395F6DDD1A8133360088CC74 /* GUIDialogSimpleMenu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 395F6DDB1A8133360088CC74 /* GUIDialogSimpleMenu.cpp */; }; 395F6DDE1A8133360088CC74 /* GUIDialogSimpleMenu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 395F6DDB1A8133360088CC74 /* GUIDialogSimpleMenu.cpp */; }; 395F6DDF1A8133360088CC74 /* GUIDialogSimpleMenu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 395F6DDB1A8133360088CC74 /* GUIDialogSimpleMenu.cpp */; }; @@ -3696,6 +3699,8 @@ 395C2A031A9CD25100EBC7AD /* ContextItemAddonInvoker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ContextItemAddonInvoker.h; path = python/ContextItemAddonInvoker.h; sourceTree = ""; }; 395C2A1D1A9F96A700EBC7AD /* ContextItemAddon.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ContextItemAddon.cpp; sourceTree = ""; }; 395C2A1E1A9F96A700EBC7AD /* ContextItemAddon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContextItemAddon.h; sourceTree = ""; }; + 395C2A221AA4C32100EBC7AD /* AudioDecoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AudioDecoder.cpp; sourceTree = ""; }; + 395C2A231AA4C32100EBC7AD /* AudioDecoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AudioDecoder.h; sourceTree = ""; }; 395F6DDB1A8133360088CC74 /* GUIDialogSimpleMenu.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GUIDialogSimpleMenu.cpp; sourceTree = ""; }; 395F6DDC1A8133360088CC74 /* GUIDialogSimpleMenu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GUIDialogSimpleMenu.h; sourceTree = ""; }; 395F6DE01A81FACF0088CC74 /* HTTPImageTransformationHandler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HTTPImageTransformationHandler.cpp; sourceTree = ""; }; @@ -6113,6 +6118,8 @@ F52BFFD9115D5574004B1D66 /* AddonStatusHandler.h */, 18B700DF13A6A5750009C1AF /* AddonVersion.cpp */, 18B700E013A6A5750009C1AF /* AddonVersion.h */, + 395C2A221AA4C32100EBC7AD /* AudioDecoder.cpp */, + 395C2A231AA4C32100EBC7AD /* AudioDecoder.h */, 7CF34D9D1930264A00D543C5 /* AudioEncoder.cpp */, 7CF34D9E1930264A00D543C5 /* AudioEncoder.h */, 395C2A1D1A9F96A700EBC7AD /* ContextItemAddon.cpp */, @@ -10838,6 +10845,7 @@ 7C779E3A104A57E500F444C4 /* RenderSystem.cpp in Sources */, 7C779E3B104A57E500F444C4 /* RenderSystemGL.cpp in Sources */, 7C779E3C104A57E500F444C4 /* WinEventsSDL.cpp in Sources */, + 395C2A241AA4C32100EBC7AD /* AudioDecoder.cpp in Sources */, 7C779E3D104A57E500F444C4 /* WinSystem.cpp in Sources */, 7C779E3E104A57E500F444C4 /* WinSystemOSX.mm in Sources */, 7C779E3F104A57E500F444C4 /* WinSystemOSXGL.mm in Sources */, @@ -11547,6 +11555,7 @@ DFF0F12817528350002DA3A4 /* Repository.cpp in Sources */, DFF0F12917528350002DA3A4 /* Scraper.cpp in Sources */, DFF0F12A17528350002DA3A4 /* ScreenSaver.cpp in Sources */, + 395C2A261AA4C32100EBC7AD /* AudioDecoder.cpp in Sources */, DFF0F12B17528350002DA3A4 /* Service.cpp in Sources */, DFF0F12C17528350002DA3A4 /* Skin.cpp in Sources */, DFF0F12D17528350002DA3A4 /* Visualisation.cpp in Sources */, @@ -12990,6 +12999,7 @@ E4991309174E5DAD00741B6D /* GUIRadioButtonControl.cpp in Sources */, E499130A174E5DAD00741B6D /* GUIRenderingControl.cpp in Sources */, E499130B174E5DAD00741B6D /* GUIResizeControl.cpp in Sources */, + 395C2A251AA4C32100EBC7AD /* AudioDecoder.cpp in Sources */, E499130C174E5DAD00741B6D /* GUIRSSControl.cpp in Sources */, E499130D174E5DAD00741B6D /* GUIScrollBarControl.cpp in Sources */, E499130E174E5DAD00741B6D /* GUISelectButtonControl.cpp in Sources */, diff --git a/addons/kodi.audiodecoder/addon.xml b/addons/kodi.audiodecoder/addon.xml new file mode 100644 index 0000000000000..b45104aec87df --- /dev/null +++ b/addons/kodi.audiodecoder/addon.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/language/English/strings.po b/language/English/strings.po index bc39872e6523e..b551666263689 100644 --- a/language/English/strings.po +++ b/language/English/strings.po @@ -828,7 +828,10 @@ msgctxt "#200" msgid "Audio encoders" msgstr "" -#empty string with id 201 +#: xbmc/filesystem/AddonsDirectory.cpp +msgctxt "#201" +msgid "Audio decoders" +msgstr "" #: xbmc/playlists/SmartPlaylist.cpp msgctxt "#202" diff --git a/project/VS2010Express/XBMC.vcxproj b/project/VS2010Express/XBMC.vcxproj index 2b435131f07cd..c22c9609f2f21 100644 --- a/project/VS2010Express/XBMC.vcxproj +++ b/project/VS2010Express/XBMC.vcxproj @@ -179,6 +179,7 @@ + diff --git a/project/VS2010Express/XBMC.vcxproj.filters b/project/VS2010Express/XBMC.vcxproj.filters index b335beb62eaeb..32c4c8fa08aed 100644 --- a/project/VS2010Express/XBMC.vcxproj.filters +++ b/project/VS2010Express/XBMC.vcxproj.filters @@ -3177,6 +3177,9 @@ network\httprequesthandler + + addons + diff --git a/xbmc/addons/Addon.cpp b/xbmc/addons/Addon.cpp index 2aa849f87b134..bd4ad7bf59dc2 100644 --- a/xbmc/addons/Addon.cpp +++ b/xbmc/addons/Addon.cpp @@ -90,6 +90,7 @@ static const TypeMapping types[] = {"xbmc.addon.image", ADDON_IMAGE, 1039, "DefaultAddonPicture.png" }, {"xbmc.addon.executable", ADDON_EXECUTABLE, 1043, "DefaultAddonProgram.png" }, {"xbmc.audioencoder", ADDON_AUDIOENCODER, 200, "DefaultAddonAudioEncoder.png" }, + {"kodi.audiodecoder", ADDON_AUDIODECODER, 201, "DefaultAddonAudioDecoder.png" }, {"xbmc.service", ADDON_SERVICE, 24018, "DefaultAddonService.png" }}; const std::string TranslateType(const ADDON::TYPE &type, bool pretty/*=false*/) @@ -397,6 +398,7 @@ void CAddon::BuildLibName(const cp_extension_t *extension) case ADDON_REPOSITORY: case ADDON_AUDIOENCODER: case ADDON_CONTEXT_ITEM: + case ADDON_AUDIODECODER: { std::string temp = CAddonMgr::Get().GetExtValue(extension->configuration, "@library"); m_strLibName = temp; diff --git a/xbmc/addons/AddonManager.cpp b/xbmc/addons/AddonManager.cpp index ba37daab43af9..11b19ca994f52 100644 --- a/xbmc/addons/AddonManager.cpp +++ b/xbmc/addons/AddonManager.cpp @@ -20,6 +20,7 @@ #include "AddonManager.h" #include "Addon.h" #include "AudioEncoder.h" +#include "AudioDecoder.h" #include "DllLibCPluff.h" #include "utils/StringUtils.h" #include "utils/JobManager.h" @@ -117,6 +118,7 @@ AddonPtr CAddonMgr::Factory(const cp_extension_t *props) case ADDON_SCREENSAVER: case ADDON_PVRDLL: case ADDON_AUDIOENCODER: + case ADDON_AUDIODECODER: { // begin temporary platform handling for Dlls // ideally platforms issues will be handled by C-Pluff // this is not an attempt at a solution @@ -163,6 +165,8 @@ AddonPtr CAddonMgr::Factory(const cp_extension_t *props) } else if (type == ADDON_AUDIOENCODER) return AddonPtr(new CAudioEncoder(props)); + else if (type == ADDON_AUDIODECODER) + return AddonPtr(new CAudioDecoder(props)); else return AddonPtr(new CScreenSaver(props)); } @@ -757,6 +761,8 @@ AddonPtr CAddonMgr::AddonFromProps(AddonProps& addonProps) return AddonPtr(new PVR::CPVRClient(addonProps)); case ADDON_AUDIOENCODER: return AddonPtr(new CAudioEncoder(addonProps)); + case ADDON_AUDIODECODER: + return AddonPtr(new CAudioDecoder(addonProps)); case ADDON_REPOSITORY: return AddonPtr(new CRepository(addonProps)); case ADDON_CONTEXT_ITEM: diff --git a/xbmc/addons/AudioDecoder.cpp b/xbmc/addons/AudioDecoder.cpp new file mode 100644 index 0000000000000..37f199350108b --- /dev/null +++ b/xbmc/addons/AudioDecoder.cpp @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2013 Arne Morten Kvarving + * + * 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 + * . + * + */ +#include "AudioDecoder.h" +#include "music/tags/MusicInfoTag.h" +#include "music/tags/TagLoaderTagLib.h" + +namespace ADDON +{ + +CAudioDecoder::CAudioDecoder(const cp_extension_t* ext) + : AudioDecoderDll(ext), + m_extension(CAddonMgr::Get().GetExtValue(ext->configuration, "@extension")), + m_mimetype(CAddonMgr::Get().GetExtValue(ext->configuration, "@mimetype")), + m_context(NULL), + m_tags(CAddonMgr::Get().GetExtValue(ext->configuration, "@tags") == "true"), + m_tracks(CAddonMgr::Get().GetExtValue(ext->configuration, "@tracks") == "true"), + m_channel(NULL) +{ + m_CodecName = CAddonMgr::Get().GetExtValue(ext->configuration, "@name"); + m_strExt = CAddonMgr::Get().GetExtValue(ext->configuration, "@name")+"stream"; +} + +AddonPtr CAudioDecoder::Clone() const +{ + // Copy constructor is generated by compiler and calls parent copy constructor + return AddonPtr(new CAudioDecoder(*this)); +} + +bool CAudioDecoder::Init(const std::string& strFile, unsigned int filecache) +{ + if (!Initialized()) + return false; + + // for replaygain + CTagLoaderTagLib tag; + tag.Load(strFile, XFILE::CMusicFileDirectory::m_tag, NULL); + + m_context = m_pStruct->Init(strFile.c_str(), filecache, + &m_Channels, &m_SampleRate, + &m_BitsPerSample, &m_TotalTime, + &m_Bitrate, &m_DataFormat, &m_channel); + + return (m_context != NULL); +} + +int CAudioDecoder::ReadPCM(uint8_t* buffer, int size, int* actualsize) +{ + if (!Initialized()) + return 0; + + return m_pStruct->ReadPCM(m_context, buffer, size, actualsize); +} + +int64_t CAudioDecoder::Seek(int64_t time) +{ + if (!Initialized()) + return 0; + + return m_pStruct->Seek(m_context, time); +} + +void CAudioDecoder::DeInit() +{ + if (!Initialized()) + return; + + m_pStruct->DeInit(m_context); +} + +bool CAudioDecoder::Load(const std::string& fileName, + MUSIC_INFO::CMusicInfoTag& tag, + MUSIC_INFO::EmbeddedArt* art) +{ + if (!Initialized()) + return false; + + char title[256]; + char artist[256]; + int length; + if (m_pStruct->ReadTag(fileName.c_str(), title, artist, &length)) + { + tag.SetTitle(title); + tag.SetArtist(artist); + tag.SetDuration(length); + return true; + } + + return false; +} + +int CAudioDecoder::GetTrackCount(const std::string& strPath) +{ + if (!Initialized()) + return 0; + + int result = m_pStruct->TrackCount(strPath.c_str()); + + if (result > 1 && !Load(strPath, XFILE::CMusicFileDirectory::m_tag, NULL)) + return 0; + + XFILE::CMusicFileDirectory::m_tag.SetLoaded(true); + return result; +} + +CAEChannelInfo CAudioDecoder::GetChannelInfo() +{ + if (m_channel) + return CAEChannelInfo(m_channel); + + return ICodec::GetChannelInfo(); +} + +void CAudioDecoder::Destroy() +{ + AudioDecoderDll::Destroy(); +} + +} /*namespace ADDON*/ + diff --git a/xbmc/addons/AudioDecoder.h b/xbmc/addons/AudioDecoder.h new file mode 100644 index 0000000000000..2d8bdea9812e1 --- /dev/null +++ b/xbmc/addons/AudioDecoder.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2013 Arne Morten Kvarving + * + * 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 + * . + * + */ +#pragma once + +#include "AddonDll.h" +#include "include/kodi_audiodec_types.h" +#include "cores/paplayer/ICodec.h" +#include "music/tags/ImusicInfoTagLoader.h" +#include "filesystem/MusicFileDirectory.h" + +namespace MUSIC_INFO +{ + class CMusicInfoTag; + class EmbeddedArt; +} + +typedef DllAddon DllAudioDecoder; +namespace ADDON +{ + typedef CAddonDll AudioDecoderDll; + + class CAudioDecoder : public AudioDecoderDll, + public ICodec, + public MUSIC_INFO::IMusicInfoTagLoader, + public XFILE::CMusicFileDirectory + { + public: + CAudioDecoder(const AddonProps &props) : AudioDecoderDll(props) {}; + CAudioDecoder(const cp_extension_t *ext); + virtual ~CAudioDecoder() {} + virtual AddonPtr Clone() const; + + // Things that MUST be supplied by the child classes + bool Init(const std::string& strFile, unsigned int filecache); + int ReadPCM(uint8_t* buffer, int size, int* actualsize); + int64_t Seek(int64_t time); + bool CanInit() { return true; } + void DeInit(); + void Destroy(); + bool Load(const std::string& strFileName, + MUSIC_INFO::CMusicInfoTag& tag, + MUSIC_INFO::EmbeddedArt *art = NULL); + int GetTrackCount(const std::string& strPath); + virtual CAEChannelInfo GetChannelInfo(); + + const std::string& GetExtensions() const { return m_extension; } + const std::string& GetMimetypes() const { return m_mimetype; } + bool HasTags() const { return m_tags; } + bool HasTracks() const { return m_tracks; } + protected: + std::string m_extension; + std::string m_mimetype; + void* m_context; + bool m_tags; + bool m_tracks; + const AEChannel* m_channel; + }; + +} /*namespace ADDON*/ diff --git a/xbmc/addons/IAddon.h b/xbmc/addons/IAddon.h index 76f22fa29ff80..8cbcd043ef518 100644 --- a/xbmc/addons/IAddon.h +++ b/xbmc/addons/IAddon.h @@ -51,6 +51,7 @@ namespace ADDON ADDON_SERVICE, ADDON_AUDIOENCODER, ADDON_CONTEXT_ITEM, + ADDON_AUDIODECODER, ADDON_VIDEO, // virtual addon types ADDON_AUDIO, ADDON_IMAGE, diff --git a/xbmc/addons/Makefile b/xbmc/addons/Makefile index 4cf5b17c4d154..e8eca6ad05049 100644 --- a/xbmc/addons/Makefile +++ b/xbmc/addons/Makefile @@ -11,6 +11,7 @@ SRCS=Addon.cpp \ AddonVersion.cpp \ AudioEncoder.cpp \ ContextItemAddon.cpp \ + AudioDecoder.cpp \ GUIDialogAddonInfo.cpp \ GUIDialogAddonSettings.cpp \ GUIViewStateAddonBrowser.cpp \ diff --git a/xbmc/addons/addon-bindings.mk b/xbmc/addons/addon-bindings.mk index 50d75bcadfc92..4a33cfd88e78b 100644 --- a/xbmc/addons/addon-bindings.mk +++ b/xbmc/addons/addon-bindings.mk @@ -3,6 +3,8 @@ BINDINGS+=xbmc/addons/include/xbmc_addon_dll.h BINDINGS+=xbmc/addons/include/xbmc_addon_types.h BINDINGS+=xbmc/addons/include/xbmc_audioenc_dll.h BINDINGS+=xbmc/addons/include/xbmc_audioenc_types.h +BINDINGS+=xbmc/addons/include/kodi_audiodec_dll.h +BINDINGS+=xbmc/addons/include/kodi_audiodec_types.h BINDINGS+=xbmc/addons/include/xbmc_codec_types.h BINDINGS+=xbmc/addons/include/xbmc_epg_types.h BINDINGS+=xbmc/addons/include/xbmc_pvr_dll.h @@ -17,4 +19,4 @@ BINDINGS+=addons/library.xbmc.gui/libXBMC_gui.h BINDINGS+=addons/library.xbmc.pvr/libXBMC_pvr.h BINDINGS+=addons/library.xbmc.codec/libXBMC_codec.h BINDINGS+=xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxPacket.h - +BINDINGS+=xbmc/cores/AudioEngine/Utils/AEChannelData.h diff --git a/xbmc/addons/include/kodi_audiodec_dll.h b/xbmc/addons/include/kodi_audiodec_dll.h new file mode 100644 index 0000000000000..78bc3cc835089 --- /dev/null +++ b/xbmc/addons/include/kodi_audiodec_dll.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2005-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 + * . + * + */ + +#pragma once + +#include +#include "xbmc_addon_dll.h" +#include "kodi_audiodec_types.h" + +extern "C" +{ + //! \copydoc AudioDecoder::Init + void* Init(const char* file, unsigned int filecache, int* channels, + int* samplerate, int* bitspersample, int64_t* totaltime, + int* bitrate, AEDataFormat* format, const AEChannel** channelinfo); + + //! \copydoc AudioDecoder::ReadPCM + int ReadPCM(void* context, uint8_t* buffer, int size, int* actualsize); + + //! \copydoc AudioDecoder::Seek + int64_t Seek(void* context, int64_t time); + + //! \copydoc AudioDecoder::ReadTag + bool ReadTag(const char* file, char* title, + char* artist, int* length); + + //! \copydoc AudioDecoder::TrackCount + int TrackCount(const char* file); + + //! \copydoc AudioDecoder::DeInit + bool DeInit(void* context); + + // function to export the above structure to XBMC + void __declspec(dllexport) get_addon(struct AudioDecoder* pScr) + { + pScr->Init = Init; + pScr->ReadPCM = ReadPCM; + pScr->Seek = Seek; + pScr->ReadTag = ReadTag; + pScr->TrackCount = TrackCount; + pScr->DeInit = DeInit; + }; +}; diff --git a/xbmc/addons/include/kodi_audiodec_types.h b/xbmc/addons/include/kodi_audiodec_types.h new file mode 100644 index 0000000000000..50c4cc49d2223 --- /dev/null +++ b/xbmc/addons/include/kodi_audiodec_types.h @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2005-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 + * . + * + */ + +#pragma once + +#include +#ifdef BUILD_KODI_ADDON +#include "kodi/AEChannelData.h" +#else +#include "cores/AudioEngine/Utils/AEChannelData.h" +#endif + +extern "C" +{ + struct AUDIODEC_INFO + { + int dummy; + }; + + struct AUDIODEC_PROPS + { + int dummy; + }; + + struct AudioDecoder + { + //! \brief Initialize a decoder + //! \param file The file to read + //! \param filecache The file cache size + //! \param channels Number of channels in output stream + //! \param samplerate Samplerate of output stream + //! \param bitspersample Bits per sample in output stream + //! \param totaltime Total time for stream + //! \param bitrate Average bitrate of input stream + //! \param format Data format for output stream + //! \param info Channel mapping for output stream + //! \return Context of output stream + //! \sa ICodec::Init + void* (__cdecl* Init) (const char* file, unsigned int filecache, + int* channels, int* samplerate, + int* bitspersample, int64_t* totaltime, + int* bitrate, AEDataFormat* format, + const AEChannel** info); + + //! \brief Produce some noise + //! \param context Context of output stream + //! \param buffer Output buffer + //! \param size Size of output buffer + //! \param actualsize Actual number of bytes written to output buffer + //! \return 0 on success, -1 on end of stream, 1 on failure + //! \sa ICodec::ReadPCM + int (__cdecl* ReadPCM) (void* context, uint8_t* buffer, int size, int* actualsize); + + + //! \brief Seek in output stream + //! \param context Context of output stream + //! \param time Time position to seek to in milliseconds + //! \return Time position seek ended up on + //! \sa ICodec::Seek + int64_t (__cdecl* Seek) (void* context, int64_t time); + + //! \brief Read tag of a file + //! \param file File to read tag for + //! \param title Title of file + //! \param artist Artist of file + //! \param length Length of file + //! \return True on success, false on failure + //! \sa IMusicInfoTagLoader::ReadTag + bool (__cdecl* ReadTag)(const char* file, char* title, + char* artist, int* length); + + //! \brief Get number of tracks in a file + //! \param file File to read tag for + //! \return Number of tracks in file + //! \sa CMusicFileDirectory + int (__cdecl* TrackCount) (const char* file); + + //! \brief Close down an output stream + //! \param context Context of stream + //! \return True on success, false on failure + //! \sa ICodec::DeInit + bool (__cdecl* DeInit)(void* context); + }; +} diff --git a/xbmc/cores/paplayer/CodecFactory.cpp b/xbmc/cores/paplayer/CodecFactory.cpp index 575d64b5b1138..28baa533d58e6 100644 --- a/xbmc/cores/paplayer/CodecFactory.cpp +++ b/xbmc/cores/paplayer/CodecFactory.cpp @@ -36,11 +36,27 @@ #include "URL.h" #include "DVDPlayerCodec.h" #include "utils/StringUtils.h" +#include "addons/AddonManager.h" +#include "addons/AudioDecoder.h" + +using namespace ADDON; ICodec* CodecFactory::CreateCodec(const std::string& strFileType) { std::string fileType = strFileType; StringUtils::ToLower(fileType); + VECADDONS codecs; + CAddonMgr::Get().GetAddons(ADDON_AUDIODECODER, codecs); + for (size_t i=0;i dec(std::static_pointer_cast(codecs[i])); + if (dec->GetExtensions().find("."+fileType) != std::string::npos) + { + CAudioDecoder* result = new CAudioDecoder(*dec); + static_cast(*result).Create(); + return result; + } + } if (fileType == "mp3" || fileType == "mp2") return new DVDPlayerCodec(); else if (fileType == "pcm" || fileType == "l16") @@ -121,9 +137,24 @@ ICodec* CodecFactory::CreateCodecDemux(const std::string& strFile, const std::st CURL urlFile(strFile); std::string content = strContent; StringUtils::ToLower(content); - if( content == "audio/mpeg" - || content == "audio/mpeg3" - || content == "audio/mp3" ) + if (!content.empty()) + { + VECADDONS codecs; + CAddonMgr::Get().GetAddons(ADDON_AUDIODECODER, codecs); + for (size_t i=0;i dec(std::static_pointer_cast(codecs[i])); + if (dec->GetMimetypes().find(content) != std::string::npos) + { + CAudioDecoder* result = new CAudioDecoder(*dec); + static_cast(*result).Create(); + return result; + } + } + } + if (content == "audio/mpeg" + || content == "audio/mpeg3" + || content == "audio/mp3") { DVDPlayerCodec *dvdcodec = new DVDPlayerCodec(); dvdcodec->SetContentType(content); diff --git a/xbmc/filesystem/FileDirectoryFactory.cpp b/xbmc/filesystem/FileDirectoryFactory.cpp index 2fd8777a779b0..bf70db05e6307 100644 --- a/xbmc/filesystem/FileDirectoryFactory.cpp +++ b/xbmc/filesystem/FileDirectoryFactory.cpp @@ -50,7 +50,10 @@ #include "FileItem.h" #include "utils/StringUtils.h" #include "URL.h" +#include "addons/AddonManager.h" +#include "addons/AudioDecoder.h" +using namespace ADDON; using namespace XFILE; using namespace PLAYLIST; using namespace std; @@ -67,6 +70,25 @@ IFileDirectory* CFileDirectoryFactory::Create(const CURL& url, CFileItem* pItem, if (url.IsProtocol("stack")) // disqualify stack as we need to work with each of the parts instead return NULL; + std::string strExtension=URIUtils::GetExtension(url); + StringUtils::ToLower(strExtension); + VECADDONS codecs; + CAddonMgr::Get().GetAddons(ADDON_AUDIODECODER, codecs); + for (size_t i=0;i dec(std::static_pointer_cast(codecs[i])); + if (!strExtension.empty() && dec->HasTracks() && + dec->GetExtensions().find(strExtension) != std::string::npos) + { + CAudioDecoder* result = new CAudioDecoder(*dec); + static_cast(*result).Create(); + if (result->ContainsFiles(url)) + return result; + delete result; + return NULL; + } + } + #ifdef HAS_FILESYSTEM if ((url.IsFileType("ogg") || url.IsFileType("oga")) && CFile::Exists(url)) { diff --git a/xbmc/music/tags/MusicInfoTagLoaderFactory.cpp b/xbmc/music/tags/MusicInfoTagLoaderFactory.cpp index 7d51837fc85f0..8e2aa750f384b 100644 --- a/xbmc/music/tags/MusicInfoTagLoaderFactory.cpp +++ b/xbmc/music/tags/MusicInfoTagLoaderFactory.cpp @@ -40,6 +40,10 @@ #include "cores/paplayer/ASAPCodec.h" #endif +#include "addons/AddonManager.h" +#include "addons/AudioDecoder.h" + +using namespace ADDON; using namespace MUSIC_INFO; CMusicInfoTagLoaderFactory::CMusicInfoTagLoaderFactory() @@ -65,6 +69,20 @@ IMusicInfoTagLoader* CMusicInfoTagLoaderFactory::CreateLoader(const std::string& if (strExtension.empty()) return NULL; + VECADDONS codecs; + CAddonMgr::Get().GetAddons(ADDON_AUDIODECODER, codecs); + for (size_t i=0;i dec(std::static_pointer_cast(codecs[i])); + if (dec->HasTags() && dec->GetExtensions().find("."+strExtension) != std::string::npos) + { + CAudioDecoder* result = new CAudioDecoder(*dec); + static_cast(*result).Create(); + return result; + } + } + + if (strExtension == "aac" || strExtension == "ape" || strExtension == "mac" || strExtension == "mp3" || @@ -75,11 +93,8 @@ IMusicInfoTagLoader* CMusicInfoTagLoaderFactory::CreateLoader(const std::string& strExtension == "ogg" || strExtension == "oga" || strExtension == "oggstream" || strExtension == "aif" || strExtension == "aiff" || strExtension == "wav" || -#ifdef HAS_MOD_PLAYER - ModPlayer::IsSupportedFormat(strExtension) || strExtension == "mod" || strExtension == "nsf" || strExtension == "nsfstream" || strExtension == "s3m" || strExtension == "it" || strExtension == "xm" || -#endif strExtension == "wv") { CTagLoaderTagLib *pTagLoader = new CTagLoaderTagLib();