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/project/cmake/kodi-config.cmake.in b/project/cmake/kodi-config.cmake.in index 0e3b1580ad2b3..118d723cab437 100644 --- a/project/cmake/kodi-config.cmake.in +++ b/project/cmake/kodi-config.cmake.in @@ -6,6 +6,6 @@ IF(NOT WIN32) SET(CMAKE_CXX_FLAGS "$ENV{CXXFLAGS} @CXX11_SWITCH@") ENDIF() LIST(APPEND CMAKE_MODULE_PATH @prefix@/lib/kodi) -ADD_DEFINITIONS(@ARCH_DEFINES@) +ADD_DEFINITIONS(@ARCH_DEFINES@ -DBUILD_KODI_ADDON) include(addon-helpers) diff --git a/xbmc/FileItem.cpp b/xbmc/FileItem.cpp index a24ee4a5fd1b2..b8986d72302b9 100644 --- a/xbmc/FileItem.cpp +++ b/xbmc/FileItem.cpp @@ -782,7 +782,7 @@ bool CFileItem::IsAudio() const return true; } - return URIUtils::HasExtension(m_strPath, g_advancedSettings.m_musicExtensions); + return URIUtils::HasExtension(m_strPath, g_advancedSettings.GetMusicExtensions()); } bool CFileItem::IsKaraoke() const @@ -2236,7 +2236,7 @@ void CFileItemList::FilterCueItems() } else { // try replacing the extension with one of our allowed ones. - vector extensions = StringUtils::Split(g_advancedSettings.m_musicExtensions, "|"); + vector extensions = StringUtils::Split(g_advancedSettings.GetMusicExtensions(), "|"); for (vector::const_iterator i = extensions.begin(); i != extensions.end(); ++i) { strMediaFile = URIUtils::ReplaceExtension(pItem->GetPath(), *i); 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/AddonDll.h b/xbmc/addons/AddonDll.h index d5e4e9e08a74a..210157b5bdd44 100644 --- a/xbmc/addons/AddonDll.h +++ b/xbmc/addons/AddonDll.h @@ -158,17 +158,19 @@ AddonPtr CAddonDll::Clone() const template bool CAddonDll::LoadDll() { + if (m_pDll) + return true; + std::string strFileName; if (!m_bIsChild) { strFileName = LibPath(); } else - { //FIXME hack to load same Dll twice + { std::string extension = URIUtils::GetExtension(m_strLibName); - strFileName = "special://temp/" + m_strLibName; - URIUtils::RemoveExtension(strFileName); - strFileName += "-" + ID() + extension; + strFileName = "special://temp/" + ID() + "-%03d" + extension; + strFileName = CUtil::GetNextFilename(strFileName, 100); if (!XFILE::CFile::Exists(strFileName)) XFILE::CFile::Copy(LibPath(), strFileName); @@ -331,6 +333,8 @@ void CAddonDll::Destroy() m_pStruct = NULL; if (m_pDll) { + if (m_bIsChild) + XFILE::CFile::Delete(m_pDll->GetFile()); delete m_pDll; m_pDll = NULL; CLog::Log(LOGINFO, "ADDON: Dll Destroyed - %s", Name().c_str()); diff --git a/xbmc/addons/AddonManager.cpp b/xbmc/addons/AddonManager.cpp index 9ab5c31c24433..a94c30179b401 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)); } @@ -753,6 +757,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/GUIDialogAddonSettings.cpp b/xbmc/addons/GUIDialogAddonSettings.cpp index ef1c3c2654d57..2f2ba13e99ce4 100644 --- a/xbmc/addons/GUIDialogAddonSettings.cpp +++ b/xbmc/addons/GUIDialogAddonSettings.cpp @@ -393,7 +393,7 @@ bool CGUIDialogAddonSettings::ShowVirtualKeyboard(int iControl) { strMask = setting->Attribute("mask"); // convert mask qualifiers - StringUtils::Replace(strMask, "$AUDIO", g_advancedSettings.m_musicExtensions); + StringUtils::Replace(strMask, "$AUDIO", g_advancedSettings.GetMusicExtensions()); StringUtils::Replace(strMask, "$VIDEO", g_advancedSettings.m_videoExtensions); StringUtils::Replace(strMask, "$IMAGE", g_advancedSettings.m_pictureExtensions); #if defined(_WIN32_WINNT) @@ -407,7 +407,7 @@ bool CGUIDialogAddonSettings::ShowVirtualKeyboard(int iControl) if (type == "video") strMask = g_advancedSettings.m_videoExtensions; else if (type == "audio") - strMask = g_advancedSettings.m_musicExtensions; + strMask = g_advancedSettings.GetMusicExtensions(); else if (type == "executable") #if defined(_WIN32_WINNT) strMask = ".exe|.bat|.cmd|.py"; 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/filesystem/RSSDirectory.cpp b/xbmc/filesystem/RSSDirectory.cpp index 3c0b16574bbae..c238e2a2af066 100644 --- a/xbmc/filesystem/RSSDirectory.cpp +++ b/xbmc/filesystem/RSSDirectory.cpp @@ -91,7 +91,7 @@ static bool IsPathToMedia(const std::string& strPath ) { return URIUtils::HasExtension(strPath, g_advancedSettings.m_videoExtensions + '|' + - g_advancedSettings.m_musicExtensions + '|' + + g_advancedSettings.GetMusicExtensions() + '|' + g_advancedSettings.m_pictureExtensions); } diff --git a/xbmc/interfaces/Builtins.cpp b/xbmc/interfaces/Builtins.cpp index 82705d4898925..b97541e0c5fa4 100644 --- a/xbmc/interfaces/Builtins.cpp +++ b/xbmc/interfaces/Builtins.cpp @@ -749,7 +749,7 @@ int CBuiltins::Execute(const std::string& execString) if (item.m_bIsFolder) { CFileItemList items; - std::string extensions = g_advancedSettings.m_videoExtensions + "|" + g_advancedSettings.m_musicExtensions; + std::string extensions = g_advancedSettings.m_videoExtensions + "|" + g_advancedSettings.GetMusicExtensions(); CDirectory::GetDirectory(item.GetPath(),items,extensions); bool containsMusic = false, containsVideo = false; diff --git a/xbmc/interfaces/json-rpc/FileOperations.cpp b/xbmc/interfaces/json-rpc/FileOperations.cpp index 6ba9d6e4c8699..9987b4279ac4b 100644 --- a/xbmc/interfaces/json-rpc/FileOperations.cpp +++ b/xbmc/interfaces/json-rpc/FileOperations.cpp @@ -93,7 +93,7 @@ JSONRPC_STATUS CFileOperations::GetDirectory(const std::string &method, ITranspo else if (media == "music") { regexps = g_advancedSettings.m_audioExcludeFromListingRegExps; - extensions = g_advancedSettings.m_musicExtensions; + extensions = g_advancedSettings.GetMusicExtensions(); } else if (media == "pictures") { @@ -310,7 +310,7 @@ bool CFileOperations::FillFileItemList(const CVariant ¶meterObject, CFileIte else if (media == "music") { regexps = g_advancedSettings.m_audioExcludeFromListingRegExps; - extensions = g_advancedSettings.m_musicExtensions; + extensions = g_advancedSettings.GetMusicExtensions(); } else if (media == "pictures") { diff --git a/xbmc/interfaces/legacy/ModuleXbmc.cpp b/xbmc/interfaces/legacy/ModuleXbmc.cpp index dfdca99b4d9c1..56691aa1df5cf 100644 --- a/xbmc/interfaces/legacy/ModuleXbmc.cpp +++ b/xbmc/interfaces/legacy/ModuleXbmc.cpp @@ -453,7 +453,7 @@ namespace XBMCAddon if (strcmpi(mediaType, "video") == 0) result = g_advancedSettings.m_videoExtensions; else if (strcmpi(mediaType, "music") == 0) - result = g_advancedSettings.m_musicExtensions; + result = g_advancedSettings.GetMusicExtensions(); else if (strcmpi(mediaType, "picture") == 0) result = g_advancedSettings.m_pictureExtensions; diff --git a/xbmc/music/GUIViewStateMusic.cpp b/xbmc/music/GUIViewStateMusic.cpp index 4d25e496e17b4..aaf1bedee7b5a 100644 --- a/xbmc/music/GUIViewStateMusic.cpp +++ b/xbmc/music/GUIViewStateMusic.cpp @@ -57,7 +57,7 @@ std::string CGUIViewStateWindowMusic::GetLockType() std::string CGUIViewStateWindowMusic::GetExtensions() { - return g_advancedSettings.m_musicExtensions; + return g_advancedSettings.GetMusicExtensions(); } VECSOURCES& CGUIViewStateWindowMusic::GetSources() diff --git a/xbmc/music/infoscanner/MusicInfoScanner.cpp b/xbmc/music/infoscanner/MusicInfoScanner.cpp index 8f2a8913128df..b7d5d8f61e179 100644 --- a/xbmc/music/infoscanner/MusicInfoScanner.cpp +++ b/xbmc/music/infoscanner/MusicInfoScanner.cpp @@ -444,7 +444,7 @@ bool CMusicInfoScanner::DoScan(const std::string& strDirectory) // load subfolder CFileItemList items; - CDirectory::GetDirectory(strDirectory, items, g_advancedSettings.m_musicExtensions + "|.jpg|.tbn|.lrc|.cdg"); + CDirectory::GetDirectory(strDirectory, items, g_advancedSettings.GetMusicExtensions() + "|.jpg|.tbn|.lrc|.cdg"); // sort and get the path hash. Note that we don't filter .cue sheet items here as we want // to detect changes in the .cue sheet as well. The .cue sheet items only need filtering @@ -1487,7 +1487,7 @@ int CMusicInfoScanner::CountFilesRecursively(const std::string& strPath) { // load subfolder CFileItemList items; - CDirectory::GetDirectory(strPath, items, g_advancedSettings.m_musicExtensions, DIR_FLAG_NO_FILE_DIRS); + CDirectory::GetDirectory(strPath, items, g_advancedSettings.GetMusicExtensions(), DIR_FLAG_NO_FILE_DIRS); if (m_bStop) return 0; 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(); diff --git a/xbmc/network/upnp/UPnPServer.cpp b/xbmc/network/upnp/UPnPServer.cpp index 364b31d1f44cb..73a5b91f3846a 100644 --- a/xbmc/network/upnp/UPnPServer.cpp +++ b/xbmc/network/upnp/UPnPServer.cpp @@ -677,7 +677,7 @@ CUPnPServer::OnBrowseDirectChildren(PLT_ActionReference& action, // request came from string supported = g_advancedSettings.m_pictureExtensions + "|" + g_advancedSettings.m_videoExtensions + "|" - + g_advancedSettings.m_musicExtensions + "|" + + g_advancedSettings.GetMusicExtensions() + "|" + g_advancedSettings.m_discStubExtensions; CDirectory::GetDirectory((const char*)parent_id, items, supported); DefaultSortItems(items); diff --git a/xbmc/settings/AdvancedSettings.cpp b/xbmc/settings/AdvancedSettings.cpp index a84d4961becf0..09a3fa1836cfe 100644 --- a/xbmc/settings/AdvancedSettings.cpp +++ b/xbmc/settings/AdvancedSettings.cpp @@ -39,6 +39,7 @@ #include "filesystem/SpecialProtocol.h" #include "addons/IAddon.h" #include "addons/AddonManager.h" +#include "addons/AudioDecoder.h" #include "addons/GUIDialogAddonSettings.h" #include "CompileInfo.h" #if defined(TARGET_DARWIN_IOS) @@ -1408,3 +1409,19 @@ void CAdvancedSettings::setExtraLogLevel(const std::vector &components m_extraLogLevels |= static_cast(it->asInteger()); } } + +std::string CAdvancedSettings::GetMusicExtensions() const +{ + std::string result(m_musicExtensions); + + VECADDONS codecs; + CAddonMgr::Get().GetAddons(ADDON_AUDIODECODER, codecs); + for (size_t i=0;i dec(std::static_pointer_cast(codecs[i])); + result += '|'; + result += dec->GetExtensions(); + } + + return result; +} diff --git a/xbmc/settings/AdvancedSettings.h b/xbmc/settings/AdvancedSettings.h index de0a689ae5ece..b9d98b271f9a3 100644 --- a/xbmc/settings/AdvancedSettings.h +++ b/xbmc/settings/AdvancedSettings.h @@ -391,11 +391,13 @@ class CAdvancedSettings : public ISettingCallback, public ISettingsHandler float GetDisplayLatency(float refreshrate); bool m_initialized; + //! \brief Returns a list of music extension for filtering in the GUI + std::string GetMusicExtensions() const; + void SetDebugMode(bool debug); // runtime settings which cannot be set from advancedsettings.xml std::string m_pictureExtensions; - std::string m_musicExtensions; std::string m_videoExtensions; std::string m_discStubExtensions; std::string m_subtitlesExtensions; @@ -409,6 +411,7 @@ class CAdvancedSettings : public ISettingCallback, public ISettingsHandler std::string m_userAgent; private: + std::string m_musicExtensions; void setExtraLogLevel(const std::vector &components); }; diff --git a/xbmc/utils/URIUtils.cpp b/xbmc/utils/URIUtils.cpp index bb3f95ca15d4c..31f61234070bb 100644 --- a/xbmc/utils/URIUtils.cpp +++ b/xbmc/utils/URIUtils.cpp @@ -139,7 +139,7 @@ void URIUtils::RemoveExtension(std::string& strFileName) std::string strFileMask; strFileMask = g_advancedSettings.m_pictureExtensions; - strFileMask += "|" + g_advancedSettings.m_musicExtensions; + strFileMask += "|" + g_advancedSettings.GetMusicExtensions(); strFileMask += "|" + g_advancedSettings.m_videoExtensions; strFileMask += "|" + g_advancedSettings.m_subtitlesExtensions; #if defined(TARGET_DARWIN)