From b8f87b0bf8795dbf815311f825a7f9f6ca5f42ff Mon Sep 17 00:00:00 2001
From: Gerasim Troeglazov <3dEyes@gmail.com>
Date: Sat, 18 Dec 2021 21:36:25 +1000
Subject: Add haiku support


diff --git a/CMakeLists.txt b/CMakeLists.txt
index 210b1fa..7cfa9ee 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -78,6 +78,9 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
 elseif(ANDROID)
     set(DEFAULT_ALSA OFF)
     set(DEFAULT_PORTAUDIO OFF)
+elseif(HAIKU)
+    set(DEFAULT_ALSA OFF)
+    set(DEFAULT_PORTAUDIO OFF)
 else()
     set(DEFAULT_ALSA OFF)
     set(DEFAULT_PORTAUDIO ON)
@@ -122,7 +125,7 @@ endif()
 option(USE_GLSLC "Compile Vulkan shaders" OFF)
 add_feature_info(GLSLC USE_GLSLC "Compile Vulkan shaders")
 
-if(NOT WIN32 AND NOT APPLE AND NOT ANDROID)
+if(NOT WIN32 AND NOT APPLE AND NOT ANDROID AND NOT HAIKU)
     option(USE_FREEDESKTOP_NOTIFICATIONS "Use Freedesktop notifications" ON)
     add_feature_info("Freedesktop notifications" USE_FREEDESKTOP_NOTIFICATIONS "Use Freedesktop notifications")
 
@@ -166,7 +169,7 @@ else()
     set(USE_YOUTUBEDL OFF)
 endif()
 
-if(USE_EXTENSIONS AND NOT WIN32 AND NOT APPLE AND NOT ANDROID)
+if(USE_EXTENSIONS AND NOT WIN32 AND NOT APPLE AND NOT ANDROID AND NOT HAIKU)
     option(USE_MPRIS2 "Build Extensions with MPRIS2 support" ON)
     add_feature_info(MPRIS2 USE_MPRIS2 "Build Extensions with MPRIS2 support")
 endif()
diff --git a/src/gui/Main.cpp b/src/gui/Main.cpp
index 1360cba..73d4cd8 100644
--- a/src/gui/Main.cpp
+++ b/src/gui/Main.cpp
@@ -606,6 +606,10 @@ int main(int argc, char *argv[])
 
     qputenv("QT_QPA_UPDATE_IDLE_TIME", "0");
 
+#ifdef Q_OS_HAIKU
+	setenv("HOME", "/boot/home", 1);
+#endif
+
     QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
 #ifndef USE_OPENGL
     QGuiApplication::setAttribute(Qt::AA_ForceRasterWidgets);
@@ -707,7 +711,7 @@ int main(int argc, char *argv[])
     }
     if (!cmakeBuildFound)
     {
-#if !defined Q_OS_WIN && !defined Q_OS_MACOS && !defined Q_OS_ANDROID
+#if !defined Q_OS_WIN && !defined Q_OS_MACOS && !defined Q_OS_ANDROID && !defined Q_OS_HAIKU
         sharePath = QCoreApplication::applicationDirPath() + "/../share/qmplay2";
         libPath = QMPlay2CoreClass::getLibDir();
         if (libPath.isEmpty() || !QDir(libPath).exists("qmplay2"))
@@ -913,5 +917,9 @@ int main(int argc, char *argv[])
     if (canDeleteApp)
 #endif
         delete qApp;
+
+#ifdef Q_OS_HAIKU
+	kill(::getpid(), SIGKILL);
+#endif
     return 0;
 }
diff --git a/src/gui/MainWidget.cpp b/src/gui/MainWidget.cpp
index 7aa180a..a50e01c 100644
--- a/src/gui/MainWidget.cpp
+++ b/src/gui/MainWidget.cpp
@@ -150,7 +150,7 @@ MainWidget::MainWidget(QList<QPair<QString, QString>> &arguments)
         setIconSize({22, 22});
 
     SettingsWidget::InitSettings();
-#ifndef Q_OS_ANDROID
+#if !defined Q_OS_ANDROID && !defined Q_OS_HAIKU
     settings.init("MainWidget/WidgetsLocked", false);
 #else
     settings.init("MainWidget/WidgetsLocked", true);
