aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--system/settings/rbp.xml80
-rw-r--r--xbmc/cores/AudioEngine/AEFactory.cpp11
-rw-r--r--xbmc/cores/AudioEngine/AESinkFactory.cpp10
-rw-r--r--xbmc/cores/AudioEngine/Engines/PiAudio/PiAudioAE.cpp206
-rw-r--r--xbmc/cores/AudioEngine/Engines/PiAudio/PiAudioAE.h80
-rw-r--r--xbmc/cores/AudioEngine/Makefile.in4
-rw-r--r--xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp293
-rw-r--r--xbmc/cores/AudioEngine/Sinks/AESinkPi.h65
-rw-r--r--xbmc/cores/dvdplayer/DVDSubtitles/DVDSubtitleStream.cpp88
-rw-r--r--xbmc/cores/omxplayer/OMXAudio.cpp85
-rw-r--r--xbmc/cores/omxplayer/OMXAudio.h12
-rw-r--r--xbmc/cores/omxplayer/OMXPlayer.cpp12
-rw-r--r--xbmc/cores/omxplayer/OMXPlayerAudio.cpp4
-rw-r--r--xbmc/cores/omxplayer/omxplayer_advancedsettings.xml4
-rw-r--r--xbmc/cores/playercorefactory/PlayerCoreConfig.h6
-rw-r--r--xbmc/linux/RBP.cpp4
-rw-r--r--xbmc/linux/RBP.h2
-rw-r--r--xbmc/utils/CharsetConverter.cpp10
-rw-r--r--xbmc/utils/CharsetConverter.h2
-rw-r--r--xbmc/utils/FileOperationJob.cpp7
-rw-r--r--xbmc/utils/URIUtils.cpp75
-rw-r--r--xbmc/utils/URIUtils.h10
-rw-r--r--xbmc/utils/test/TestURIUtils.cpp52
-rw-r--r--xbmc/visualizations/OpenGLSpectrum/opengl_spectrum.cpp188
24 files changed, 675 insertions, 635 deletions
diff --git a/system/settings/rbp.xml b/system/settings/rbp.xml
index cfdeea6fd4..3af681dfa4 100644
--- a/system/settings/rbp.xml
+++ b/system/settings/rbp.xml
@@ -38,91 +38,13 @@
</setting>
</group>
</category>
-
- <category id="audiooutput" label="772" help="36360">
+ <category id="audiooutput">
<group id="1">
- <setting id="audiooutput.audiodevice">
- <level>1</level>
- <default>HDMI</default>
- <constraints>
- <options>audiodevices</options>
- </constraints>
- <control type="list" format="string" />
- </setting>
<setting id="audiooutput.dualaudio" type="boolean" label="37017" help="36542">
<level>2</level>
<default>false</default>
- <dependencies>
- <dependency type="visible">
- <condition on="property" name="aesettingvisible" setting="audiooutput.audiodevice">audiooutput.passthrough</condition>
- </dependency>
- </dependencies>
- <control type="toggle" />
- </setting>
- <setting id="audiooutput.boostcentre" type="boolean" label="37018" help="36543">
- <level>2</level>
- <default>false</default>
<control type="toggle" />
</setting>
- <setting id="audiooutput.config">
- <visible>false</visible>
- </setting>
- <setting id="audiooutput.stereoupmix">
- <visible>false</visible>
- </setting>
- <setting id="audiooutput.streamsilence">
- <level>2</level>
- <default>0</default>
- <dependencies>
- <dependency type="visible">
- <condition on="property" name="aesettingvisible" setting="audiooutput.audiodevice">audiooutput.streamsilence</condition>
- </dependency>
- </dependencies>
- <constraints>
- <options>audiostreamsilence</options>
- </constraints>
- <control type="spinner" format="string" />
- </setting>
- </group>
- <group id="2">
- <visible>false</visible>
- </group>
- <group id="3">
- <setting id="audiooutput.passthrough">
- <level>2</level>
- <default>false</default>
- <dependencies>
- <dependency type="visible">
- <condition on="property" name="aesettingvisible" setting="audiooutput.audiodevice">audiooutput.passthrough</condition>
- </dependency>
- </dependencies>
- </setting>
- <setting id="audiooutput.passthroughdevice">
- <visible>false</visible>
- </setting>
- <setting id="audiooutput.truehdpassthrough">
- <visible>false</visible>
- </setting>
- <setting id="audiooutput.dtshdpassthrough">
- <visible>false</visible>
- </setting>
- <setting id="audiooutput.eac3passthrough">
- <visible>false</visible>
- </setting>
- <setting id="audiooutput.ac3passthrough">
- <dependencies>
- <dependency type="visible">
- <condition on="property" name="aesettingvisible" setting="audiooutput.audiodevice">audiooutput.ac3passthrough</condition>
- </dependency>
- </dependencies>
- </setting>
- <setting id="audiooutput.dtspassthrough">
- <dependencies>
- <dependency type="visible">
- <condition on="property" name="aesettingvisible" setting="audiooutput.audiodevice">audiooutput.dtspassthrough</condition>
- </dependency>
- </dependencies>
- </setting>
</group>
</category>
</section>
diff --git a/xbmc/cores/AudioEngine/AEFactory.cpp b/xbmc/cores/AudioEngine/AEFactory.cpp
index e798e0fae8..b76d30470e 100644
--- a/xbmc/cores/AudioEngine/AEFactory.cpp
+++ b/xbmc/cores/AudioEngine/AEFactory.cpp
@@ -33,10 +33,6 @@
#include "Engines/PulseAE/PulseAE.h"
#endif
-#if defined(TARGET_RASPBERRY_PI)
- #include "Engines/PiAudio/PiAudioAE.h"
-#endif
-
#include "guilib/LocalizeStrings.h"
#include "settings/lib/Setting.h"
#include "settings/Settings.h"
@@ -55,9 +51,7 @@ bool CAEFactory::LoadEngine()
{
bool loaded = false;
-#if defined(TARGET_RASPBERRY_PI)
- return CAEFactory::LoadEngine(AE_ENGINE_PIAUDIO);
-#elif defined(TARGET_DARWIN)
+#if defined(TARGET_DARWIN)
return CAEFactory::LoadEngine(AE_ENGINE_COREAUDIO);
#endif
@@ -104,9 +98,6 @@ bool CAEFactory::LoadEngine(enum AEEngine engine)
#if defined(HAS_PULSEAUDIO)
case AE_ENGINE_PULSE : AE = new CPulseAE(); break;
#endif
-#if defined(TARGET_RASPBERRY_PI)
- case AE_ENGINE_PIAUDIO : AE = new PiAudioAE::CPiAudioAE(); break;
-#endif
default:
return false;
}
diff --git a/xbmc/cores/AudioEngine/AESinkFactory.cpp b/xbmc/cores/AudioEngine/AESinkFactory.cpp
index e7fb9a3416..7dc504b515 100644
--- a/xbmc/cores/AudioEngine/AESinkFactory.cpp
+++ b/xbmc/cores/AudioEngine/AESinkFactory.cpp
@@ -25,6 +25,8 @@
#include "Sinks/AESinkDirectSound.h"
#elif defined(TARGET_ANDROID)
#include "Sinks/AESinkAUDIOTRACK.h"
+#elif defined(TARGET_RASPBERRY_PI)
+ #include "Sinks/AESinkPi.h"
#elif defined(TARGET_LINUX) || defined(TARGET_FREEBSD)
#if defined(HAS_ALSA)
#include "Sinks/AESinkALSA.h"
@@ -55,6 +57,8 @@ void CAESinkFactory::ParseDevice(std::string &device, std::string &driver)
driver == "DIRECTSOUND" ||
#elif defined(TARGET_ANDROID)
driver == "AUDIOTRACK" ||
+#elif defined(TARGET_RASPBERRY_PI)
+ driver == "Pi" ||
#elif defined(TARGET_LINUX) || defined(TARGET_FREEBSD)
#if defined(HAS_ALSA)
driver == "ALSA" ||
@@ -110,6 +114,10 @@ IAESink *CAESinkFactory::Create(std::string &device, AEAudioFormat &desiredForma
if (driver.empty() || driver == "AUDIOTRACK")
TRY_SINK(AUDIOTRACK)
+#elif defined(TARGET_RASPBERRY_PI)
+ if (driver.empty() || driver == "Pi")
+ TRY_SINK(Pi)
+
#elif defined(TARGET_LINUX) || defined(TARGET_FREEBSD)
#if defined(HAS_ALSA)
if (driver.empty() || driver == "ALSA")
@@ -143,6 +151,8 @@ void CAESinkFactory::EnumerateEx(AESinkInfoList &list, bool force)
ENUMERATE_SINK(WASAPI, force);
#elif defined(TARGET_ANDROID)
ENUMERATE_SINK(AUDIOTRACK, force);
+#elif defined(TARGET_RASPBERRY_PI)
+ ENUMERATE_SINK(Pi, force);
#elif defined(TARGET_LINUX) || defined(TARGET_FREEBSD)
#if defined(HAS_ALSA)
ENUMERATE_SINK(ALSA, force);
diff --git a/xbmc/cores/AudioEngine/Engines/PiAudio/PiAudioAE.cpp b/xbmc/cores/AudioEngine/Engines/PiAudio/PiAudioAE.cpp
deleted file mode 100644
index ccf40b0ea8..0000000000
--- a/xbmc/cores/AudioEngine/Engines/PiAudio/PiAudioAE.cpp
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * 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 "PiAudioAE.h"
-
-using namespace PiAudioAE;
-#include "Utils/AEUtil.h"
-
-#include "settings/Settings.h"
-#include "settings/AdvancedSettings.h"
-#include "windowing/WindowingFactory.h"
-
-#if defined(TARGET_RASPBERRY_PI)
-#include "linux/RBP.h"
-#endif
-
-CPiAudioAE::CPiAudioAE()
-: CThread("CPiAudio")
-{
-}
-
-CPiAudioAE::~CPiAudioAE()
-{
-}
-
-bool CPiAudioAE::Initialize()
-{
- UpdateStreamSilence();
- Create();
- return true;
-}
-
-void CPiAudioAE::Process()
-{
- while(!m_bStop)
- {
- /* thread just currently checks once a second if it's time to disable streamsilence */
- Sleep(1000);
-
- if (m_extSilenceTimer.IsTimePast())
- {
- UpdateStreamSilence(false);
- m_extSilenceTimer.Set(XbmcThreads::EndTime::InfiniteValue);
- }
- }
-}
-
-void CPiAudioAE::UpdateStreamSilence()
-{
- if (CSettings::Get().GetInt("audiooutput.streamsilence") > 0)
- m_extSilenceTimeout = CSettings::Get().GetInt("audiooutput.streamsilence") * 60000;
- else
- m_extSilenceTimeout = XbmcThreads::EndTime::InfiniteValue;
- m_extSilenceTimer.Set(m_extSilenceTimeout);
- UpdateStreamSilence(CSettings::Get().GetString("audiooutput.audiodevice") == "HDMI" &&
- CSettings::Get().GetInt("audiooutput.streamsilence") != 0);
-}
-
-void CPiAudioAE::UpdateStreamSilence(bool enable)
-{
-#if defined(TARGET_RASPBERRY_PI)
- char response[80] = "";
- char command[80] = "";
- sprintf(command, "force_audio hdmi %d", enable);
- vc_gencmd(response, sizeof response, command);
-#endif
-}
-
-bool CPiAudioAE::Suspend()
-{
- return true;
-}
-
-bool CPiAudioAE::Resume()
-{
- return true;
-}
-
-float CPiAudioAE::GetVolume()
-{
- return m_aeVolume;
-}
-
-void CPiAudioAE::SetVolume(const float volume)
-{
- m_aeVolume = std::max( 0.0f, std::min(1.0f, volume));
-}
-
-void CPiAudioAE::SetMute(const bool enabled)
-{
- m_aeMuted = enabled;
-}
-
-bool CPiAudioAE::IsMuted()
-{
- return m_aeMuted;
-}
-
-IAEStream *CPiAudioAE::MakeStream(enum AEDataFormat dataFormat, unsigned int sampleRate, unsigned int encodedSampleRate, CAEChannelInfo channelLayout, unsigned int options)
-{
- return NULL;
-}
-
-IAEStream *CPiAudioAE::FreeStream(IAEStream *stream)
-{
- // will retrigger the streamsilence timer
- UpdateStreamSilence();
- return NULL;
-}
-
-IAESound *CPiAudioAE::MakeSound(const std::string& file)
-{
- return NULL;
-}
-
-void CPiAudioAE::FreeSound(IAESound *sound)
-{
-}
-
-bool CPiAudioAE::SupportsRaw(AEDataFormat format)
-{
- bool supported = false;
-#if defined(TARGET_RASPBERRY_PI)
- if (CSettings::Get().GetString("audiooutput.audiodevice") == "HDMI")
- {
- if (!CSettings::Get().GetBool("audiooutput.dualaudio"))
- {
- DllBcmHost m_DllBcmHost;
- m_DllBcmHost.Load();
- if (format == AE_FMT_AC3 && CSettings::Get().GetBool("audiooutput.ac3passthrough") &&
- m_DllBcmHost.vc_tv_hdmi_audio_supported(EDID_AudioFormat_eAC3, 2, EDID_AudioSampleRate_e44KHz, EDID_AudioSampleSize_16bit ) == 0)
- supported = true;
- if (format == AE_FMT_DTS && CSettings::Get().GetBool("audiooutput.dtspassthrough") &&
- m_DllBcmHost.vc_tv_hdmi_audio_supported(EDID_AudioFormat_eDTS, 2, EDID_AudioSampleRate_e44KHz, EDID_AudioSampleSize_16bit ) == 0)
- supported = true;
- m_DllBcmHost.Unload();
- }
- }
-#endif
- return supported;
-}
-
-bool CPiAudioAE::SupportsSilenceTimeout()
-{
- return true;
-}
-
-void CPiAudioAE::OnSettingsChange(const std::string& setting)
-{
- if (setting == "audiooutput.streamsilence" || setting == "audiooutput.audiodevice")
- UpdateStreamSilence();
-}
-
-void CPiAudioAE::EnumerateOutputDevices(AEDeviceList &devices, bool passthrough)
-{
- if (!passthrough)
- {
- devices.push_back(AEDevice("Analogue", "Analogue"));
- devices.push_back(AEDevice("HDMI", "HDMI"));
- }
-}
-
-std::string CPiAudioAE::GetDefaultDevice(bool passthrough)
-{
- return "HDMI";
-}
-
-bool CPiAudioAE::IsSettingVisible(const std::string &settingId)
-{
- if (settingId == "audiooutput.samplerate")
- return true;
-
- if (CSettings::Get().GetString("audiooutput.audiodevice") == "HDMI")
- {
- if (settingId == "audiooutput.passthrough")
- return true;
- if (settingId == "audiooutput.dtspassthrough")
- return true;
- if (settingId == "audiooutput.ac3passthrough")
- return true;
- if (settingId == "audiooutput.channels")
- return true;
- if (settingId == "audiooutput.dualaudio")
- return true;
- if (settingId == "audiooutput.streamsilence")
- return true;
- }
- return false;
-}
diff --git a/xbmc/cores/AudioEngine/Engines/PiAudio/PiAudioAE.h b/xbmc/cores/AudioEngine/Engines/PiAudio/PiAudioAE.h
deleted file mode 100644
index 944fba89d5..0000000000
--- a/xbmc/cores/AudioEngine/Engines/PiAudio/PiAudioAE.h
+++ /dev/null
@@ -1,80 +0,0 @@
-#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 "system.h"
-#include "threads/Thread.h"
-
-#include "Interfaces/AEStream.h"
-#include "Interfaces/AESound.h"
-#include "AEFactory.h"
-
-namespace PiAudioAE
-{
-
-class CPiAudioAE : public IAE, public CThread
-{
-protected:
- friend class ::CAEFactory;
- CPiAudioAE();
- virtual ~CPiAudioAE();
- virtual bool Initialize();
- virtual void Process();
-
-public:
- virtual bool Suspend();
- virtual bool Resume();
- virtual void OnSettingsChange(const std::string& setting);
-
- virtual float GetVolume();
- virtual void SetVolume(const float volume);
- virtual void SetMute(const bool enabled);
- virtual bool IsMuted();
- virtual void SetSoundMode(const int mode) {}
-
- /* returns a new stream for data in the specified format */
- virtual IAEStream *MakeStream(enum AEDataFormat dataFormat, unsigned int sampleRate, unsigned int encodedSampleRate, CAEChannelInfo channelLayout, unsigned int options = 0);
- virtual IAEStream *FreeStream(IAEStream *stream);
-
- /* returns a new sound object */
- virtual IAESound *MakeSound(const std::string& file);
- virtual void FreeSound(IAESound *sound);
-
- virtual void GarbageCollect() {};
- virtual void EnumerateOutputDevices(AEDeviceList &devices, bool passthrough);
- virtual std::string GetDefaultDevice(bool passthrough);
- virtual bool IsSettingVisible(const std::string &settingId);
-
- virtual bool SupportsRaw(AEDataFormat format);
- virtual bool SupportsSilenceTimeout();
-
- virtual void OnLostDevice() {}
- virtual void OnResetDevice() {}
-
-protected:
- void UpdateStreamSilence();
- void UpdateStreamSilence(bool enable);
- // polled via the interface
- float m_aeVolume;
- bool m_aeMuted;
- int m_extSilenceTimeout;
- XbmcThreads::EndTime m_extSilenceTimer;
-};
-};
diff --git a/xbmc/cores/AudioEngine/Makefile.in b/xbmc/cores/AudioEngine/Makefile.in
index c1d53f55ea..7f8741082c 100644
--- a/xbmc/cores/AudioEngine/Makefile.in
+++ b/xbmc/cores/AudioEngine/Makefile.in
@@ -39,6 +39,8 @@ SRCS += AESinkFactory.cpp
SRCS += Sinks/AESinkNULL.cpp
SRCS += Sinks/AESinkProfiler.cpp
+SRCS += Sinks/AESinkPi.cpp
+
SRCS += Engines/ActiveAE/ActiveAE.cpp
SRCS += Engines/ActiveAE/ActiveAESink.cpp
SRCS += Engines/ActiveAE/ActiveAEStream.cpp
@@ -46,8 +48,6 @@ SRCS += Engines/ActiveAE/ActiveAESound.cpp
SRCS += Engines/ActiveAE/ActiveAEResample.cpp
SRCS += Engines/ActiveAE/ActiveAEBuffer.cpp
-SRCS += Engines/PiAudio/PiAudioAE.cpp
-
ifeq (@USE_ANDROID@,1)
SRCS += Sinks/AESinkAUDIOTRACK.cpp
else
diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp
new file mode 100644
index 0000000000..72beba4518
--- /dev/null
+++ b/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp
@@ -0,0 +1,293 @@
+/*
+ * 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"
+
+#if defined(TARGET_RASPBERRY_PI)
+
+#include <stdint.h>
+#include <limits.h>
+
+#include "AESinkPi.h"
+#include "cores/AudioEngine/Utils/AEUtil.h"
+#include "utils/log.h"
+#include "settings/Settings.h"
+#include "linux/RBP.h"
+
+#define CLASSNAME "CAESinkPi"
+
+#define NUM_OMX_BUFFERS 2
+#define AUDIO_PLAYBUFFER (1.0/20.0)
+
+CAEDeviceInfo CAESinkPi::m_info;
+
+CAESinkPi::CAESinkPi() :
+ m_sinkbuffer_size(0),
+ m_sinkbuffer_sec_per_byte(0),
+ m_Initialized(false),
+ m_submitted(0)
+{
+}
+
+CAESinkPi::~CAESinkPi()
+{
+}
+
+void CAESinkPi::SetAudioDest()
+{
+ OMX_ERRORTYPE omx_err = OMX_ErrorNone;
+ OMX_CONFIG_BRCMAUDIODESTINATIONTYPE audioDest;
+ OMX_INIT_STRUCTURE(audioDest);
+ if (CSettings::Get().GetString("audiooutput.audiodevice") == "Pi:Analogue")
+ strncpy((char *)audioDest.sName, "local", strlen("local"));
+ else
+ strncpy((char *)audioDest.sName, "hdmi", strlen("hdmi"));
+ omx_err = m_omx_render.SetConfig(OMX_IndexConfigBrcmAudioDestination, &audioDest);
+ if (omx_err != OMX_ErrorNone)
+ CLog::Log(LOGERROR, "%s::%s - m_omx_render.SetConfig omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
+}
+
+bool CAESinkPi::Initialize(AEAudioFormat &format, std::string &device)
+{
+ m_initDevice = device;
+ m_initFormat = format;
+ // setup for a 50ms sink feed from SoftAE
+ format.m_dataFormat = AE_FMT_S16NE;
+ format.m_frames = format.m_sampleRate * AUDIO_PLAYBUFFER;
+ format.m_frameSamples = format.m_channelLayout.Count();
+ format.m_frameSize = format.m_frameSamples * (CAEUtil::DataFormatToBits(format.m_dataFormat) >> 3);
+ format.m_sampleRate = std::max(8000U, std::min(96000U, format.m_sampleRate));
+
+ m_format = format;
+
+ m_sinkbuffer_size = format.m_frameSize * format.m_frames * NUM_OMX_BUFFERS;
+ m_sinkbuffer_sec_per_byte = 1.0 / (double)(format.m_frameSize * format.m_sampleRate);
+
+ CLog::Log(LOGDEBUG, "%s:%s Format:%d Channels:%d Samplerate:%d framesize:%d bufsize:%d bytes/s=%.2f", CLASSNAME, __func__,
+ format.m_dataFormat, format.m_channelLayout.Count(), format.m_sampleRate, format.m_frameSize, m_sinkbuffer_size, 1.0/m_sinkbuffer_sec_per_byte);
+
+ // This may be called before Application calls g_RBP.Initialise, so call it here too
+ g_RBP.Initialize();
+
+ CLog::Log(LOGDEBUG, "%s:%s", CLASSNAME, __func__);
+
+ OMX_ERRORTYPE omx_err = OMX_ErrorNone;
+
+ if (!m_omx_render.Initialize("OMX.broadcom.audio_render", OMX_IndexParamAudioInit))
+ CLog::Log(LOGERROR, "%s::%s - m_omx_render.Initialize omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
+
+ OMX_INIT_STRUCTURE(m_pcm_input);
+ m_pcm_input.nPortIndex = m_omx_render.GetInputPort();
+ m_pcm_input.eNumData = OMX_NumericalDataSigned;
+ m_pcm_input.eEndian = OMX_EndianLittle;
+ m_pcm_input.bInterleaved = OMX_TRUE;
+ m_pcm_input.nBitPerSample = 16;
+ m_pcm_input.ePCMMode = OMX_AUDIO_PCMModeLinear;
+ m_pcm_input.nChannels = m_format.m_frameSamples;
+ m_pcm_input.nSamplingRate = m_format.m_sampleRate;
+ m_pcm_input.eChannelMapping[0] = OMX_AUDIO_ChannelLF;
+ m_pcm_input.eChannelMapping[1] = OMX_AUDIO_ChannelRF;
+ m_pcm_input.eChannelMapping[2] = OMX_AUDIO_ChannelMax;
+
+ omx_err = m_omx_render.SetParameter(OMX_IndexParamAudioPcm, &m_pcm_input);
+ if (omx_err != OMX_ErrorNone)
+ CLog::Log(LOGERROR, "%s::%s - error m_omx_render SetParameter omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
+
+ m_omx_render.ResetEos();
+
+ SetAudioDest();
+
+ // set up the number/size of buffers for decoder input
+ OMX_PARAM_PORTDEFINITIONTYPE port_param;
+ OMX_INIT_STRUCTURE(port_param);
+ port_param.nPortIndex = m_omx_render.GetInputPort();
+
+ omx_err = m_omx_render.GetParameter(OMX_IndexParamPortDefinition, &port_param);
+ if (omx_err != OMX_ErrorNone)
+ CLog::Log(LOGERROR, "%s:%s - error get OMX_IndexParamPortDefinition (input) omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
+
+ port_param.nBufferCountActual = std::max((unsigned int)port_param.nBufferCountMin, (unsigned int)NUM_OMX_BUFFERS);
+ port_param.nBufferSize = m_sinkbuffer_size / port_param.nBufferCountActual;
+
+ omx_err = m_omx_render.SetParameter(OMX_IndexParamPortDefinition, &port_param);
+ if (omx_err != OMX_ErrorNone)
+ CLog::Log(LOGERROR, "%s:%s - error set OMX_IndexParamPortDefinition (intput) omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
+
+ omx_err = m_omx_render.AllocInputBuffers();
+ if (omx_err != OMX_ErrorNone)
+ CLog::Log(LOGERROR, "%s:%s - Error alloc buffers 0x%08x", CLASSNAME, __func__, omx_err);
+
+ omx_err = m_omx_render.SetStateForComponent(OMX_StateExecuting);
+ if (omx_err != OMX_ErrorNone)
+ CLog::Log(LOGERROR, "%s:%s - m_omx_render OMX_StateExecuting omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
+
+ m_Initialized = true;
+ return true;
+}
+
+
+void CAESinkPi::Deinitialize()
+{
+ CLog::Log(LOGDEBUG, "%s:%s", CLASSNAME, __func__);
+ if (m_Initialized)
+ {
+ m_omx_render.FlushAll();
+ m_omx_render.Deinitialize();
+ m_Initialized = false;
+ }
+}
+
+bool CAESinkPi::IsCompatible(const AEAudioFormat &format, const std::string &device)
+{
+ bool compatible =
+ /* compare against the requested format and the real format */
+ (m_initFormat.m_sampleRate == format.m_sampleRate || m_format.m_sampleRate == format.m_sampleRate ) &&
+ (m_initFormat.m_dataFormat == format.m_dataFormat || m_format.m_dataFormat == format.m_dataFormat ) &&
+ (m_initFormat.m_channelLayout == format.m_channelLayout || m_format.m_channelLayout == format.m_channelLayout) &&
+ (m_initDevice == device);
+ CLog::Log(LOGDEBUG, "%s:%s Format:%d Channels:%d Samplerate:%d = %d", CLASSNAME, __func__, format.m_dataFormat, format.m_channelLayout.Count(), format.m_sampleRate, compatible);
+ return compatible;
+}
+
+double CAESinkPi::GetDelay()
+{
+ OMX_PARAM_U32TYPE param;
+ OMX_INIT_STRUCTURE(param);
+
+ if (!m_Initialized)
+ return 0.0;
+
+ param.nPortIndex = m_omx_render.GetInputPort();
+
+ OMX_ERRORTYPE omx_err = m_omx_render.GetConfig(OMX_IndexConfigAudioRenderingLatency, &param);
+
+ if (omx_err != OMX_ErrorNone)
+ {
+ CLog::Log(LOGERROR, "%s::%s - error getting OMX_IndexConfigAudioRenderingLatency error 0x%08x",
+ CLASSNAME, __func__, omx_err);
+ }
+ double sinkbuffer_seconds_to_empty = m_sinkbuffer_sec_per_byte * param.nU32 * m_format.m_frameSize;
+ return sinkbuffer_seconds_to_empty;
+}
+
+double CAESinkPi::GetCacheTime()
+{
+ return GetDelay();
+}
+
+double CAESinkPi::GetCacheTotal()
+{
+ double audioplus_buffer = AUDIO_PLAYBUFFER;
+ return m_sinkbuffer_sec_per_byte * (double)m_sinkbuffer_size + audioplus_buffer;
+}
+
+unsigned int CAESinkPi::AddPackets(uint8_t *data, unsigned int frames, bool hasAudio, bool blocking)
+{
+ unsigned int sent = 0;
+
+ if (!m_Initialized)
+ return frames;
+
+ OMX_ERRORTYPE omx_err = OMX_ErrorNone;
+ OMX_BUFFERHEADERTYPE *omx_buffer = NULL;
+ while (sent < frames)
+ {
+ int timeout = blocking ? 1000 : 0;
+
+ // delay compared to maximum we'd like (to keep lag low)
+ double delay = GetDelay();
+ bool too_laggy = delay - AUDIO_PLAYBUFFER > 0.0;
+ omx_buffer = too_laggy ? NULL : m_omx_render.GetInputBuffer(timeout);
+
+ if (omx_buffer == NULL)
+ {
+ if (too_laggy)
+ {
+ Sleep((int)((delay - AUDIO_PLAYBUFFER) * 1000.0));
+ continue;
+ }
+ if (blocking)
+ CLog::Log(LOGERROR, "COMXAudio::Decode timeout");
+ break;
+ }
+
+ omx_buffer->nFilledLen = std::min(omx_buffer->nAllocLen, (frames - sent) * m_format.m_frameSize);
+ omx_buffer->nTimeStamp = ToOMXTime(0);
+ omx_buffer->nFlags = 0;
+ memcpy(omx_buffer->pBuffer, (uint8_t *)data + sent * m_format.m_frameSize, omx_buffer->nFilledLen);
+ sent += omx_buffer->nFilledLen / m_format.m_frameSize;
+
+ if (sent == frames)
+ omx_buffer->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME;
+
+ if (delay <= 0.0 && m_submitted)
+ CLog::Log(LOGERROR, "%s:%s Underrun (delay:%.2f frames:%d)", CLASSNAME, __func__, delay, frames);
+
+ omx_err = m_omx_render.EmptyThisBuffer(omx_buffer);
+ if (omx_err != OMX_ErrorNone)
+ CLog::Log(LOGERROR, "%s:%s frames=%d err=%x", CLASSNAME, __func__, frames, omx_err);
+ m_submitted += omx_buffer->nFilledLen;
+ }
+
+ return sent;
+}
+
+void CAESinkPi::Drain()
+{
+ int delay = (int)(GetDelay() * 1000.0);
+ if (delay)
+ Sleep(delay);
+ CLog::Log(LOGDEBUG, "%s:%s delay:%dms now:%dms", CLASSNAME, __func__, delay, (int)(GetDelay() * 1000.0));
+}
+
+void CAESinkPi::EnumerateDevicesEx(AEDeviceInfoList &list, bool force)
+{
+ m_info.m_channels.Reset();
+ m_info.m_dataFormats.clear();
+ m_info.m_sampleRates.clear();
+
+ m_info.m_deviceType = AE_DEVTYPE_HDMI;
+ m_info.m_deviceName = "HDMI";
+ m_info.m_displayName = "HDMI";
+ m_info.m_displayNameExtra = "";
+ m_info.m_channels += AE_CH_FL;
+ m_info.m_channels += AE_CH_FR;
+ m_info.m_sampleRates.push_back(48000);
+ m_info.m_dataFormats.push_back(AE_FMT_S16LE);
+
+ list.push_back(m_info);
+
+ m_info.m_channels.Reset();
+ m_info.m_dataFormats.clear();
+ m_info.m_sampleRates.clear();
+
+ m_info.m_deviceType = AE_DEVTYPE_PCM;
+ m_info.m_deviceName = "Analogue";
+ m_info.m_displayName = "Analogue";
+ m_info.m_displayNameExtra = "";
+ m_info.m_channels += AE_CH_FL;
+ m_info.m_channels += AE_CH_FR;
+ m_info.m_sampleRates.push_back(48000);
+ m_info.m_dataFormats.push_back(AE_FMT_S16LE);
+
+ list.push_back(m_info);
+}
+
+#endif
diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkPi.h b/xbmc/cores/AudioEngine/Sinks/AESinkPi.h
new file mode 100644
index 0000000000..1f3311560e
--- /dev/null
+++ b/xbmc/cores/AudioEngine/Sinks/AESinkPi.h
@@ -0,0 +1,65 @@
+#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 "system.h"
+
+#if defined(TARGET_RASPBERRY_PI)
+
+#include "cores/AudioEngine/Interfaces/AESink.h"
+#include "Utils/AEDeviceInfo.h"
+
+#include "cores/omxplayer/OMXAudio.h"
+
+class CAESinkPi : public IAESink
+{
+public:
+ virtual const char *GetName() { return "SinkPi"; }
+
+ CAESinkPi();
+ virtual ~CAESinkPi();
+
+ virtual bool Initialize(AEAudioFormat &format, std::string &device);
+ virtual void Deinitialize();
+ virtual bool IsCompatible(const AEAudioFormat &format, const std::string &device);
+
+ virtual double GetDelay ();
+ virtual double GetCacheTime ();
+ virtual double GetCacheTotal ();
+ virtual unsigned int AddPackets (uint8_t *data, unsigned int frames, bool hasAudio, bool blocking = false);
+ virtual void Drain ();
+
+ static void EnumerateDevicesEx(AEDeviceInfoList &list, bool force = false);
+private:
+ void SetAudioDest();
+
+ std::string m_initDevice;
+ AEAudioFormat m_initFormat;
+ AEAudioFormat m_format;
+ unsigned int m_sinkbuffer_size; ///< total size of the buffer
+ double m_sinkbuffer_sec_per_byte;
+ static CAEDeviceInfo m_info;
+ bool m_Initialized;
+ uint32_t m_submitted;
+ OMX_AUDIO_PARAM_PCMMODETYPE m_pcm_input;
+ COMXCoreComponent m_omx_render;
+};
+
+#endif
diff --git a/xbmc/cores/dvdplayer/DVDSubtitles/DVDSubtitleStream.cpp b/xbmc/cores/dvdplayer/DVDSubtitles/DVDSubtitleStream.cpp
index 30756cf2e1..5218d01b0e 100644
--- a/xbmc/cores/dvdplayer/DVDSubtitles/DVDSubtitleStream.cpp
+++ b/xbmc/cores/dvdplayer/DVDSubtitles/DVDSubtitleStream.cpp
@@ -23,8 +23,11 @@
#include "DVDInputStreams/DVDInputStream.h"
#include "utils/CharsetConverter.h"
#include "utils/Utf8Utils.h"
+#include "utils/CharsetDetection.h"
+#include "filesystem/File.h"
using namespace std;
+using XFILE::auto_buffer;
CDVDSubtitleStream::CDVDSubtitleStream()
{
@@ -40,60 +43,51 @@ bool CDVDSubtitleStream::Open(const string& strFile)
pInputStream = CDVDFactoryInputStream::CreateInputStream(NULL, strFile, "");
if (pInputStream && pInputStream->Open(strFile.c_str(), ""))
{
- unsigned char buffer[16384];
- int size_read = 0;
- size_read = pInputStream->Read(buffer,3);
- bool isUTF8 = false;
- bool isUTF16 = false;
- if (buffer[0] == 0xEF && buffer[1] == 0xBB && buffer[2] == 0xBF)
- isUTF8 = true;
- else if (buffer[0] == 0xFF && buffer[1] == 0xFE)
+ static const size_t chunksize = 64 * 1024;
+ auto_buffer buf;
+
+ // read content
+ size_t totalread = 0;
+ int read;
+ do
{
- isUTF16 = true;
- pInputStream->Seek(2, SEEK_SET);
- }
- else
- pInputStream->Seek(0, SEEK_SET);
+ if (totalread == buf.size())
+ buf.resize(buf.size() + chunksize);
+
+ read = pInputStream->Read((uint8_t*)buf.get() + totalread, buf.size() - totalread);
+ if (read > 0)
+ totalread += read;
+ } while (read > 0);
+
+ delete pInputStream;
+ if (!totalread)
+ return false;
- if (isUTF16)
+ std::string tmpStr(buf.get(), totalread);
+ buf.clear();
+
+ std::string enc(CCharsetDetection::GetBomEncoding(tmpStr));
+ if (enc == "UTF-8" || (enc.empty() && CUtf8Utils::isValidUtf8(tmpStr)))
+ m_stringstream << tmpStr;
+ else if (!enc.empty())
{
- std::wstringstream wstringstream;
- while( (size_read = pInputStream->Read(buffer, sizeof(buffer)-2) ) > 0 )
- {
- buffer[size_read] = buffer[size_read + 1] = '\0';
- CStdStringW temp;
- g_charsetConverter.utf16LEtoW(std::u16string((char16_t*)buffer),temp);
- wstringstream << temp;
- }
- delete pInputStream;
-
- CStdString strUTF8;
- g_charsetConverter.wToUTF8(CStdStringW(wstringstream.str()),strUTF8);
- m_stringstream.str("");
- m_stringstream << strUTF8;
+ std::string converted;
+ g_charsetConverter.ToUtf8(enc, tmpStr, converted);
+ if (converted.empty())
+ return false;
+
+ m_stringstream << converted;
}
else
{
- while( (size_read = pInputStream->Read(buffer, sizeof(buffer)-1) ) > 0 )
- {
- buffer[size_read] = '\0';
- m_stringstream << buffer;
- }
- delete pInputStream;
-
- if (!isUTF8)
- isUTF8 = CUtf8Utils::isValidUtf8(m_stringstream.str());
-
- if (!isUTF8)
- {
- CStdStringW strUTF16;
- CStdString strUTF8;
- g_charsetConverter.subtitleCharsetToW(m_stringstream.str(), strUTF16);
- g_charsetConverter.wToUTF8(strUTF16,strUTF8);
- m_stringstream.str("");
- m_stringstream << strUTF8;
- }
+ std::string converted;
+ g_charsetConverter.subtitleCharsetToUtf8(tmpStr, converted);
+ if (converted.empty())
+ return false;
+
+ m_stringstream << converted;
}
+
return true;
}
diff --git a/xbmc/cores/omxplayer/OMXAudio.cpp b/xbmc/cores/omxplayer/OMXAudio.cpp
index dbd065f442..440a26e71d 100644
--- a/xbmc/cores/omxplayer/OMXAudio.cpp
+++ b/xbmc/cores/omxplayer/OMXAudio.cpp
@@ -83,17 +83,16 @@ COMXAudio::COMXAudio() :
m_submitted_eos (false ),
m_failed_eos (false )
{
- m_vizBufferSize = m_vizRemapBufferSize = VIS_PACKET_SIZE * sizeof(float);
- m_vizRemapBuffer = (uint8_t *)_aligned_malloc(m_vizRemapBufferSize,16);
- m_vizBuffer = (uint8_t *)_aligned_malloc(m_vizBufferSize,16);
+ CAEFactory::Suspend();
+ while (!CAEFactory::IsSuspended())
+ Sleep(10);
}
COMXAudio::~COMXAudio()
{
Deinitialize();
- _aligned_free(m_vizRemapBuffer);
- _aligned_free(m_vizBuffer);
+ CAEFactory::Resume();
}
bool COMXAudio::PortSettingsChanged()
@@ -118,12 +117,12 @@ bool COMXAudio::PortSettingsChanged()
if(!m_omx_splitter.Initialize("OMX.broadcom.audio_splitter", OMX_IndexParamAudioInit))
return false;
}
- if (CSettings::Get().GetBool("audiooutput.dualaudio") || CSettings::Get().GetString("audiooutput.audiodevice") == "Analogue")
+ if (CSettings::Get().GetBool("audiooutput.dualaudio") || CSettings::Get().GetString("audiooutput.audiodevice") == "Pi:Analogue")
{
if(!m_omx_render_analog.Initialize("OMX.broadcom.audio_render", OMX_IndexParamAudioInit))
return false;
}
- if (CSettings::Get().GetBool("audiooutput.dualaudio") || CSettings::Get().GetString("audiooutput.audiodevice") == "HDMI")
+ if (CSettings::Get().GetBool("audiooutput.dualaudio") || CSettings::Get().GetString("audiooutput.audiodevice") != "Pi:Analogue")
{
if(!m_omx_render_hdmi.Initialize("OMX.broadcom.audio_render", OMX_IndexParamAudioInit))
return false;
@@ -471,7 +470,7 @@ bool COMXAudio::Initialize(AEAudioFormat format, OMXClock *clock, CDVDStreamInfo
enum PCMChannels outLayout[OMX_AUDIO_MAXCHANNELS];
enum PCMLayout layout = (enum PCMLayout)std::max(0, CSettings::Get().GetInt("audiooutput.channels")-1);
// ignore layout setting for analogue
- if (CSettings::Get().GetBool("audiooutput.dualaudio") || CSettings::Get().GetString("audiooutput.audiodevice") == "Analogue")
+ if (CSettings::Get().GetBool("audiooutput.dualaudio") || CSettings::Get().GetString("audiooutput.audiodevice") == "Pi:Analogue")
layout = PCM_LAYOUT_2_0;
// force out layout to stereo if input is not multichannel - it gives the receiver a chance to upmix
@@ -487,8 +486,6 @@ bool COMXAudio::Initialize(AEAudioFormat format, OMXClock *clock, CDVDStreamInfo
m_wave_header.dwChannelMask = channelMap;
BuildChannelMapOMX(m_input_channels, channelMap);
BuildChannelMapOMX(m_output_channels, GetChannelLayout(layout));
-
- m_vizRemap.Initialize(GetAEChannelLayout(channelMap), CAEChannelInfo(AE_CH_LAYOUT_2_0), false, true);
}
m_SampleRate = m_format.m_sampleRate;
@@ -690,9 +687,6 @@ bool COMXAudio::Initialize(AEAudioFormat format, OMXClock *clock, CDVDStreamInfo
CLog::Log(LOGDEBUG, "COMXAudio::Initialize device passthrough %d hwdecode %d",
m_Passthrough, m_HWDecode);
- /* dummy call to inform PiAudioAE that audo is active */
- CAEFactory::MakeStream((enum AEDataFormat)0, 0, 0, (CAEChannelInfo)0, 0);
-
return true;
}
@@ -752,9 +746,6 @@ bool COMXAudio::Deinitialize()
m_extradata = NULL;
m_extrasize = 0;
- while(!m_vizqueue.empty())
- m_vizqueue.pop();
-
m_dllAvUtil.Unload();
while(!m_ampqueue.empty())
@@ -764,9 +755,6 @@ bool COMXAudio::Deinitialize()
m_submitted = 0.0f;
m_maxLevel = 0.0f;
- /* dummy call to inform PiAudioAE that audo is inactive */
- CAEFactory::FreeStream(0);
-
return true;
}
@@ -874,62 +862,6 @@ bool COMXAudio::ApplyVolume(void)
return true;
}
-void COMXAudio::VizPacket(const void* data, unsigned int len, double pts)
-{
- /* input samples */
- unsigned int vizBufferSamples = len / (CAEUtil::DataFormatToBits(m_format.m_dataFormat) >> 3);
-
- /* input frames */
- unsigned int frames = vizBufferSamples / m_InputChannels;
- float *floatBuffer = (float *)data;
-
- if (m_format.m_dataFormat != AE_FMT_FLOAT)
- {
- CAEConvert::AEConvertToFn m_convertFn = CAEConvert::ToFloat(m_format.m_dataFormat);
-
- /* check convert buffer */
- CheckOutputBufferSize((void **)&m_vizBuffer, &m_vizBufferSize, vizBufferSamples * (CAEUtil::DataFormatToBits(AE_FMT_FLOAT) >> 3));
-
- /* convert to float */
- m_convertFn((uint8_t *)data, vizBufferSamples, (float *)m_vizBuffer);
- floatBuffer = (float *)m_vizBuffer;
- }
-
- // Viz channel count is 2
- CheckOutputBufferSize((void **)&m_vizRemapBuffer, &m_vizRemapBufferSize, frames * 2 * sizeof(float));
-
- /* remap */
- m_vizRemap.Remap(floatBuffer, (float*)m_vizRemapBuffer, frames);
-
- /* output samples */
- vizBufferSamples = vizBufferSamples / m_InputChannels * 2;
-
- /* viz size is limited */
- if(vizBufferSamples > VIS_PACKET_SIZE)
- vizBufferSamples = VIS_PACKET_SIZE;
-
- vizblock_t v;
- v.pts = pts;
- v.num_samples = vizBufferSamples;
- memcpy(v.samples, m_vizRemapBuffer, vizBufferSamples * sizeof(float));
- m_vizqueue.push(v);
-
- double stamp = m_av_clock->OMXMediaTime();
- while(!m_vizqueue.empty())
- {
- vizblock_t &v = m_vizqueue.front();
- /* if packet has almost reached media time (allow time for rendering delay) then display it */
- /* we'll also consume if queue gets unexpectedly long to avoid filling memory */
- if (v.pts == DVD_NOPTS_VALUE || v.pts - stamp < DVD_SEC_TO_TIME(1.0/30.0) || v.pts - stamp > DVD_SEC_TO_TIME(15.0))
- {
- m_pCallback->OnAudioData(v.samples, v.num_samples);
- m_vizqueue.pop();
- }
- else break;
- }
-}
-
-
//***********************************************************************************************
unsigned int COMXAudio::AddPackets(const void* data, unsigned int len)
{
@@ -947,9 +879,6 @@ unsigned int COMXAudio::AddPackets(const void* data, unsigned int len, double dt
return len;
}
- if (m_pCallback && len && !(m_Passthrough || m_HWDecode))
- VizPacket(data, len, pts);
-
if(m_eEncoding == OMX_AUDIO_CodingDTS && m_LostSync && (m_Passthrough || m_HWDecode))
{
int skip = SyncDTS((uint8_t *)data, len);
diff --git a/xbmc/cores/omxplayer/OMXAudio.h b/xbmc/cores/omxplayer/OMXAudio.h
index 1a223e1414..804bd2aadc 100644
--- a/xbmc/cores/omxplayer/OMXAudio.h
+++ b/xbmc/cores/omxplayer/OMXAudio.h
@@ -98,7 +98,6 @@ public:
bool BadState() { return !m_Initialized; };
unsigned int GetAudioRenderingLatency();
float GetMaxLevel(double &pts);
- void VizPacket(const void* data, unsigned int len, double pts);
void BuildChannelMap(enum PCMChannels *channelMap, uint64_t layout);
int BuildChannelMapCEA(enum PCMChannels *channelMap, uint64_t layout);
@@ -135,19 +134,8 @@ private:
int m_extrasize;
// stuff for visualisation
double m_last_pts;
- int m_vizBufferSize;
- uint8_t *m_vizBuffer;
- int m_vizRemapBufferSize;
- uint8_t *m_vizRemapBuffer;
- CAERemap m_vizRemap;
bool m_submitted_eos;
bool m_failed_eos;
- typedef struct {
- int num_samples;
- float samples[VIS_PACKET_SIZE];
- double pts;
- } vizblock_t;
- std::queue<vizblock_t> m_vizqueue;
typedef struct {
double pts;
diff --git a/xbmc/cores/omxplayer/OMXPlayer.cpp b/xbmc/cores/omxplayer/OMXPlayer.cpp
index 7e2199ac82..e391c0e84e 100644
--- a/xbmc/cores/omxplayer/OMXPlayer.cpp
+++ b/xbmc/cores/omxplayer/OMXPlayer.cpp
@@ -3303,17 +3303,7 @@ bool COMXPlayer::OpenVideoStream(int iStream, int source, bool reset)
if(m_CurrentVideo.id < 0
|| m_CurrentVideo.hint != hint)
{
- // for music file, don't open artwork as video
- bool disabled = false;
- CStdString extension = URIUtils::GetExtension(m_filename);
- StringUtils::ToLower(extension);
- if (!extension.empty() && g_advancedSettings.m_musicExtensions.find(extension) != std::string::npos)
- {
- CLog::Log(LOGWARNING, "%s - Ignoring video in audio filetype:%s", __FUNCTION__, m_filename.c_str());
- disabled = true;
- }
-
- if (disabled || !m_omxPlayerVideo.OpenStream(hint))
+ if (!m_omxPlayerVideo.OpenStream(hint))
{
/* mark stream as disabled, to disallaw further attempts */
CLog::Log(LOGWARNING, "%s - Unsupported stream %d. Stream disabled.", __FUNCTION__, iStream);
diff --git a/xbmc/cores/omxplayer/OMXPlayerAudio.cpp b/xbmc/cores/omxplayer/OMXPlayerAudio.cpp
index 7949ebcc19..27dbb5d75c 100644
--- a/xbmc/cores/omxplayer/OMXPlayerAudio.cpp
+++ b/xbmc/cores/omxplayer/OMXPlayerAudio.cpp
@@ -511,12 +511,12 @@ AEDataFormat OMXPlayerAudio::GetDataFormat(CDVDStreamInfo hints)
/* check our audio capabilties */
/* pathrought is overriding hw decode*/
- if(hints.codec == AV_CODEC_ID_AC3 && CAEFactory::SupportsRaw(AE_FMT_AC3))
+ if(hints.codec == AV_CODEC_ID_AC3 && CAEFactory::SupportsRaw(AE_FMT_AC3) && !CSettings::Get().GetBool("audiooutput.dualaudio"))
{
dataFormat = AE_FMT_AC3;
m_passthrough = true;
}
- if(hints.codec == AV_CODEC_ID_DTS && CAEFactory::SupportsRaw(AE_FMT_DTS))
+ if(hints.codec == AV_CODEC_ID_DTS && CAEFactory::SupportsRaw(AE_FMT_DTS) && !CSettings::Get().GetBool("audiooutput.dualaudio"))
{
dataFormat = AE_FMT_DTS;
m_passthrough = true;
diff --git a/xbmc/cores/omxplayer/omxplayer_advancedsettings.xml b/xbmc/cores/omxplayer/omxplayer_advancedsettings.xml
index 4995b32e68..77c6a155cd 100644
--- a/xbmc/cores/omxplayer/omxplayer_advancedsettings.xml
+++ b/xbmc/cores/omxplayer/omxplayer_advancedsettings.xml
@@ -4,8 +4,4 @@
<defaultplayer>omxplayer</defaultplayer>
<defaultdvdplayer>omxplayer</defaultdvdplayer>
</video>
- <audio>
- <defaultplayer>omxplayer</defaultplayer>
- <streamsilence>false</streamsilence>
- </audio>
</advancedsettings>
diff --git a/xbmc/cores/playercorefactory/PlayerCoreConfig.h b/xbmc/cores/playercorefactory/PlayerCoreConfig.h
index 7a5d4e72b1..27f0beca5f 100644
--- a/xbmc/cores/playercorefactory/PlayerCoreConfig.h
+++ b/xbmc/cores/playercorefactory/PlayerCoreConfig.h
@@ -93,14 +93,10 @@ public:
pPlayer = new COMXPlayer(callback);
CLog::Log(LOGINFO, "Created player %s for core %d / OMXPlayer forced as DVDPlayer", "OMXPlayer", m_eCore);
break;
- case EPC_PAPLAYER:
- pPlayer = new COMXPlayer(callback);
- CLog::Log(LOGINFO, "Created player %s for core %d / OMXPlayer forced as PAPLayer", "OMXPlayer", m_eCore);
- break;
#else
case EPC_DVDPLAYER: pPlayer = new CDVDPlayer(callback); break;
- case EPC_PAPLAYER: pPlayer = new PAPlayer(callback); break;
#endif
+ case EPC_PAPLAYER: pPlayer = new PAPlayer(callback); break;
case EPC_EXTPLAYER: pPlayer = new CExternalPlayer(callback); break;
#if defined(HAS_OMXPLAYER)
case EPC_OMXPLAYER: pPlayer = new COMXPlayer(callback); break;
diff --git a/xbmc/linux/RBP.cpp b/xbmc/linux/RBP.cpp
index ef489354e9..947925910b 100644
--- a/xbmc/linux/RBP.cpp
+++ b/xbmc/linux/RBP.cpp
@@ -42,6 +42,10 @@ CRBP::~CRBP()
bool CRBP::Initialize()
{
+ CSingleLock lock (m_critSection);
+ if (m_initialized)
+ return true;
+
m_initialized = m_DllBcmHost->Load();
if(!m_initialized)
return false;
diff --git a/xbmc/linux/RBP.h b/xbmc/linux/RBP.h
index f742934e86..9d527db46d 100644
--- a/xbmc/linux/RBP.h
+++ b/xbmc/linux/RBP.h
@@ -37,6 +37,7 @@
#if defined(TARGET_RASPBERRY_PI)
#include "DllBCM.h"
#include "OMXCore.h"
+#include "threads/CriticalSection.h"
class CRBP
{
@@ -63,6 +64,7 @@ private:
int m_gpu_mem;
COMXCore *m_OMX;
class DllLibOMXCore;
+ CCriticalSection m_critSection;
};
extern CRBP g_RBP;
diff --git a/xbmc/utils/CharsetConverter.cpp b/xbmc/utils/CharsetConverter.cpp
index 5fb0c95885..aa75d0af4a 100644
--- a/xbmc/utils/CharsetConverter.cpp
+++ b/xbmc/utils/CharsetConverter.cpp
@@ -271,7 +271,7 @@ enum StdConversionType /* Keep it in sync with CCharsetConverter::CInnerConverte
Utf32ToUtf8,
Utf32ToW,
WToUtf32,
- SubtitleCharsetToW,
+ SubtitleCharsetToUtf8,
Utf8ToUserCharset,
UserCharsetToUtf8,
Utf32ToUserCharset,
@@ -315,7 +315,7 @@ CConverterType CCharsetConverter::CInnerConverter::m_stdConversion[NumberOfStdCo
/* Utf32ToUtf8 */ CConverterType(UTF32_CHARSET, "UTF-8", CCharsetConverter::m_Utf8CharMaxSize),
/* Utf32ToW */ CConverterType(UTF32_CHARSET, WCHAR_CHARSET),
/* WToUtf32 */ CConverterType(WCHAR_CHARSET, UTF32_CHARSET),
- /* SubtitleCharsetToW */ CConverterType(SubtitleCharset, WCHAR_CHARSET),
+ /* SubtitleCharsetToUtf8*/CConverterType(SubtitleCharset, "UTF-8", CCharsetConverter::m_Utf8CharMaxSize),
/* Utf8ToUserCharset */ CConverterType(UTF8_SOURCE, UserCharset),
/* UserCharsetToUtf8 */ CConverterType(UserCharset, "UTF-8", CCharsetConverter::m_Utf8CharMaxSize),
/* Utf32ToUserCharset */ CConverterType(UTF32_CHARSET, UserCharset),
@@ -654,7 +654,7 @@ void CCharsetConverter::resetUserCharset(void)
void CCharsetConverter::resetSubtitleCharset(void)
{
- CInnerConverter::m_stdConversion[SubtitleCharsetToW].Reset();
+ CInnerConverter::m_stdConversion[SubtitleCharsetToUtf8].Reset();
}
void CCharsetConverter::resetKaraokeCharset(void)
@@ -749,9 +749,9 @@ bool CCharsetConverter::utf8ToW(const std::string& utf8StringSrc, std::wstring&
return CInnerConverter::stdConvert(Utf8toW, utf8StringSrc, wStringDst, failOnBadChar);
}
-bool CCharsetConverter::subtitleCharsetToW(const std::string& stringSrc, std::wstring& wStringDst)
+bool CCharsetConverter::subtitleCharsetToUtf8(const std::string& stringSrc, std::string& utf8StringDst)
{
- return CInnerConverter::stdConvert(SubtitleCharsetToW, stringSrc, wStringDst, false);
+ return CInnerConverter::stdConvert(SubtitleCharsetToUtf8, stringSrc, utf8StringDst, false);
}
bool CCharsetConverter::fromW(const std::wstring& wStringSrc,
diff --git a/xbmc/utils/CharsetConverter.h b/xbmc/utils/CharsetConverter.h
index 325daa8fa3..f80411fddd 100644
--- a/xbmc/utils/CharsetConverter.h
+++ b/xbmc/utils/CharsetConverter.h
@@ -131,7 +131,7 @@ public:
static bool utf16LEtoW(const std::u16string& utf16String, std::wstring& wString);
- static bool subtitleCharsetToW(const std::string& stringSrc, std::wstring& wStringDst);
+ static bool subtitleCharsetToUtf8(const std::string& stringSrc, std::string& utf8StringDst);
static bool utf8ToStringCharset(const std::string& utf8StringSrc, std::string& stringDst);
diff --git a/xbmc/utils/FileOperationJob.cpp b/xbmc/utils/FileOperationJob.cpp
index 901eba99c4..b1f061294e 100644
--- a/xbmc/utils/FileOperationJob.cpp
+++ b/xbmc/utils/FileOperationJob.cpp
@@ -158,11 +158,6 @@ bool CFileOperationJob::DoProcess(FileAction action, CFileItemList & items, cons
URIUtils::RemoveSlashAtEnd(strNoSlash);
CStdString strFileName = URIUtils::GetFileName(strNoSlash);
- // URL Decode for cases where source uses URL encoding and target does not
- if ( URIUtils::ProtocolHasEncodedFilename(CURL(pItem->GetPath()).GetProtocol() )
- && !URIUtils::ProtocolHasEncodedFilename(CURL(strDestFile).GetProtocol() ) )
- CURL::Decode(strFileName);
-
// special case for upnp
if (URIUtils::IsUPnP(items.GetPath()) || URIUtils::IsUPnP(pItem->GetPath()))
{
@@ -181,7 +176,7 @@ bool CFileOperationJob::DoProcess(FileAction action, CFileItemList & items, cons
CStdString strnewDestFile;
if(!strDestFile.empty()) // only do this if we have a destination
- strnewDestFile = URIUtils::AddFileToFolder(strDestFile, strFileName);
+ strnewDestFile = URIUtils::ChangeBasePath(pItem->GetPath(), strFileName, strDestFile); // Convert (URL) encoding + slashes (if source / target differ)
if (pItem->m_bIsFolder)
{
diff --git a/xbmc/utils/URIUtils.cpp b/xbmc/utils/URIUtils.cpp
index 5b292bc25a..1f44d6fcfc 100644
--- a/xbmc/utils/URIUtils.cpp
+++ b/xbmc/utils/URIUtils.cpp
@@ -395,29 +395,80 @@ bool URIUtils::GetParentPath(const CStdString& strPath, CStdString& strParent)
return true;
}
+std::string URLEncodePath(const std::string& strPath)
+{
+ vector<string> segments = StringUtils::Split(strPath, "/");
+ for (vector<string>::iterator i = segments.begin(); i != segments.end(); ++i)
+ *i = CURL::Encode(*i);
+
+ return StringUtils::Join(segments, "/");
+}
+
+std::string URLDecodePath(const std::string& strPath)
+{
+ vector<string> segments = StringUtils::Split(strPath, "/");
+ for (vector<string>::iterator i = segments.begin(); i != segments.end(); ++i)
+ *i = CURL::Decode(*i);
+
+ return StringUtils::Join(segments, "/");
+}
+
+std::string URIUtils::ChangeBasePath(const std::string &fromPath, const std::string &fromFile, const std::string &toPath)
+{
+ std::string toFile = fromFile;
+
+ // Convert back slashes to forward slashes, if required
+ if (IsDOSPath(fromPath) && !IsDOSPath(toPath))
+ StringUtils::Replace(toFile, "\\", "/");
+
+ // Handle difference in URL encoded vs. not encoded
+ if ( ProtocolHasEncodedFilename(CURL(fromPath).GetProtocol() )
+ && !ProtocolHasEncodedFilename(CURL(toPath).GetProtocol() ) )
+ {
+ toFile = URLDecodePath(toFile); // Decode path
+ }
+ else if (!ProtocolHasEncodedFilename(CURL(fromPath).GetProtocol() )
+ && ProtocolHasEncodedFilename(CURL(toPath).GetProtocol() ) )
+ {
+ toFile = URLEncodePath(toFile); // Encode path
+ }
+
+ // Convert forward slashes to back slashes, if required
+ if (!IsDOSPath(fromPath) && IsDOSPath(toPath))
+ StringUtils::Replace(toFile, "/", "\\");
+
+ return AddFileToFolder(toPath, toFile);
+}
+
CStdString URIUtils::SubstitutePath(const CStdString& strPath, bool reverse /* = false */)
{
for (CAdvancedSettings::StringMapping::iterator i = g_advancedSettings.m_pathSubstitutions.begin();
i != g_advancedSettings.m_pathSubstitutions.end(); i++)
{
+ CStdString fromPath;
+ CStdString toPath;
+
if (!reverse)
{
- if (strncmp(strPath.c_str(), i->first.c_str(), HasSlashAtEnd(i->first.c_str()) ? i->first.size()-1 : i->first.size()) == 0)
- {
- if (strPath.size() > i->first.size())
- return URIUtils::AddFileToFolder(i->second, strPath.substr(i->first.size()));
- else
- return i->second;
- }
+ fromPath = i->first; // Fake path
+ toPath = i->second; // Real path
}
else
{
- if (strncmp(strPath.c_str(), i->second.c_str(), HasSlashAtEnd(i->second.c_str()) ? i->second.size()-1 : i->second.size()) == 0)
+ fromPath = i->second; // Real path
+ toPath = i->first; // Fake path
+ }
+
+ if (strncmp(strPath.c_str(), fromPath.c_str(), HasSlashAtEnd(fromPath) ? fromPath.size() - 1 : fromPath.size()) == 0)
+ {
+ if (strPath.size() > fromPath.size())
+ {
+ CStdString strSubPathAndFileName = strPath.substr(fromPath.size());
+ return ChangeBasePath(fromPath, strSubPathAndFileName, toPath); // Fix encoding + slash direction
+ }
+ else
{
- if (strPath.size() > i->second.size())
- return URIUtils::AddFileToFolder(i->first, strPath.substr(i->second.size()));
- else
- return i->first;
+ return toPath;
}
}
}
diff --git a/xbmc/utils/URIUtils.h b/xbmc/utils/URIUtils.h
index 146bf5cd01..cf7ea3f257 100644
--- a/xbmc/utils/URIUtils.h
+++ b/xbmc/utils/URIUtils.h
@@ -68,6 +68,16 @@ public:
static void GetCommonPath(CStdString& strPath, const CStdString& strPath2);
static CStdString GetParentPath(const CStdString& strPath);
static bool GetParentPath(const CStdString& strPath, CStdString& strParent);
+
+ /* \brief Change the base path of a URL: fromPath/fromFile -> toPath/toFile
+ Handles changes in path separator and filename URL encoding if necessary to derive toFile.
+ \param fromPath the base path of the original URL
+ \param fromFile the filename portion of the original URL
+ \param toPath the base path of the resulting URL
+ \return the full path.
+ */
+ static std::string ChangeBasePath(const std::string &fromPath, const std::string &fromFile, const std::string &toPath);
+
static CStdString SubstitutePath(const CStdString& strPath, bool reverse = false);
static bool IsAddonsPath(const CStdString& strFile);
diff --git a/xbmc/utils/test/TestURIUtils.cpp b/xbmc/utils/test/TestURIUtils.cpp
index 7170c46939..9af7f2fc27 100644
--- a/xbmc/utils/test/TestURIUtils.cpp
+++ b/xbmc/utils/test/TestURIUtils.cpp
@@ -178,12 +178,56 @@ TEST_F(TestURIUtils, SubstitutePath)
{
CStdString from, to, ref, var;
- from = "/somepath";
- to = "/someotherpath";
+ from = "C:\\My Videos";
+ to = "https://myserver/some%20other%20path";
g_advancedSettings.m_pathSubstitutions.push_back(std::make_pair(from, to));
- ref = "/someotherpath/to/movie.avi";
- var = URIUtils::SubstitutePath("/somepath/to/movie.avi");
+ from = "/this/path1";
+ to = "/some/other/path2";
+ g_advancedSettings.m_pathSubstitutions.push_back(std::make_pair(from, to));
+
+ from = "davs://otherserver/my%20music%20path";
+ to = "D:\\Local Music\\MP3 Collection";
+ g_advancedSettings.m_pathSubstitutions.push_back(std::make_pair(from, to));
+
+ ref = "https://myserver/some%20other%20path/sub%20dir/movie%20name.avi";
+ var = URIUtils::SubstitutePath("C:\\My Videos\\sub dir\\movie name.avi");
+ EXPECT_STREQ(ref.c_str(), var.c_str());
+
+ ref = "C:\\My Videos\\sub dir\\movie name.avi";
+ var = URIUtils::SubstitutePath("https://myserver/some%20other%20path/sub%20dir/movie%20name.avi", true);
+ EXPECT_STREQ(ref.c_str(), var.c_str());
+
+ ref = "D:\\Local Music\\MP3 Collection\\Phil Collins\\Some CD\\01 - Two Hearts.mp3";
+ var = URIUtils::SubstitutePath("davs://otherserver/my%20music%20path/Phil%20Collins/Some%20CD/01%20-%20Two%20Hearts.mp3");
+ EXPECT_STREQ(ref.c_str(), var.c_str());
+
+ ref = "davs://otherserver/my%20music%20path/Phil%20Collins/Some%20CD/01%20-%20Two%20Hearts.mp3";
+ var = URIUtils::SubstitutePath("D:\\Local Music\\MP3 Collection\\Phil Collins\\Some CD\\01 - Two Hearts.mp3", true);
+ EXPECT_STREQ(ref.c_str(), var.c_str());
+
+ ref = "/some/other/path2/to/movie.avi";
+ var = URIUtils::SubstitutePath("/this/path1/to/movie.avi");
+ EXPECT_STREQ(ref.c_str(), var.c_str());
+
+ ref = "/this/path1/to/movie.avi";
+ var = URIUtils::SubstitutePath("/some/other/path2/to/movie.avi", true);
+ EXPECT_STREQ(ref.c_str(), var.c_str());
+
+ ref = "/no/translation path/";
+ var = URIUtils::SubstitutePath(ref);
+ EXPECT_STREQ(ref.c_str(), var.c_str());
+
+ ref = "/no/translation path/";
+ var = URIUtils::SubstitutePath(ref, true);
+ EXPECT_STREQ(ref.c_str(), var.c_str());
+
+ ref = "c:\\no\\translation path";
+ var = URIUtils::SubstitutePath(ref);
+ EXPECT_STREQ(ref.c_str(), var.c_str());
+
+ ref = "c:\\no\\translation path";
+ var = URIUtils::SubstitutePath(ref, true);
EXPECT_STREQ(ref.c_str(), var.c_str());
}
diff --git a/xbmc/visualizations/OpenGLSpectrum/opengl_spectrum.cpp b/xbmc/visualizations/OpenGLSpectrum/opengl_spectrum.cpp
index a039fc457f..9d0e97f563 100644
--- a/xbmc/visualizations/OpenGLSpectrum/opengl_spectrum.cpp
+++ b/xbmc/visualizations/OpenGLSpectrum/opengl_spectrum.cpp
@@ -33,6 +33,7 @@
#include "addons/include/xbmc_vis_dll.h"
#include <string.h>
+#include <stdlib.h>
#include <math.h>
#include <stdint.h>
@@ -59,16 +60,15 @@
#define glLoadIdentity() vis_shader->LoadIdentity()
#define glFrustum(a,b,c,d,e,f) vis_shader->Frustum(a,b,c,d,e,f)
-GLenum g_mode = GL_TRIANGLES;
-float g_fWaveform[2][512];
-const char *frag = "precision mediump float; \n"
+static GLenum g_mode = GL_TRIANGLES;
+static const char *frag = "precision mediump float; \n"
"varying lowp vec4 m_colour; \n"
"void main () \n"
"{ \n"
" gl_FragColor = m_colour; \n"
"}\n";
-const char *vert = "attribute vec4 m_attrpos;\n"
+static const char *vert = "attribute vec4 m_attrpos;\n"
"attribute vec4 m_attrcol;\n"
"attribute vec4 m_attrcord0;\n"
"attribute vec4 m_attrcord1;\n"
@@ -86,24 +86,24 @@ const char *vert = "attribute vec4 m_attrpos;\n"
" m_cord1 = m_attrcord1;\n"
"}\n";
-CVisGUIShader *vis_shader = NULL;
+static CVisGUIShader *vis_shader = NULL;
#elif defined(HAS_SDL_OPENGL)
#include <GL/glew.h>
-GLenum g_mode = GL_FILL;
+static GLenum g_mode = GL_FILL;
#endif
#define NUM_BANDS 16
-GLfloat x_angle = 20.0, x_speed = 0.0;
-GLfloat y_angle = 45.0, y_speed = 0.5;
-GLfloat z_angle = 0.0, z_speed = 0.0;
-GLfloat heights[16][16], cHeights[16][16], scale;
-GLfloat hSpeed = 0.05;
+static GLfloat x_angle = 20.0, x_speed = 0.0;
+static GLfloat y_angle = 45.0, y_speed = 0.5;
+static GLfloat z_angle = 0.0, z_speed = 0.0;
+static GLfloat heights[16][16], cHeights[16][16], scale;
+static GLfloat hSpeed = 0.05;
#if defined(HAS_SDL_OPENGL)
-void draw_rectangle(GLfloat x1, GLfloat y1, GLfloat z1, GLfloat x2, GLfloat y2, GLfloat z2)
+static void draw_rectangle(GLfloat x1, GLfloat y1, GLfloat z1, GLfloat x2, GLfloat y2, GLfloat z2)
{
if(y1 == y2)
{
@@ -127,7 +127,7 @@ void draw_rectangle(GLfloat x1, GLfloat y1, GLfloat z1, GLfloat x2, GLfloat y2,
}
}
-void draw_bar(GLfloat x_offset, GLfloat z_offset, GLfloat height, GLfloat red, GLfloat green, GLfloat blue )
+static void draw_bar(GLfloat x_offset, GLfloat z_offset, GLfloat height, GLfloat red, GLfloat green, GLfloat blue, int index)
{
GLfloat width = 0.1;
@@ -158,69 +158,105 @@ void draw_bar(GLfloat x_offset, GLfloat z_offset, GLfloat height, GLfloat red, G
#elif defined(HAS_GLES)
-void draw_bar(GLfloat x_offset, GLfloat z_offset, GLfloat height, GLfloat red, GLfloat green, GLfloat blue )
+static GLfloat *m_col;
+static GLfloat *m_ver;
+static GLushort *m_idx;
+
+static void draw_bar(GLfloat x_offset, GLfloat z_offset, GLfloat height, GLfloat red, GLfloat green, GLfloat blue, int index)
{
+ if (!m_col || !m_ver || !m_idx)
+ return;
+
// avoid zero sized bars, which results in overlapping triangles of same depth and display artefacts
height = std::max(height, 1e-3f);
- GLfloat col[] = {
- red * 0.1f, green * 0.1f, blue * 0.1f,
- red * 0.2f, green * 0.2f, blue * 0.2f,
- red * 0.3f, green * 0.3f, blue * 0.3f,
- red * 0.4f, green * 0.4f, blue * 0.4f,
- red * 0.5f, green * 0.5f, blue * 0.5f,
- red * 0.6f, green * 0.6f, blue * 0.6f,
- red * 0.7f, green * 0.7f, blue * 0.7f,
- red * 0.8f, green * 0.8f, blue *0.8f
- };
- GLfloat ver[] = {
- x_offset + 0.0f, 0.0f, z_offset + 0.0f,
- x_offset + 0.1f, 0.0f, z_offset + 0.0f,
- x_offset + 0.1f, 0.0f, z_offset + 0.1f,
- x_offset + 0.0f, 0.0f, z_offset + 0.1f,
- x_offset + 0.0f, height, z_offset + 0.0f,
- x_offset + 0.1f, height, z_offset + 0.0f,
- x_offset + 0.1f, height, z_offset + 0.1f,
- x_offset + 0.0f, height, z_offset + 0.1f
- };
-
- GLubyte idx[] = {
- // Bottom
- 0, 1, 2,
- 0, 2, 3,
- // Left
- 0, 4, 7,
- 0, 7, 3,
- // Back
- 3, 7, 6,
- 3, 6, 2,
- // Right
- 1, 5, 6,
- 1, 6, 2,
- // Front
- 0, 4, 5,
- 0, 5, 1,
- // Top
- 4, 5, 6,
- 4, 6, 7
- };
-
- GLint posLoc = vis_shader->GetPosLoc();
- GLint colLoc = vis_shader->GetColLoc();
-
- glVertexAttribPointer(colLoc, 3, GL_FLOAT, 0, 0, col);
- glVertexAttribPointer(posLoc, 3, GL_FLOAT, 0, 0, ver);
-
- glEnableVertexAttribArray(posLoc);
- glEnableVertexAttribArray(colLoc);
-
- glDrawElements(g_mode, 36, GL_UNSIGNED_BYTE, idx);
-
- glDisableVertexAttribArray(posLoc);
- glDisableVertexAttribArray(colLoc);
+ GLfloat *ver = m_ver + 3 * 8 * index;
+ // just need to update the height vertex, all else is the same
+ for (int i=0; i<8; i++)
+ {
+ ver[1] = (((i+0)>>2)&1) * height;
+ ver += 3;
+ }
+ // on last index, draw the object
+ if (index == 16*16-1)
+ {
+ GLint posLoc = vis_shader->GetPosLoc();
+ GLint colLoc = vis_shader->GetColLoc();
+
+ glVertexAttribPointer(colLoc, 3, GL_FLOAT, 0, 0, m_col);
+ glVertexAttribPointer(posLoc, 3, GL_FLOAT, 0, 0, m_ver);
+
+ glEnableVertexAttribArray(posLoc);
+ glEnableVertexAttribArray(colLoc);
+
+ glDrawElements(g_mode, 16*16*36, GL_UNSIGNED_SHORT, m_idx);
+
+ glDisableVertexAttribArray(posLoc);
+ glDisableVertexAttribArray(colLoc);
+ }
+}
+
+static void init_bars(void)
+{
+ if (!m_col || !m_ver || !m_idx)
+ return;
+
+ GLfloat x_offset, z_offset, r_base, b_base;
+ for(int y = 0; y < 16; y++)
+ {
+ z_offset = -1.6 + ((15 - y) * 0.2);
+
+ b_base = y * (1.0 / 15);
+ r_base = 1.0 - b_base;
+
+ for(int x = 0; x < 16; x++)
+ {
+ x_offset = -1.6 + ((float)x * 0.2);
+
+ GLfloat red = r_base - (float(x) * (r_base / 15.0));
+ GLfloat green = (float)x * (1.0 / 15);
+ GLfloat blue = b_base;
+ int index = 16*y+x;
+ GLfloat *col = m_col + 3 * 8 * index;
+ for (int i=0; i<8; i++)
+ {
+ float scale = 0.1f * i;
+ *col++ = red * scale;
+ *col++ = green * scale;
+ *col++ = blue * scale;
+ }
+ GLfloat *ver = m_ver + 3 * 8 * index;
+ for (int i=0; i<8; i++)
+ {
+ *ver++ = x_offset + (((i+1)>>1)&1) * 0.1f;
+ *ver++ = 0; // height - filled in later
+ *ver++ = z_offset + (((i+0)>>1)&1) * 0.1f;
+ }
+ GLushort *idx = m_idx + 36 * index;
+ GLushort startidx = 8 * index;
+ // Bottom
+ *idx++ = startidx + 0; *idx++ = startidx + 1; *idx++ = startidx + 2;
+ *idx++ = startidx + 0; *idx++ = startidx + 2; *idx++ = startidx + 3;
+ // Left
+ *idx++ = startidx + 0; *idx++ = startidx + 4; *idx++ = startidx + 7;
+ *idx++ = startidx + 0; *idx++ = startidx + 7; *idx++ = startidx + 3;
+ // Back
+ *idx++ = startidx + 3; *idx++ = startidx + 7; *idx++ = startidx + 6;
+ *idx++ = startidx + 3; *idx++ = startidx + 6; *idx++ = startidx + 2;
+ // Right
+ *idx++ = startidx + 1; *idx++ = startidx + 5; *idx++ = startidx + 6;
+ *idx++ = startidx + 1; *idx++ = startidx + 6; *idx++ = startidx + 2;
+ // Front
+ *idx++ = startidx + 0; *idx++ = startidx + 4; *idx++ = startidx + 5;
+ *idx++ = startidx + 0; *idx++ = startidx + 5; *idx++ = startidx + 1;
+ // Top
+ *idx++ = startidx + 4; *idx++ = startidx + 5; *idx++ = startidx + 6;
+ *idx++ = startidx + 4; *idx++ = startidx + 6; *idx++ = startidx + 7;
+ }
+ }
}
#endif
-void draw_bars(void)
+static void draw_bars(void)
{
int x,y;
GLfloat x_offset, z_offset, r_base, b_base;
@@ -254,7 +290,7 @@ void draw_bars(void)
}
draw_bar(x_offset, z_offset,
cHeights[y][x], r_base - (float(x) * (r_base / 15.0)),
- (float)x * (1.0 / 15), b_base);
+ (float)x * (1.0 / 15), b_base, 16*y+x);
}
}
glEnd();
@@ -283,6 +319,10 @@ ADDON_STATUS ADDON_Create(void* hdl, void* props)
delete vis_shader;
return ADDON_STATUS_UNKNOWN;
}
+ m_col = (GLfloat *)malloc(16*16*3*8 * sizeof(GLfloat *));
+ m_ver = (GLfloat *)malloc(16*16*3*8 * sizeof(GLfloat *));
+ m_idx = (GLushort *)malloc(16*16*36 * sizeof(GLushort *));
+ init_bars();
#endif
scale = 1.0 / log(256.0);
@@ -456,6 +496,12 @@ extern "C" void ADDON_Destroy()
vis_shader->Free();
delete vis_shader;
}
+ free(m_col);
+ free(m_ver);
+ free(m_idx);
+ m_col = NULL;
+ m_ver = NULL;
+ m_idx = NULL;
#endif
}