diff --git a/src/modules/CMakeLists.txt b/src/modules/CMakeLists.txt
index 832b774..216e162 100644
--- a/src/modules/CMakeLists.txt
+++ b/src/modules/CMakeLists.txt
@@ -7,6 +7,9 @@ if(WIN32)
 elseif(APPLE)
     set(MODULES_INSTALL_PATH "${CMAKE_INSTALL_LIBDIR}/modules")
     set(QMPLAY2_MODULE SHARED) # otherwise CMake uses ".so" extension
+elseif(HAIKU)
+    set(MODULES_INSTALL_PATH "modules")
+    set(QMPLAY2_MODULE MODULE)
 else()
     set(MODULES_INSTALL_PATH "${CMAKE_INSTALL_LIBDIR}/qmplay2/modules")
     set(QMPLAY2_MODULE MODULE)
@@ -58,6 +61,10 @@ if(USE_PIPEWIRE)
     add_subdirectory(PipeWire)
 endif()
 
+if(HAIKU)
+    add_subdirectory(MediaKit)
+endif()
+
 if(USE_XVIDEO)
     add_subdirectory(XVideo)
 endif()
diff --git a/src/modules/MediaKit/CMakeLists.txt b/src/modules/MediaKit/CMakeLists.txt
new file mode 100644
index 0000000..f94e365
--- /dev/null
+++ b/src/modules/MediaKit/CMakeLists.txt
@@ -0,0 +1,36 @@
+cmake_minimum_required(VERSION 3.1)
+project(MediaKit)
+
+set(MediaKit_HDR
+    MediaKit.hpp
+    MediaKitWriter.hpp
+    RingBuffer.hpp
+    SndPlayer.hpp
+)
+
+set(MediaKit_SRC
+    MediaKit.cpp
+    MediaKitWriter.cpp
+    RingBuffer.cpp
+    SndPlayer.cpp
+)
+
+set(MediaKit_RESOURCES
+    icon.qrc
+)
+
+include_directories(../../qmplay2/headers)
+
+add_library(${PROJECT_NAME} ${QMPLAY2_MODULE}
+    ${MediaKit_HDR}
+    ${MediaKit_SRC}
+    ${MediaKit_RESOURCES}
+)
+
+target_link_libraries(${PROJECT_NAME}
+    be
+    media
+    libqmplay2
+)
+
+install(TARGETS ${PROJECT_NAME} LIBRARY DESTINATION ${MODULES_INSTALL_PATH})
diff --git a/src/modules/MediaKit/MediaKit.cpp b/src/modules/MediaKit/MediaKit.cpp
new file mode 100644
index 0000000..2fee2d5
--- /dev/null
+++ b/src/modules/MediaKit/MediaKit.cpp
@@ -0,0 +1,65 @@
+#include <MediaKit.hpp>
+#include <MediaKitWriter.hpp>
+
+MediaKit::MediaKit() :
+	Module( "MediaKit" )
+{
+	m_icon = QIcon( ":/MediaKit" );
+
+	init( "WriterEnabled", true );
+	init( "Delay", 0.2 );
+}
+
+QList< MediaKit::Info > MediaKit::getModulesInfo( const bool showDisabled ) const
+{
+	QList< Info > modulesInfo;
+	if ( showDisabled || getBool( "WriterEnabled" ) )
+		modulesInfo += Info( MediaKitWriterName, WRITER, QStringList( "audio" ) );
+	return modulesInfo;
+}
+void *MediaKit::createInstance( const QString &name )
+{
+	if ( name == MediaKitWriterName && getBool( "WriterEnabled" ) )
+		return new MediaKitWriter( *this );
+	return NULL;
+}
+
+MediaKit::SettingsWidget *MediaKit::getSettingsWidget()
+{
+	return new ModuleSettingsWidget( *this );
+}
+
+QMPLAY2_EXPORT_MODULE( MediaKit )
+
+/**/
+
+#include <QDoubleSpinBox>
+#include <QGridLayout>
+#include <QCheckBox>
+#include <QLabel>
+
+ModuleSettingsWidget::ModuleSettingsWidget( Module &module ) :
+	Module::SettingsWidget( module )
+{
+	enabledB = new QCheckBox( tr( "Enabled" ) );
+	enabledB->setChecked( sets().getBool( "WriterEnabled" ) );
+
+	QLabel *delayL = new QLabel( tr( "Delay" ) + ": " );
+
+	delayB = new QDoubleSpinBox;
+	delayB->setRange( 0.01, 1.0 );
+	delayB->setSingleStep( 0.01 );
+	delayB->setSuffix( " " + tr( "sec" ) );
+	delayB->setValue( sets().getDouble( "Delay" ) );
+
+	QGridLayout *layout = new QGridLayout( this );
+	layout->addWidget( enabledB, 0, 0, 1, 2 );
+	layout->addWidget( delayL, 1, 0, 1, 1 );
+	layout->addWidget( delayB, 1, 1, 1, 1 );
+}
+
+void ModuleSettingsWidget::saveSettings()
+{
+	sets().set( "WriterEnabled", enabledB->isChecked() );
+	sets().set( "Delay", delayB->value() );
+}
diff --git a/src/modules/MediaKit/MediaKit.hpp b/src/modules/MediaKit/MediaKit.hpp
new file mode 100644
index 0000000..ed89e32
--- /dev/null
+++ b/src/modules/MediaKit/MediaKit.hpp
@@ -0,0 +1,33 @@
+#pragma once
+
+#include <Module.hpp>
+
+class MediaKit : public Module
+{
+public:
+	MediaKit();
+private:
+	QList< Info > getModulesInfo( const bool ) const;
+	void *createInstance( const QString & );
+
+	SettingsWidget *getSettingsWidget();
+};
+
+/**/
+
+#include <QCoreApplication>
+
+class QDoubleSpinBox;
+class QCheckBox;
+
+class ModuleSettingsWidget : public Module::SettingsWidget
+{
+	Q_DECLARE_TR_FUNCTIONS( ModuleSettingsWidget )
+public:
+	ModuleSettingsWidget( Module & );
+private:
+	void saveSettings();
+
+	QCheckBox *enabledB;
+	QDoubleSpinBox *delayB;
+};
diff --git a/src/modules/MediaKit/MediaKitWriter.cpp b/src/modules/MediaKit/MediaKitWriter.cpp
new file mode 100644
index 0000000..a86e584
--- /dev/null
+++ b/src/modules/MediaKit/MediaKitWriter.cpp
@@ -0,0 +1,85 @@
+#include <MediaKitWriter.hpp>
+#include <QMPlay2Core.hpp>
+
+MediaKitWriter::MediaKitWriter( Module &module ) :
+	err( false )
+{
+	addParam( "delay" );
+	addParam( "chn" );
+	addParam( "rate" );
+
+	SetModule( module );
+}
+
+bool MediaKitWriter::set()
+{
+	if ( player.delay != sets().getDouble( "Delay" ) )
+	{
+		player.delay = sets().getDouble( "Delay" );
+		return false;
+	}
+	return sets().getBool( "WriterEnabled" );
+}
+
+bool MediaKitWriter::readyWrite() const
+{
+	return !err && player.isOpen();
+}
+
+bool MediaKitWriter::processParams( bool * )
+{
+	bool resetAudio = false;
+
+	uchar chn = getParam( "chn" ).toUInt();
+	if ( player.channels != chn )
+	{
+		resetAudio = true;
+		player.channels = chn;
+	}
+	uint rate = getParam( "rate" ).toUInt();
+	if ( player.sample_rate != rate )
+	{
+		resetAudio = true;
+		player.sample_rate = rate;
+	}
+
+	if ( resetAudio || err )
+	{
+		player.stop();
+		err = !player.start();
+		if ( !err )
+			modParam( "delay", player.delay );
+		else
+			QMPlay2Core.logError( "MediaKitWriter :: " + tr ( "Cannot open audio output stream" ) );
+	}
+
+	return readyWrite();
+}
+qint64 MediaKitWriter::write( const QByteArray &arr )
+{
+	if ( !arr.size() || !readyWrite() )
+		return 0;
+
+	err = !player.write( arr );
+	if ( err )
+	{
+		QMPlay2Core.logError( "MediaKitWriter :: " + tr ( "Playback error" ) );
+		return 0;
+	}
+
+	return arr.size();
+}
+
+qint64 MediaKitWriter::size() const
+{
+	return -1;
+}
+QString MediaKitWriter::name() const
+{
+	return MediaKitWriterName;
+}
+
+bool MediaKitWriter::open()
+{
+	return player.isOK();
+}
diff --git a/src/modules/MediaKit/MediaKitWriter.hpp b/src/modules/MediaKit/MediaKitWriter.hpp
new file mode 100644
index 0000000..28fa249
--- /dev/null
+++ b/src/modules/MediaKit/MediaKitWriter.hpp
@@ -0,0 +1,30 @@
+#include <Writer.hpp>
+#include <SndPlayer.hpp>
+
+#include <QCoreApplication>
+
+class MediaKitWriter : public Writer
+{
+	Q_DECLARE_TR_FUNCTIONS( MediaKitWriter )
+public:
+	MediaKitWriter( Module & );
+private:
+	bool set();
+
+	bool readyWrite() const;
+
+	bool processParams( bool *paramsCorrected );
+	qint64 write( const QByteArray & );
+
+	qint64 size() const;
+	QString name() const;
+
+	bool open();
+
+	/**/
+
+	SndPlayer player;
+	bool err;
+};
+
+#define MediaKitWriterName "MediaKit Writer"
diff --git a/src/modules/MediaKit/RingBuffer.cpp b/src/modules/MediaKit/RingBuffer.cpp
new file mode 100644
index 0000000..915becc
--- /dev/null
+++ b/src/modules/MediaKit/RingBuffer.cpp
@@ -0,0 +1,129 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "RingBuffer.hpp"
+
+RingBuffer::RingBuffer( int size )
+{
+	 initialized = false;
+     Buffer = new unsigned char[size];
+     if(Buffer!=NULL) {
+     	memset( Buffer, 0, size );
+	    BufferSize = size;     	
+     } else {
+     	BufferSize = 0;
+     }
+     reader = 0;
+     writer = 0;
+     writeBytesAvailable = size;
+     if((locker=create_sem(1,"locker")) >= B_OK) {
+     	initialized = true;
+     } else {
+     	if(Buffer!=NULL) {
+     		delete[] Buffer;     		
+     	}
+     }
+}
+
+RingBuffer::~RingBuffer( )
+{
+	 if(initialized) {
+     	delete[] Buffer;
+     	delete_sem(locker);
+	 }
+}
+
+bool 
+RingBuffer::Empty( void )
+{
+     memset( Buffer, 0, BufferSize );
+     reader = 0;
+     writer = 0;
+     writeBytesAvailable = BufferSize;
+     return true;
+}
+
+int 
+RingBuffer::Read( unsigned char *data, int size )
+{	
+	 acquire_sem(locker);
+	 
+     if( data == 0 || size <= 0 || writeBytesAvailable == BufferSize ) {
+     	 release_sem(locker);
+         return 0;
+     }
+
+     int readBytesAvailable = BufferSize - writeBytesAvailable;
+
+     if( size > readBytesAvailable ) {
+         size = readBytesAvailable;
+     }
+
+     if(size > BufferSize - reader) {
+         int len = BufferSize - reader;
+         memcpy(data, Buffer + reader, len);
+         memcpy(data + len, Buffer, size-len);
+     } else {
+         memcpy(data, Buffer + reader, size);
+     }
+
+     reader = (reader + size) % BufferSize;
+     writeBytesAvailable += size;
+	 
+	 release_sem(locker);
+     return size;
+}
+
+int 
+RingBuffer::Write( unsigned char *data, int size )
+{
+	 acquire_sem(locker);
+	 
+     if( data == 0 || size <= 0 || writeBytesAvailable == 0 ) {
+     	 release_sem(locker);
+         return 0;
+     }
+
+     if( size > writeBytesAvailable ) {
+         size = writeBytesAvailable;
+     }
+
+     if(size > BufferSize - writer) {
+         int len = BufferSize - writer;
+         memcpy(Buffer + writer, data, len);
+         memcpy(Buffer, data+len, size-len);
+     } else {
+         memcpy(Buffer + writer, data, size);
+     }
+
+     writer = (writer + size) % BufferSize;
+     writeBytesAvailable -= size;
+
+	 release_sem(locker);	 
+     return size;
+}
+
+int 
+RingBuffer::GetSize( void )
+{
+     return BufferSize;
+}
+
+int 
+RingBuffer::GetWriteAvailable( void )
+{
+     return writeBytesAvailable;
+}
+
+int 
+RingBuffer::GetReadAvailable( void )
+{
+     return BufferSize - writeBytesAvailable;
+}
+
+status_t 
+RingBuffer::InitCheck( void )
+{
+	return initialized?B_OK:B_ERROR;
+}
diff --git a/src/modules/MediaKit/RingBuffer.hpp b/src/modules/MediaKit/RingBuffer.hpp
new file mode 100644
index 0000000..4715632
--- /dev/null
+++ b/src/modules/MediaKit/RingBuffer.hpp
@@ -0,0 +1,31 @@
+#ifndef __RING_BUFFER_H__
+#define __RING_BUFFER_H__
+
+#include <OS.h>
+
+class RingBuffer {
+
+public:
+     RingBuffer(int size);
+     ~RingBuffer();
+     int Read( unsigned char* dataPtr, int numBytes );
+     int Write( unsigned char *dataPtr, int numBytes );
+     
+     bool Empty( void );
+     int GetSize( );
+     int GetWriteAvailable( );
+     int GetReadAvailable( );
+     status_t InitCheck( );
+private:
+     unsigned char *Buffer;
+     int BufferSize;
+     int reader;
+     int writer;
+     int writeBytesAvailable;
+     
+     sem_id locker;
+     
+     bool 	initialized;
+};
+
+#endif
diff --git a/src/modules/MediaKit/SndPlayer.cpp b/src/modules/MediaKit/SndPlayer.cpp
new file mode 100644
index 0000000..dafa355
--- /dev/null
+++ b/src/modules/MediaKit/SndPlayer.cpp
@@ -0,0 +1,103 @@
+#include <SndPlayer.hpp>
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <SoundPlayer.h>
+
+
+static void proc(void *cookie, void *buffer, size_t len, const media_raw_audio_format &format)
+{
+	RingBuffer *ring = (RingBuffer*)cookie;
+	unsigned char* ptr = (unsigned char*)buffer;
+	
+	int readed = ring->Read(ptr,len);
+	
+	if(readed <len)
+		memset(ptr+readed, 0, len - readed);
+}
+
+SndPlayer::SndPlayer()
+{	
+	channels = sample_rate = delay = 0;
+	player = NULL;
+	_isOK = true;	
+}
+
+bool SndPlayer::start()
+{
+	size_t gSoundBufferSize = 8192 * sizeof(float);
+		
+	media_raw_audio_format form = {
+		sample_rate,
+		channels,
+		media_raw_audio_format::B_AUDIO_FLOAT,
+		B_MEDIA_LITTLE_ENDIAN,
+		gSoundBufferSize
+	};
+	
+	ring = new RingBuffer(gSoundBufferSize * 3);
+	if(ring->InitCheck() != B_OK) {
+		delete ring; ring = 0;
+		return false;
+	}
+			
+	player = new BSoundPlayer(&form, "QMPlay2_BSoundPlayer", proc, NULL, (void*)ring);
+	
+	if(player->InitCheck() != B_OK) {
+		delete player;
+		player = NULL;
+		return false;
+	}
+	
+	player->Start();
+	player->SetHasData(true);	
+
+	_isOK = true;
+
+	return player;
+}
+void SndPlayer::stop()
+{
+	if ( player )
+	{
+		if(player) {
+			player->Stop();
+			delete player;
+			delete ring;
+		}
+	
+		player = NULL;
+		ring = NULL;
+	}	
+}
+
+double SndPlayer::getLatency()
+{
+	double lat = player->Latency() / (ring->GetSize()*4.0);	
+
+	return lat;
+}
+
+bool SndPlayer::write( const QByteArray &arr )
+{
+	int s = arr.size();
+	while ( s > 0 && s % 4 )
+		s--;
+	if ( s <= 0 )
+		return false;
+
+	int len=s;
+
+	unsigned char *src_ptr = (unsigned char *)arr.data();
+	
+	for(;;) {
+			int len2 = ring->Write(src_ptr,len);
+			if(len2 == len)break;
+			len -= len2;
+			src_ptr += len2;
+			snooze(100);
+	}
+		
+	return true;
+}
diff --git a/src/modules/MediaKit/SndPlayer.hpp b/src/modules/MediaKit/SndPlayer.hpp
new file mode 100644
index 0000000..63709b4
--- /dev/null
+++ b/src/modules/MediaKit/SndPlayer.hpp
@@ -0,0 +1,49 @@
+#ifndef PULSE_HPP
+#define PULSE_HPP
+
+#include <QByteArray>
+
+#include <SoundPlayer.h>
+
+#include <Window.h>
+#include <View.h>
+#include <TextControl.h>
+
+#include "RingBuffer.hpp"
+
+class SndPlayer
+{
+public:
+	SndPlayer();
+	inline ~SndPlayer()
+	{
+		stop();
+	}
+
+	inline bool isOK() const
+	{
+		return _isOK;
+	}
+	inline bool isOpen() const
+	{
+		return player;
+	}
+
+	bool start();
+	void stop();
+
+	double getLatency();
+
+	bool write( const QByteArray & );
+
+	double delay;
+	uchar channels;
+	float sample_rate;
+		
+private:
+	bool _isOK;
+	BSoundPlayer *player;
+	RingBuffer *ring;
+};
+
+#endif
diff --git a/src/modules/MediaKit/icon.qrc b/src/modules/MediaKit/icon.qrc
new file mode 100644
index 0000000..24b4ebd
--- /dev/null
+++ b/src/modules/MediaKit/icon.qrc
@@ -0,0 +1,3 @@
+<RCC><qresource>
+	<file alias="MediaKit">MediaKit.png</file>
+</qresource></RCC>
diff --git a/src/qmplay2/IPC_Unix.cpp b/src/qmplay2/IPC_Unix.cpp
index bac1b16..2bc3175 100644
--- a/src/qmplay2/IPC_Unix.cpp
+++ b/src/qmplay2/IPC_Unix.cpp
@@ -98,7 +98,7 @@ bool IPCSocket::open(QIODevice::OpenMode mode)
 
     if (m_priv->fd > 0)
     {
-        const unsigned long on = 1;
+        unsigned long on = 1;
         ioctl(m_priv->fd, FIONBIO, &on);
         m_priv->socketNotifier = new QSocketNotifier(m_priv->fd, QSocketNotifier::Read, this);
         connect(m_priv->socketNotifier, SIGNAL(activated(int)), this, SLOT(socketReadActive()));
diff --git a/src/qmplay2/QMPlay2Core.cpp b/src/qmplay2/QMPlay2Core.cpp
index 5cf15b9..aacaade 100644
--- a/src/qmplay2/QMPlay2Core.cpp
+++ b/src/qmplay2/QMPlay2Core.cpp
@@ -45,7 +45,7 @@
     #include <powrprof.h>
 #elif defined Q_OS_MACOS
     #include <QOperatingSystemVersion>
-#elif !defined Q_OS_ANDROID
+#elif !defined Q_OS_ANDROID && !defined Q_OS_HAIKU
     #include <QDBusConnection>
     #include <QDBusInterface>
 #endif
@@ -243,7 +243,7 @@ void QMPlay2CoreClass::init(bool loadModules, bool modulesInSubdirs, const QStri
     }
     else
     {
-#if defined(Q_OS_WIN)
+#if defined(Q_OS_WIN) || defined(Q_OS_HAIKU)
         settingsDir = QFileInfo(QSettings(QSettings::IniFormat, QSettings::UserScope, QString()).fileName()).absolutePath() + "/QMPlay2/";
 #elif defined(Q_OS_MACOS)
         settingsDir = Functions::cleanPath(QStandardPaths::standardLocations(QStandardPaths::AppDataLocation).value(0));
@@ -491,6 +491,11 @@ QStringList QMPlay2CoreClass::getModules(const QString &type, int typeLen) const
 #elif defined Q_OS_WIN
     if (type == "videoWriters")
         defaultModules << "OpenGL 2" << "DirectDraw";
+#elif defined Q_OS_HAIKU
+	if ( type == "videoWriters" )
+		defaultModules << "QPainter";
+	else if ( type == "audioWriters" )
+		defaultModules << "MediaKit";
 #endif
     if (type == "decoders")
         defaultModules << "FFmpeg Decoder";
diff --git a/src/qmplay2/YouTubeDL.cpp b/src/qmplay2/YouTubeDL.cpp
index 5659018..63256fa 100644
--- a/src/qmplay2/YouTubeDL.cpp
+++ b/src/qmplay2/YouTubeDL.cpp
@@ -37,9 +37,13 @@ static QMutex g_mutex(QMutex::Recursive);
 
 QString YouTubeDL::getFilePath()
 {
+#ifdef Q_OS_HAIKU
+    return "/bin/yt-dlp"
+#else
     return QMPlay2Core.getSettingsDir() + "yt-dlp"
 #ifdef Q_OS_WIN
     "_x86.exe"
+#endif
 #endif
     ;
 }
@@ -258,6 +262,9 @@ void YouTubeDL::abort()
 
 bool YouTubeDL::prepare()
 {
+#ifdef Q_OS_HAIKU
+	return true;
+#endif
 #ifdef Q_OS_ANDROID
     return false;
 #endif
@@ -304,6 +311,9 @@ bool YouTubeDL::prepare()
 
 bool YouTubeDL::download()
 {
+#if defined(Q_OS_HAIKU)
+	return true;
+#endif
     // Mutex must be locked here
 
     const QString downloadUrl = "https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp"
@@ -357,6 +367,9 @@ bool YouTubeDL::download()
 }
 bool YouTubeDL::update()
 {
+#if defined(Q_OS_HAIKU)
+	return true;
+#endif
     // Mutex must be locked here
 
     qDebug() << "\"youtube-dl\" updates will be checked";
@@ -408,7 +421,7 @@ bool YouTubeDL::update()
 
 void YouTubeDL::ensureExecutable()
 {
-#ifndef Q_OS_WIN
+#if !defined(Q_OS_WIN) && !defined(Q_OS_HAIKU)
     if (!QFileInfo(m_ytDlPath).isExecutable())
     {
         QFile file(m_ytDlPath);
-- 
2.30.2


From ec53a2afe9e2e59c2322f591a65894bd2fecadd6 Mon Sep 17 00:00:00 2001
From: Jerome Duval <jerome.duval@gmail.com>
Date: Tue, 22 Feb 2022 16:52:40 +0100
Subject: ffmpeg5 build fix


diff --git a/src/modules/CUVID/CuvidDec.cpp b/src/modules/CUVID/CuvidDec.cpp
index 65a7b8d..b503ffb 100644
--- a/src/modules/CUVID/CuvidDec.cpp
+++ b/src/modules/CUVID/CuvidDec.cpp
@@ -431,7 +431,7 @@ bool CuvidDec::open(StreamInfo &streamInfo)
     if (streamInfo.codec_type != AVMEDIA_TYPE_VIDEO)
         return false;
 
-    AVCodec *avCodec = avcodec_find_decoder_by_name(streamInfo.codec_name);
+    auto avCodec = const_cast<AVCodec *>(avcodec_find_decoder_by_name(streamInfo.codec_name));
     if (!avCodec)
         return false;
 
diff --git a/src/modules/CUVID/CuvidDec.hpp b/src/modules/CUVID/CuvidDec.hpp
index 972cbb5..6f7dc68 100644
--- a/src/modules/CUVID/CuvidDec.hpp
+++ b/src/modules/CUVID/CuvidDec.hpp
@@ -26,6 +26,9 @@
 #include <QCoreApplication>
 #include <QQueue>
 
+extern "C" {
+	#include <libavcodec/bsf.h>
+}
 class CuvidHWInterop;
 class VideoWriter;
 
diff --git a/src/modules/FFmpeg/FFDec.cpp b/src/modules/FFmpeg/FFDec.cpp
index 0b2dae2..571465a 100644
--- a/src/modules/FFmpeg/FFDec.cpp
+++ b/src/modules/FFmpeg/FFDec.cpp
@@ -70,7 +70,7 @@ void FFDec::clearFrames()
 
 AVCodec *FFDec::init(StreamInfo &streamInfo)
 {
-    AVCodec *codec = avcodec_find_decoder_by_name(streamInfo.codec_name);
+    auto codec = const_cast<AVCodec*>(avcodec_find_decoder_by_name(streamInfo.codec_name));
     if (codec)
     {
         codec_ctx = avcodec_alloc_context3(codec);
diff --git a/src/modules/FFmpeg/FormatContext.cpp b/src/modules/FFmpeg/FormatContext.cpp
index 0996f9a..c241e7b 100644
--- a/src/modules/FFmpeg/FormatContext.cpp
+++ b/src/modules/FFmpeg/FormatContext.cpp
@@ -687,7 +687,7 @@ bool FormatContext::open(const QString &_url, const QString &param)
         if (scheme != "rtsp")
         {
             // It is needed for QMPlay2 schemes like "alsa://", "v4l2://", etc.
-            inputFmt = av_find_input_format(scheme);
+            inputFmt = const_cast<AVInputFormat*>(av_find_input_format(scheme));
             if (inputFmt)
                 url = _url.right(_url.length() - scheme.length() - 3);
         }
-- 
2.30.2

