From 73662e183cbab1e641c4460b74b0871ce1d94b21 Mon Sep 17 00:00:00 2001
From: Gerasim Troeglazov <3dEyes@gmail.com>
Date: Wed, 27 Jan 2021 16:32:03 +1000
Subject: Add Haiku support


diff --git a/bin/override.c b/bin/override.c
index fb4608c..9c7c085 100644
--- a/bin/override.c
+++ b/bin/override.c
@@ -125,6 +125,8 @@ static void *getsym (const char *name)
  *
  * Some evil libraries modify the environment. We currently ignore the calls as
  * they could crash the process. This may cause funny behaviour though. */
+#ifndef __HAIKU__
+//not working
 int putenv (char *str)
 {
     if (override)
@@ -135,6 +137,7 @@ int putenv (char *str)
     return CALL(putenv, str);
 }
 
+#endif
 int setenv (const char *name, const char *value, int overwrite)
 {
     if (override)
diff --git a/compat/recvmsg.c b/compat/recvmsg.c
index c037ab9..bd8a886 100644
--- a/compat/recvmsg.c
+++ b/compat/recvmsg.c
@@ -83,7 +83,7 @@ ssize_t recvmsg(int fd, struct msghdr *msg, int flags)
     return -1;
 }
 
-#elif defined __native_client__
+#elif defined __native_client__ || defined __HAIKU__
 #include <errno.h>
 #include <limits.h>
 #include <stdlib.h>
diff --git a/compat/sendmsg.c b/compat/sendmsg.c
index 0f42e78..0ce5aef 100644
--- a/compat/sendmsg.c
+++ b/compat/sendmsg.c
@@ -73,7 +73,7 @@ ssize_t sendmsg(int fd, const struct msghdr *msg, int flags)
     return -1;
 }
 
-#elif defined __native_client__
+#elif defined __native_client__ || defined __HAIKU__
 #include <errno.h>
 #include <limits.h>
 #include <stdlib.h>
diff --git a/configure.ac b/configure.ac
index 3fc0954..2dbb94a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -46,7 +46,6 @@ dnl
 AC_PROG_CC
 AC_USE_SYSTEM_EXTENSIONS
 VLC_PROG_CC_C11
-AC_DEFINE([_FORTIFY_SOURCE], 2, [Define to 2 to get glibc warnings.])
 AC_DEFINE([_FILE_OFFSET_BITS], 64, [Define to 64 for large files support.])
 AH_TOP([
 #ifndef _REENTRANT
@@ -325,6 +324,13 @@ case "${host_os}" in
     AC_LIBOBJ([recvmsg])
     AC_LIBOBJ([sendmsg])
     ;;
+  *haiku*)
+    SYS=haiku
+    VLC_ADD_LIBS([libvlccore libvlc vlc],[-lnetwork -lbe -lgnu])
+#    VLC_ADD_PLUGIN([haiku_aout])
+#    VLC_ADD_LIBS([haiku_aout],[-lmedia])
+#    VLC_ADD_CXXFLAGS([qt4],[-std=c++11])
+    ;;
   *)
     SYS="${host_os}"
     ;;
@@ -363,6 +369,7 @@ AS_IF([test "${SYS}" = "mingw32"],[
 
 AM_CONDITIONAL(HAVE_LINUX,   test "${SYS}" = "linux")
 AM_CONDITIONAL(HAVE_OS2,     test "${SYS}" = "os2")
+AM_CONDITIONAL(HAVE_HAIKU,     test "${SYS}" = "haiku")
 
 AM_CONDITIONAL(HAVE_DARWIN,  test "${SYS}" = "darwin")
 AM_CONDITIONAL(HAVE_IOS,     test "${HAVE_IOS}" = "1")
@@ -632,7 +639,7 @@ need_libc=false
 
 dnl Check for usual libc functions
 AC_CHECK_FUNCS([accept4 daemon fcntl flock fstatvfs fork getenv getmntent_r getpwuid_r isatty lstat memalign mkostemp mmap newlocale open_memstream openat pipe2 pread posix_fadvise posix_madvise posix_memalign setlocale stricmp strnicmp strptime uselocale])
-AC_REPLACE_FUNCS([aligned_alloc atof atoll dirfd fdopendir ffsll flockfile fsync getdelim getpid lfind lldiv memrchr nrand48 poll recvmsg rewind sendmsg setenv strcasecmp strcasestr strdup strlcpy strndup strnlen strnstr strsep strtof strtok_r strtoll swab tdestroy tfind timegm timespec_get strverscmp pathconf])
+AC_REPLACE_FUNCS([aligned_alloc atof atoll dirfd fdopendir ffsll flockfile fsync getdelim getpid lfind lldiv memrchr nrand48 poll recvmsg rewind sendmsg setenv strcasecmp strcasestr strdup strlcpy strndup strnlen strnstr strsep strtof strtok_r strtoll swab tfind timegm timespec_get strverscmp pathconf])
 AC_REPLACE_FUNCS([gettimeofday])
 AC_CHECK_FUNC(fdatasync,,
   [AC_DEFINE(fdatasync, fsync, [Alias fdatasync() to fsync() if missing.])
@@ -972,8 +979,10 @@ AC_SEARCH_LIBS(connect, [socket], [
   AS_IF([test "${SYS}" = "mingw32"], [
     SOCKET_LIBS="-lws2_32 -liphlpapi"
   ])
+  AS_IF([test "${SYS}" = "haiku"], [
+    SOCKET_LIBS="-lnetwork"
+  ])
 ])
-
 AC_SEARCH_LIBS([inet_pton], [nsl], [
  AS_IF([test "$ac_cv_search_inet_pton" != "none required"], [
     SOCKET_LIBS="$ac_cv_search_inet_pton $SOCKET_LIBS"
@@ -1186,9 +1195,12 @@ AH_BOTTOM([
     AS_IF([test "${ac_cv_c_omit_frame_pointer}" = "no"], [VLC_RESTORE_FLAGS])
   ])
 
-  AX_APPEND_COMPILE_FLAGS([-fstack-protector-strong])
-  AX_APPEND_COMPILE_FLAGS([-fstack-protector-strong], [CXXFLAGS])
-  dnl Win32 requires linking to ssp for stack-protection
+  AS_IF([test "${SYS}" != "haiku"], [
+	AX_APPEND_COMPILE_FLAGS([-fstack-protector-strong])
+	AX_APPEND_COMPILE_FLAGS([-fstack-protector-strong], [CXXFLAGS])
+	dnl Win32 requires linking to ssp for stack-protection
+  ])
+
   AS_IF([test "${SYS}" = "mingw32"], [
       LDFLAGS="${LDFLAGS} -lssp"
       AS_IF([test "${vlc_winstore_app}" != 1], [LDFLAGS="${LDFLAGS} -ladvapi32"])
@@ -1712,7 +1724,7 @@ then
   fi
   AC_ARG_VAR([LUAC], [LUA byte compiler])
   AS_IF([test -z "$LUAC"], [
-     AC_CHECK_TOOL(LUAC, [luac], [false])
+     AC_CHECK_TOOL(LUAC, [luac5.2], [false])
   ])
   AS_IF([test "${LUAC}" = "false"], [
     AC_MSG_ERROR([Could not find the LUA byte compiler.])
@@ -2644,7 +2656,7 @@ then
       VLC_SAVE_FLAGS
       CPPFLAGS="${CPPFLAGS} ${POSTPROC_CFLAGS}"
       CFLAGS="${CFLAGS} ${POSTPROC_CFLAGS}"
-      AC_CHECK_HEADERS(postproc/postprocess.h)
+      AC_CHECK_HEADERS(libpostproc/postprocess.h)
       VLC_ADD_PLUGIN([postproc])
       VLC_RESTORE_FLAGS
     ],[
@@ -3122,7 +3134,7 @@ dnl  X C Bindings modules
 dnl
 AC_ARG_ENABLE(xcb,
   [  --enable-xcb            X11 support with XCB (default enabled)],, [
-  AS_IF([test "${SYS}" != "mingw32" -a "${SYS}" != "darwin"], [
+  AS_IF([test "${SYS}" != "mingw32" -a "${SYS}" != "darwin" -a "${SYS}" != "haiku"], [
     enable_xcb="yes"
   ], [
     enable_xcb="no"
diff --git a/haiku/VLCLauncher.cpp b/haiku/VLCLauncher.cpp
new file mode 100644
index 0000000..37af2e8
--- /dev/null
+++ b/haiku/VLCLauncher.cpp
@@ -0,0 +1,89 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+
+#include <Application.h>
+#include <String.h>
+#include <Resources.h>
+#include <Roster.h>
+#include <Mime.h>
+#include <Path.h>
+#include <AppFileInfo.h>
+
+class VLCLauncherApp : public BApplication {
+	public:
+		VLCLauncherApp(const char *signature, int argc, char **argv);
+		~VLCLauncherApp() {};
+		void			RefsReceived(BMessage *pmsg);
+		virtual void 	ReadyToRun();
+		BString			GetVLCPath(void);
+	private:
+		BMessenger  	fTrackerMessenger;
+};
+
+VLCLauncherApp::VLCLauncherApp(const char *signature, int argc, char **argv)
+	: BApplication(signature)
+{
+}
+
+BString
+VLCLauncherApp::GetVLCPath(void)
+{
+	app_info inf;
+   	be_app->GetAppInfo(&inf);
+   	BPath binPath = BPath(&(inf.ref));
+   	BPath appPath;
+   	binPath.GetParent(&appPath);
+   	appPath.Append("VLC");
+   	return appPath.Path();
+}
+
+void
+VLCLauncherApp::RefsReceived(BMessage *pmsg)
+{
+	if (pmsg->HasMessenger("TrackerViewToken")) {
+		pmsg->FindMessenger("TrackerViewToken", &fTrackerMessenger);
+	}
+
+	uint32 type;
+	int32 count;
+	status_t ret = pmsg->GetInfo("refs", &type, &count);
+	if (ret != B_OK || type != B_REF_TYPE)
+		return;
+
+	BString commandLine = GetVLCPath();
+	
+	entry_ref ref;	
+	for (int32 i = 0; i < count; i++) {
+   		if (pmsg->FindRef("refs", i, &ref) == B_OK)
+   		 {
+   		    BPath file=BPath(&ref);
+   		    commandLine += " \"";
+   		    commandLine += file.Path();
+   		    commandLine += "\"";
+   		 }
+   	}
+   	commandLine += " &";
+   	system(commandLine.String());
+   	Quit();
+}
+
+void
+VLCLauncherApp::ReadyToRun()
+{
+	BString commandLine = GetVLCPath();
+	commandLine += " &";
+    system(commandLine.String());
+    Quit();
+}
+
+
+int main(int argc, char **argv)
+{
+	VLCLauncherApp application("application/x-vnd.vlc-launcher", argc, argv);
+	application.Run();
+	return 0;
+}
+
+
diff --git a/include/vlc_fixups.h b/include/vlc_fixups.h
index a83d068..49cfe60 100644
--- a/include/vlc_fixups.h
+++ b/include/vlc_fixups.h
@@ -103,7 +103,7 @@ typedef struct
 
 #if !defined (HAVE_GETDELIM) || \
     !defined (HAVE_GETPID)   || \
-    !defined (HAVE_SWAB)
+    !defined (HAVE_SWAB) || defined(__HAIKU__)
 # include <sys/types.h> /* ssize_t, pid_t */
 #endif
 
@@ -381,6 +381,7 @@ void swab (const void *, void *, ssize_t);
 #endif
 
 /* Socket stuff */
+#ifndef __HAIKU__
 #ifndef HAVE_INET_PTON
 # ifndef _WIN32
 #  include <sys/socket.h>
@@ -390,6 +391,7 @@ typedef int socklen_t;
 int inet_pton(int, const char *, void *);
 const char *inet_ntop(int, const void *, char *, socklen_t);
 #endif
+#endif
 
 /* NaCl has a broken netinet/tcp.h, so TCP_NODELAY is not set */
 #if defined(__native_client__) && !defined( HAVE_NETINET_TCP_H )
@@ -423,6 +425,8 @@ struct pollfd;
 int poll (struct pollfd *, unsigned, int);
 #endif
 
+// or these
+#ifndef __HAIKU__
 #ifndef HAVE_IF_NAMEINDEX
 #include <errno.h>
 # ifndef HAVE_STRUCT_IF_NAMEINDEX
@@ -438,6 +442,7 @@ struct if_nameindex
 # define if_nameindex()         (errno = ENOBUFS, NULL)
 # define if_freenameindex(list) (void)0
 #endif
+#endif
 
 #ifndef HAVE_STRUCT_TIMESPEC
 struct timespec {
diff --git a/include/vlc_vout_display.h b/include/vlc_vout_display.h
index 36f1227..e31d87d 100644
--- a/include/vlc_vout_display.h
+++ b/include/vlc_vout_display.h
@@ -81,7 +81,7 @@ enum {
  * Initial/Current configuration for a vout_display_t
  */
 typedef struct {
-#if defined(_WIN32) || defined(__OS2__)
+#if defined(_WIN32) || defined(__OS2__) || defined(__HAIKU__)
     bool is_fullscreen VLC_DEPRECATED;  /* Is the display fullscreen */
 #endif
 
@@ -148,7 +148,7 @@ enum {
      */
     VOUT_DISPLAY_RESET_PICTURES,
 
-#if defined(_WIN32) || defined(__OS2__)
+#if defined(_WIN32) || defined(__OS2__) || defined(__HAIKU__)
     /* Ask the module to acknowledge/refuse the fullscreen state change after
      * being requested (externally or by VOUT_DISPLAY_EVENT_FULLSCREEN */
     VOUT_DISPLAY_CHANGE_FULLSCREEN VLC_DEPRECATED_ENUM,     /* bool fs */
@@ -196,7 +196,7 @@ enum {
     /* */
     VOUT_DISPLAY_EVENT_PICTURES_INVALID,    /* The buffer are now invalid and need to be changed */
 
-#if defined(_WIN32) || defined(__OS2__)
+#if defined(_WIN32) || defined(__OS2__) || defined(__HAIKU__)
     VOUT_DISPLAY_EVENT_FULLSCREEN,
     VOUT_DISPLAY_EVENT_WINDOW_STATE,
 #endif
@@ -369,7 +369,7 @@ static inline void vout_display_SendEventKey(vout_display_t *vd, int key)
 {
     vout_display_SendEvent(vd, VOUT_DISPLAY_EVENT_KEY, key);
 }
-#if defined(_WIN32) || defined(__OS2__)
+#if defined(_WIN32) || defined(__OS2__) || defined(__HAIKU__)
 static inline void vout_display_SendEventFullscreen(vout_display_t *vd, bool is_fullscreen,
                                                     bool is_window_fullscreen)
 {
diff --git a/include/vlc_vout_window.h b/include/vlc_vout_window.h
index edc94fe..88eee0c 100644
--- a/include/vlc_vout_window.h
+++ b/include/vlc_vout_window.h
@@ -53,6 +53,7 @@ enum vout_window_type {
     VOUT_WINDOW_TYPE_NSOBJECT /**< MacOS X view */,
     VOUT_WINDOW_TYPE_ANDROID_NATIVE /**< Android native window */,
     VOUT_WINDOW_TYPE_WAYLAND /**< Wayland surface */,
+    VOUT_WINDOW_TYPE_HAIKU /**< Haiku */,
 };
 
 /**
@@ -159,6 +160,7 @@ struct vout_window_t {
         void     *nsobject;      /**< Mac OSX view object */
         void     *anativewindow; /**< Android native window */
         struct wl_surface *wl;   /**< Wayland surface (client pointer) */
+        void 	 *haikuwindow;   /**< Haiku */
     } handle;
 
     /** Display server (mandatory)
diff --git a/include/vlc_vout_wrapper.h b/include/vlc_vout_wrapper.h
index b808f55..4f918d5 100644
--- a/include/vlc_vout_wrapper.h
+++ b/include/vlc_vout_wrapper.h
@@ -62,7 +62,7 @@ static inline void vout_display_Display(vout_display_t *vd,
  */
 typedef struct {
     vout_display_cfg_t cfg;
-#if defined(_WIN32) || defined(__OS2__)
+#if defined(_WIN32) || defined(__OS2__) || defined(__HAIKU__)
     unsigned wm_state;
 #endif
     vlc_rational_t sar;
diff --git a/modules/audio_output/Makefile.am b/modules/audio_output/Makefile.am
index 13cf5ba..c60ea48 100644
--- a/modules/audio_output/Makefile.am
+++ b/modules/audio_output/Makefile.am
@@ -93,6 +93,12 @@ if HAVE_SNDIO
 aout_LTLIBRARIES += libsndio_plugin.la
 endif
 
+libhaiku_aout_plugin_la_SOURCES = audio_output/haiku.cpp
+libhaiku_aout_plugin_la_LIBADD = -lmedia
+if HAVE_HAIKU
+aout_LTLIBRARIES += libhaiku_aout_plugin.la
+endif
+
 libwaveout_plugin_la_SOURCES = audio_output/waveout.c \
 	audio_output/windows_audio_common.h
 libwaveout_plugin_la_LIBADD = -lwinmm
diff --git a/modules/audio_output/haiku.cpp b/modules/audio_output/haiku.cpp
new file mode 100644
index 0000000..025c285
--- /dev/null
+++ b/modules/audio_output/haiku.cpp
@@ -0,0 +1,394 @@
+/*****************************************************************************
+ * haiku.cpp : Haiku MediaKit audio output plugin for vlc
+ *****************************************************************************
+ * Copyright (C) 2010-2013 VLC authors and VideoLAN
+ * Copyright (C) 2020 Gerasim Troeglazov (3dEyes**)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <vlc_common.h>
+#include <vlc_plugin.h>
+#include <vlc_aout.h>
+
+#include <float.h>
+#include <sys/param.h>
+
+#include <media/MediaDefs.h>
+#include <media/MediaRoster.h>
+#include <media/SoundPlayer.h>
+
+#define FRAME_SIZE 2048
+#define AUDIO_BUFFER_SIZE_IN_SECONDS 1.0
+
+struct audio_buffer_t
+{
+    uint8_t    *data;
+    int         read_pos;
+    int         write_pos;
+    int         length;
+    int         size;
+    vlc_mutex_t mutex;
+    vlc_cond_t  cond;
+};
+
+typedef struct audio_buffer_t audio_buffer_t;
+
+struct aout_sys_t
+{
+    audio_buffer_t*       buffer;
+	BSoundPlayer*         player;
+    bool                  mute;
+    float                 volume;
+    audio_sample_format_t format;
+};
+
+static int  Open     ( vlc_object_t * );
+static void Close    ( vlc_object_t * );
+static void Play     ( audio_output_t *_p_aout, block_t *block );
+static void Pause    ( audio_output_t *, bool, mtime_t );
+static void Flush    ( audio_output_t *, bool );
+static int  TimeGet  ( audio_output_t *, mtime_t *restrict );
+static int  VolumeSet(audio_output_t* aout, float volume);
+static int  MuteSet  (audio_output_t* aout, bool mute);
+
+static void PlayBuffer(void* cookie, void* buffer, size_t size, const media_raw_audio_format &format);
+
+static int  CreateBuffer ( audio_output_t *, int );
+static void DestroyBuffer( audio_output_t * );
+static int  ReadBuffer   ( audio_output_t *, uint8_t *, int );
+static int  WriteBuffer  ( audio_output_t *, uint8_t *, int );
+
+vlc_module_begin ()
+    set_shortname(N_("Haiku audio"))
+    set_description(N_("Haiku Mediakit audio output"))
+    set_capability( "audio output", 100 )
+    set_category( CAT_AUDIO )
+    set_subcategory( SUBCAT_AUDIO_AOUT )
+    set_callbacks( Open, Close )
+    add_shortcut("haiku")
+vlc_module_end ()
+
+
+static int Start ( audio_output_t *p_aout, audio_sample_format_t *fmt )
+{
+    aout_sys_t *p_sys = p_aout->sys;
+    media_raw_audio_format hformat;
+    
+    int i_nb_channels;
+    int i_bytes_per_frame;
+    audio_sample_format_t format = *fmt;
+
+    if( aout_FormatNbChannels( fmt ) == 0 )
+        return VLC_EGENERIC;
+
+    i_nb_channels = aout_FormatNbChannels( &format );
+
+    if ( i_nb_channels >= 2 ) {
+        i_nb_channels = 2;
+        format.i_physical_channels = AOUT_CHANS_STEREO;
+    } else {
+        format.i_physical_channels = AOUT_CHAN_CENTER;
+    }
+
+    format.i_format = VLC_CODEC_S16N;
+
+    aout_FormatPrepare( &format );
+
+    i_bytes_per_frame = format.i_bytes_per_frame;
+
+    hformat.frame_rate = fmt->i_rate;
+    hformat.channel_count = i_nb_channels;
+	hformat.format = media_raw_audio_format::B_AUDIO_SHORT;
+	hformat.byte_order = B_MEDIA_HOST_ENDIAN;
+	hformat.buffer_size = FRAME_SIZE * i_bytes_per_frame;
+	
+    p_sys->player = new BSoundPlayer(&hformat, "VLC Media Player", PlayBuffer, NULL, p_aout);
+
+    if (p_sys->player->InitCheck() != B_OK) {
+        msg_Err( p_aout, "cannot initialize BSoundPlayer");
+		delete p_sys->player;
+        free(p_sys);
+        return VLC_EGENERIC;
+    }
+
+    format.channel_type = AUDIO_CHANNEL_TYPE_BITMAP;
+    p_sys->format = *fmt = format;
+
+    p_aout->time_get = TimeGet;
+    p_aout->play     = Play;
+    p_aout->pause    = Pause;
+    p_aout->flush    = Flush;
+
+    CreateBuffer( p_aout, AUDIO_BUFFER_SIZE_IN_SECONDS * format.i_rate * format.i_bytes_per_frame );
+    
+    VolumeSet(p_aout, 1.0 );
+                      
+	p_sys->player->Start();
+
+    return VLC_SUCCESS;
+}
+
+static void Play (audio_output_t *p_aout, block_t *block)
+{
+    aout_sys_t *p_sys = p_aout->sys;
+
+    WriteBuffer( p_aout, block->p_buffer, block->i_buffer );
+
+    p_sys->player->SetHasData(true);
+
+    block_Release( block );
+}
+
+static void Stop ( audio_output_t *p_aout )
+{
+    aout_sys_t *p_sys = p_aout->sys;
+
+    p_sys->player->SetHasData(false);
+    p_sys->player->Stop(true, false);
+    delete p_sys->player;
+    p_sys->player = NULL;
+
+    DestroyBuffer( p_aout );
+}
+
+static void PlayBuffer(void* cookie, void* p_buffer, size_t i_buf_size, const media_raw_audio_format &format)
+{
+	VLC_UNUSED( format );
+	
+    audio_output_t *p_aout = (audio_output_t *)cookie;
+    size_t i_len;
+
+    i_len = ReadBuffer( p_aout, (uint8_t*)p_buffer, i_buf_size );
+    if(i_len < i_buf_size )
+        memset(( uint8_t * )p_buffer + i_len, 0, i_buf_size - i_len );
+}
+
+static int Open (vlc_object_t *obj)
+{
+    audio_output_t *aout = (audio_output_t *)obj;
+    aout_sys_t *sys = (aout_sys_t*)calloc( 1, sizeof( aout_sys_t ) );
+
+    if( unlikely( sys == NULL ))
+        return VLC_ENOMEM;
+
+    aout->sys = sys;
+    aout->start = Start;
+    aout->stop = Stop;
+    aout->mute_set = MuteSet;
+    aout->volume_set = VolumeSet;
+
+    sys->player = NULL;
+
+    return VLC_SUCCESS;
+}
+
+static void Close( vlc_object_t *obj )
+{
+    audio_output_t *aout = (audio_output_t *)obj;
+    aout_sys_t *sys = aout->sys;
+
+    free(sys);
+}
+
+static void Pause( audio_output_t *aout, bool pause, mtime_t date )
+{
+    VLC_UNUSED( date );
+
+    aout_sys_t *sys = aout->sys;
+    
+    if (sys->player == NULL)
+    	return;
+
+    if (pause)
+        sys->player->SetHasData(false);
+    else
+        sys->player->SetHasData(true);
+}
+
+static void Flush( audio_output_t *aout, bool drain )
+{
+    audio_buffer_t *buffer = aout->sys->buffer;
+
+    vlc_mutex_lock( &buffer->mutex );
+
+    if( drain ) {
+        while( buffer->length > 0 )
+            vlc_cond_wait( &buffer->cond, &buffer->mutex );
+    } else {
+        buffer->read_pos = buffer->write_pos;
+        buffer->length   = 0;
+    }
+
+    vlc_mutex_unlock( &buffer->mutex );
+}
+
+static int TimeGet( audio_output_t *aout, mtime_t *restrict delay )
+{
+    aout_sys_t            *sys = aout->sys;
+    audio_sample_format_t *format = &sys->format;
+    audio_buffer_t        *buffer = sys->buffer;
+
+    vlc_mutex_lock( &buffer->mutex );
+
+    *delay = ( buffer->length / format->i_bytes_per_frame ) * CLOCK_FREQ /
+             format->i_rate;
+
+    vlc_mutex_unlock( &buffer->mutex );
+
+    return 0;
+}
+
+static int VolumeSet(audio_output_t* aout, float volume)
+{
+    aout_sys_t* sys = (aout_sys_t*)aout->sys;
+
+    if (sys->player == NULL)
+    	return VLC_EGENERIC;
+
+    sys->volume = volume;
+    aout_VolumeReport(aout, volume);
+
+	float dbVol = lroundf(125.f * log10f(volume));
+
+    if (sys->mute == false)
+        sys->player->SetVolumeDB(dbVol);
+
+    return VLC_SUCCESS;
+}
+
+static int MuteSet(audio_output_t* aout, bool mute)
+{
+    aout_sys_t* sys = (aout_sys_t*)aout->sys;
+
+    if (sys->player == NULL)
+    	return VLC_EGENERIC;
+
+    sys->mute = mute;
+    aout_MuteReport(aout, mute);
+    
+    float dbVol = lroundf(125.f * log10f(sys->volume));
+
+    if (mute == false)
+        sys->player->SetVolumeDB(dbVol);
+    else
+        sys->player->SetVolume(0.0);
+
+    return VLC_SUCCESS;
+}
+
+static int CreateBuffer( audio_output_t *aout, int size )
+{
+    audio_buffer_t *buffer;
+
+    buffer = (audio_buffer_t*)calloc( 1, sizeof( *buffer ));
+    if( !buffer )
+        return -1;
+
+    buffer->data = (uint8_t*)malloc( size );
+    if( !buffer->data ) {
+        free( buffer );
+        return -1;
+    }
+
+    buffer->size = size;
+
+    vlc_mutex_init( &buffer->mutex );
+    vlc_cond_init( &buffer->cond );
+
+    aout->sys->buffer = buffer;
+
+    return 0;
+}
+
+static void DestroyBuffer( audio_output_t *aout )
+{
+    audio_buffer_t *buffer = aout->sys->buffer;
+
+    vlc_mutex_destroy( &buffer->mutex );
+    vlc_cond_destroy( &buffer->cond );
+
+    free( buffer->data );
+    free( buffer );
+}
+
+static int ReadBuffer( audio_output_t *aout, uint8_t *data, int size )
+{
+    audio_buffer_t *buffer = aout->sys->buffer;
+    int             len;
+    int             remain_len = 0;
+
+    vlc_mutex_lock( &buffer->mutex );
+
+    len = MIN( buffer->length, size );
+    if( buffer->read_pos + len > buffer->size ) {
+        remain_len  = len;
+        len         = buffer->size - buffer->read_pos;
+        remain_len -= len;
+    }
+
+    memcpy( data, buffer->data + buffer->read_pos, len );
+    if( remain_len )
+        memcpy( data + len, buffer->data, remain_len );
+
+    len += remain_len;
+
+    buffer->read_pos += len;
+    buffer->read_pos %= buffer->size;
+
+    buffer->length -= len;
+
+    vlc_cond_signal( &buffer->cond );
+
+    vlc_mutex_unlock( &buffer->mutex );
+
+    return len;
+}
+
+static int WriteBuffer( audio_output_t *aout, uint8_t *data, int size )
+{
+    audio_buffer_t *buffer = aout->sys->buffer;
+    int             len;
+    int             remain_len = 0;
+
+    vlc_mutex_lock( &buffer->mutex );
+
+    while( buffer->length + size > buffer->size )
+        vlc_cond_wait( &buffer->cond, &buffer->mutex );
+
+    len = size;
+    if( buffer->write_pos + len > buffer->size ) {
+        remain_len  = len;
+        len         = buffer->size - buffer->write_pos;
+        remain_len -= len;
+    }
+
+    memcpy( buffer->data + buffer->write_pos, data, len );
+    if( remain_len )
+        memcpy( buffer->data, data + len, remain_len );
+
+    buffer->write_pos += size;
+    buffer->write_pos %= buffer->size;
+
+    buffer->length += size;
+
+    vlc_mutex_unlock( &buffer->mutex );
+
+    return size;
+}
diff --git a/modules/codec/avcodec/avcommon_compat.h b/modules/codec/avcodec/avcommon_compat.h
index d386444..5ed96c1 100644
--- a/modules/codec/avcodec/avcommon_compat.h
+++ b/modules/codec/avcodec/avcommon_compat.h
@@ -78,6 +78,46 @@
 # define  FF_MAX_B_FRAMES 16 // FIXME: remove this
 #endif
 
+#ifndef AV_CODEC_FLAG_OUTPUT_CORRUPT
+# define AV_CODEC_FLAG_OUTPUT_CORRUPT CODEC_FLAG_OUTPUT_CORRUPT
+#endif
+#ifndef AV_CODEC_FLAG_GRAY
+# define AV_CODEC_FLAG_GRAY CODEC_FLAG_GRAY
+#endif
+#ifndef AV_CODEC_FLAG_DR1
+# define AV_CODEC_FLAG_DR1 CODEC_FLAG_DR1
+#endif
+#ifndef AV_CODEC_FLAG_DELAY
+# define AV_CODEC_FLAG_DELAY CODEC_FLAG_DELAY
+#endif
+#ifndef AV_CODEC_FLAG2_FAST
+# define AV_CODEC_FLAG2_FAST CODEC_FLAG2_FAST
+#endif
+#ifndef FF_INPUT_BUFFER_PADDING_SIZE
+# define FF_INPUT_BUFFER_PADDING_SIZE AV_INPUT_BUFFER_PADDING_SIZE
+#endif
+#ifndef AV_CODEC_FLAG_INTERLACED_DCT
+# define AV_CODEC_FLAG_INTERLACED_DCT CODEC_FLAG_INTERLACED_DCT
+#endif
+#ifndef AV_CODEC_FLAG_INTERLACED_ME
+# define AV_CODEC_FLAG_INTERLACED_ME CODEC_FLAG_INTERLACED_ME
+#endif
+#ifndef AV_CODEC_FLAG_GLOBAL_HEADER
+# define AV_CODEC_FLAG_GLOBAL_HEADER CODEC_FLAG_GLOBAL_HEADER
+#endif
+#ifndef AV_CODEC_FLAG_LOW_DELAY
+# define AV_CODEC_FLAG_LOW_DELAY CODEC_FLAG_LOW_DELAY
+#endif
+#ifndef AV_CODEC_CAP_SMALL_LAST_FRAME
+# define AV_CODEC_CAP_SMALL_LAST_FRAME CODEC_CAP_SMALL_LAST_FRAME
+#endif
+#ifndef AV_INPUT_BUFFER_MIN_SIZE
+# define AV_INPUT_BUFFER_MIN_SIZE FF_MIN_BUFFER_SIZE
+#endif
+#ifndef  FF_MAX_B_FRAMES
+# define  FF_MAX_B_FRAMES 16 // FIXME: remove this
+#endif
+
 #endif /* HAVE_LIBAVCODEC_AVCODEC_H */
 
 #ifdef HAVE_LIBAVUTIL_AVUTIL_H
diff --git a/modules/gui/qt/components/controller.cpp b/modules/gui/qt/components/controller.cpp
index f91d748..56918a2 100644
--- a/modules/gui/qt/components/controller.cpp
+++ b/modules/gui/qt/components/controller.cpp
@@ -229,7 +229,11 @@ void AbstractController::createAndAddWidget( QBoxLayout *controlLayout_,
 
 QWidget *AbstractController::createWidget( buttonType_e button, int options )
 {
+#ifdef __HAIKU__
+	bool b_flat  = true; // Flat for Haiku
+#else
     bool b_flat  = options & WIDGET_FLAT;
+#endif
     bool b_big   = options & WIDGET_BIG;
     bool b_shiny = options & WIDGET_SHINY;
     bool b_special = false;
@@ -731,10 +735,10 @@ ControlsWidget::ControlsWidget( intf_thread_t *_p_i,
     QString line2 = getSettings()->value( "MainWindow/MainToolbar2", MAIN_TB2_DEFAULT )
                                         .toString();
     parseAndCreate( line2, controlLayout2 );
-
+#ifndef __HAIKU__
     grip = new QSizeGrip( this );
     controlLayout2->addWidget( grip, 0, Qt::AlignBottom|Qt::AlignRight );
-
+#endif
     if( !b_advancedVisible && advControls ) advControls->hide();
 
     controlLayout->addLayout( controlLayout1 );
diff --git a/modules/gui/qt/components/controller.hpp b/modules/gui/qt/components/controller.hpp
index 8650029..40be498 100644
--- a/modules/gui/qt/components/controller.hpp
+++ b/modules/gui/qt/components/controller.hpp
@@ -210,17 +210,17 @@ public:
     /* p_intf, advanced control visible or not, blingbling or not */
     ControlsWidget( intf_thread_t *_p_i, bool b_advControls,
                     QWidget *_parent = 0 );
-
+#ifndef __HAIKU__
     void setGripVisible( bool b_visible )
     { grip->setVisible( b_visible ); }
-
+#endif
 protected:
     friend class MainInterface;
 
     bool b_advancedVisible;
 
 private:
-    QSizeGrip *grip;
+    QWidget *grip;
 
 protected slots:
     void toggleAdvanced();
diff --git a/modules/gui/qt/components/interface_widgets.cpp b/modules/gui/qt/components/interface_widgets.cpp
index bcf65d2..ff2babd 100644
--- a/modules/gui/qt/components/interface_widgets.cpp
+++ b/modules/gui/qt/components/interface_widgets.cpp
@@ -158,6 +158,9 @@ bool VideoWidget::request( struct vout_window_t *p_wnd )
         case VOUT_WINDOW_TYPE_HWND:
             p_wnd->handle.hwnd = (void *)stable->winId();
             break;
+        case VOUT_WINDOW_TYPE_HAIKU:
+            p_wnd->handle.haikuwindow = (void *)stable->winId();
+            break;
         case VOUT_WINDOW_TYPE_NSOBJECT:
             p_wnd->handle.nsobject = (void *)stable->winId();
             break;
diff --git a/modules/gui/qt/dialogs/plugins.cpp b/modules/gui/qt/dialogs/plugins.cpp
index 450889b..e389724 100644
--- a/modules/gui/qt/dialogs/plugins.cpp
+++ b/modules/gui/qt/dialogs/plugins.cpp
@@ -53,6 +53,7 @@
 #include <QListView>
 #include <QListWidget>
 #include <QPainter>
+#include <QPainterPath>
 #include <QStyleOptionViewItem>
 #include <QKeyEvent>
 #include <QPushButton>
diff --git a/modules/gui/qt/main_interface.cpp b/modules/gui/qt/main_interface.cpp
index bb5dad8..d421f4f 100644
--- a/modules/gui/qt/main_interface.cpp
+++ b/modules/gui/qt/main_interface.cpp
@@ -127,7 +127,13 @@ MainInterface::MainInterface( intf_thread_t *_p_intf ) : QVLCMW( _p_intf )
     setWindowRole( "vlc-main" );
     setWindowIcon( QApplication::windowIcon() );
     setWindowOpacity( var_InheritFloat( p_intf, "qt-opacity" ) );
-
+#ifdef __HAIKU__
+	setWindowFlags(Qt::Window
+		| Qt::MSWindowsFixedSizeDialogHint
+		| Qt::WindowMinimizeButtonHint
+		| Qt::WindowCloseButtonHint
+		| Qt::CustomizeWindowHint);
+#endif
     /* Does the interface resize to video size or the opposite */
     b_autoresize = var_InheritBool( p_intf, "qt-video-autoresize" );
 
@@ -144,7 +150,11 @@ MainInterface::MainInterface( intf_thread_t *_p_intf ) : QVLCMW( _p_intf )
     settings = getSettings();
 
     /* */
+#ifndef __HAIKU__
     b_plDocked = getSettings()->value( "MainWindow/pl-dock-status", true ).toBool();
+#else
+	b_plDocked = false;
+#endif
 
     /* Should the UI stays on top of other windows */
     b_interfaceOnTop = var_InheritBool( p_intf, "video-on-top" );
@@ -313,11 +323,27 @@ MainInterface::~MainInterface()
 
 void MainInterface::computeMinimumSize()
 {
+#ifndef __HAIKU__
     int minWidth = 80;
     if( menuBar()->isVisible() )
         minWidth += controls->sizeHint().width();
 
     setMinimumWidth( minWidth );
+#else
+	int minWidth = 32;
+	minWidth += fmax(controls->sizeHint().width(), menuBar()->sizeHint().width());
+    setMinimumWidth( minWidth );
+
+    int minHeight = 50;
+    minHeight += controls->sizeHint().height();
+    if( statusBar()->isVisible() )
+        minHeight += statusBar()->sizeHint().height();
+    if( resumePanel->isVisible() )
+    	minHeight += resumePanel->sizeHint().height();
+    setMinimumHeight(minHeight);
+    setMaximumHeight(minHeight);
+    setMaximumWidth(minWidth);
+#endif
 }
 
 /*****************************
@@ -411,6 +437,9 @@ void MainInterface::showResumePanel( int64_t _time ) {
         if( !isFullScreen() && !isMaximized() && !b_isWindowTiled )
             resizeWindow( width(), height() + resumePanel->height() );
         resumePanel->setVisible(true);
+#ifdef __HAIKU__
+	    computeMinimumSize();
+#endif
         resumeTimer->start();
     }
 }
@@ -423,6 +452,9 @@ void MainInterface::hideResumePanel()
             resizeWindow( width(), height() - resumePanel->height() );
         resumePanel->hide();
         resumeTimer->stop();
+#ifdef __HAIKU__
+        computeMinimumSize();
+#endif
     }
 }
 
@@ -463,7 +495,7 @@ void MainInterface::createMainWidget( QSettings *creationSettings )
     createResumePanel( main );
     /* */
     stackCentralW = new QVLCStackedWidget( main );
-
+#ifndef __HAIKU__
     /* Bg Cone */
     if ( QDate::currentDate().dayOfYear() >= QT_XMAS_JOKE_DAY
          && var_InheritBool( p_intf, "qt-icon-change" ) )
@@ -493,7 +525,9 @@ void MainInterface::createMainWidget( QSettings *creationSettings )
         creationSettings->value( "MainWindow/bgSize", QSize( 600, 0 ) ).toSize();
     /* Resize even if no-auto-resize, because we are at creation */
     resizeStack( stackWidgetsSizes[bgWidget].width(), stackWidgetsSizes[bgWidget].height() );
-
+#else
+	mainLayout->insertWidget( 1, stackCentralW );
+#endif
     /* Create the CONTROLS Widget */
     controls = new ControlsWidget( p_intf,
         creationSettings->value( "MainWindow/adv-controls", false ).toBool(), this );
@@ -1202,6 +1236,9 @@ void MainInterface::toggleMinimalView( bool b_minimal )
 void MainInterface::toggleAdvancedButtons()
 {
     controls->toggleAdvanced();
+#ifdef __HAIKU__
+    computeMinimumSize();
+#endif
 //    if( fullscreenControls ) fullscreenControls->toggleAdvanced();
 }
 
@@ -1223,7 +1260,11 @@ void MainInterface::setStatusBarVisibility( bool b_visible )
 {
     statusBar()->setVisible( b_visible );
     b_statusbarVisible = b_visible;
+#ifdef __HAIKU__
+    computeMinimumSize();
+#else
     if( controls ) controls->setGripVisible( !b_statusbarVisible );
+#endif
 }
 
 
@@ -1294,9 +1335,9 @@ void MainInterface::createSystray()
 {
     QIcon iconVLC;
     if( QDate::currentDate().dayOfYear() >= QT_XMAS_JOKE_DAY && var_InheritBool( p_intf, "qt-icon-change" ) )
-        iconVLC = QIcon::fromTheme( "vlc-xmas", QIcon( ":/logo/vlc128-xmas.png" ) );
+        iconVLC = QIcon( ":/logo/vlc128-xmas.png" );
     else
-        iconVLC = QIcon::fromTheme( "vlc", QIcon( ":/logo/vlc256.png" ) );
+        iconVLC = QIcon( ":/logo/vlc256.png" );
     sysTray = new QSystemTrayIcon( iconVLC, this );
     sysTray->setToolTip( qtr( "VLC media player" ));
 
diff --git a/modules/gui/qt/menus.cpp b/modules/gui/qt/menus.cpp
index aea98c9..c946f9b 100644
--- a/modules/gui/qt/menus.cpp
+++ b/modules/gui/qt/menus.cpp
@@ -486,7 +486,7 @@ QMenu *VLCMenuBar::ViewMenu( intf_thread_t *p_intf, QMenu *current, MainInterfac
 #endif
             qtr( "Play&list" ), mi,
             SLOT( togglePlaylist() ), qtr( "Ctrl+L" ) );
-
+#ifndef __HAIKU__
     /* Docked Playlist */
     action = menu->addAction( qtr( "Docked Playlist" ) );
     action->setCheckable( true );
@@ -495,7 +495,7 @@ QMenu *VLCMenuBar::ViewMenu( intf_thread_t *p_intf, QMenu *current, MainInterfac
 
     if( mi->getPlaylistView() )
         menu->addMenu( StandardPLPanel::viewSelectionMenu( mi->getPlaylistView() ) );
-
+#endif
     menu->addSeparator();
 
     action = menu->addAction( qtr( "Always on &top" ) );
@@ -504,7 +504,7 @@ QMenu *VLCMenuBar::ViewMenu( intf_thread_t *p_intf, QMenu *current, MainInterfac
     CONNECT( action, triggered( bool ), mi, setInterfaceAlwaysOnTop( bool ) );
 
     menu->addSeparator();
-
+#ifndef __HAIKU__
     /* Minimal View */
     action = menu->addAction( qtr( "Mi&nimal Interface" ) );
     action->setShortcut( qtr( "Ctrl+H" ) );
@@ -529,7 +529,7 @@ QMenu *VLCMenuBar::ViewMenu( intf_thread_t *p_intf, QMenu *current, MainInterfac
     action->setCheckable( true );
     if( mi->getControlsVisibilityStatus() & MainInterface::CONTROLS_ADVANCED )
         action->setChecked( true );
-
+#endif
     action = menu->addAction( qtr( "Status Bar" ) );
     action->setCheckable( true );
     action->setChecked( mi->statusBar()->isVisible() );
diff --git a/modules/gui/qt/qt.cpp b/modules/gui/qt/qt.cpp
index ab912fd..e3c9ed8 100644
--- a/modules/gui/qt/qt.cpp
+++ b/modules/gui/qt/qt.cpp
@@ -604,6 +604,8 @@ static void *ThreadPlatform( void *obj, char *platform_name )
         else if( platform == qfu("windows") )
             p_sys->voutWindowType = VOUT_WINDOW_TYPE_HWND;
         else if( platform == qfu("cocoa" ) )
+            p_sys->voutWindowType = VOUT_WINDOW_TYPE_HAIKU;
+        else if( platform == qfu("haiku" ) )
             p_sys->voutWindowType = VOUT_WINDOW_TYPE_NSOBJECT;
         else
             msg_Err( p_intf, "unknown Qt platform: %s", qtu(platform) );
diff --git a/modules/gui/qt/util/timetooltip.cpp b/modules/gui/qt/util/timetooltip.cpp
index 70a8e6d..f6237bc 100644
--- a/modules/gui/qt/util/timetooltip.cpp
+++ b/modules/gui/qt/util/timetooltip.cpp
@@ -27,7 +27,11 @@
 #include <QFontMetrics>
 #include <QDesktopWidget>
 
+#ifdef __HAIKU__
+#define TIP_HEIGHT 0
+#else
 #define TIP_HEIGHT 5
+#endif
 
 TimeTooltip::TimeTooltip( QWidget *parent ) :
     QWidget( parent )
diff --git a/modules/video_output/Makefile.am b/modules/video_output/Makefile.am
index 78c06cf..0ae24ec 100644
--- a/modules/video_output/Makefile.am
+++ b/modules/video_output/Makefile.am
@@ -356,6 +356,13 @@ if HAVE_WIN32
 vout_LTLIBRARIES += libdrawable_plugin.la
 endif
 
+### HAIKU ###
+libhaiku_vout_plugin_la_SOURCES = video_output/haiku.cpp
+libhaiku_vout_plugin_la_LIBADD = -lbe
+if HAVE_HAIKU
+vout_LTLIBRARIES += libhaiku_vout_plugin.la
+endif
+
 ### OS/2 ###
 if HAVE_OS2
 vout_LTLIBRARIES += libdrawable_plugin.la
@@ -422,9 +429,11 @@ libcaca_plugin_la_CFLAGS = $(AM_CFLAGS) $(CACA_CFLAGS)
 libcaca_plugin_la_LIBADD = libevent_thread.la $(CACA_LIBS)
 if !HAVE_WIN32
 if !HAVE_DARWIN
+if !HAVE_HAIKU
 libcaca_plugin_la_LIBADD += $(X_LIBS) $(X_PRE_LIBS) -lX11
 endif
 endif
+endif
 libcaca_plugin_la_LDFLAGS = $(AM_LDFLAGS) -rpath '$(voutdir)'
 EXTRA_LTLIBRARIES += libcaca_plugin.la
 vout_LTLIBRARIES += $(LTLIBcaca)
diff --git a/modules/video_output/haiku.cpp b/modules/video_output/haiku.cpp
new file mode 100644
index 0000000..9f0a2e3
--- /dev/null
+++ b/modules/video_output/haiku.cpp
@@ -0,0 +1,785 @@
+/*****************************************************************************
+ * haiku.c: Haiku video output display method for testing purposes
+ *****************************************************************************
+ * Copyright (C) 2020 Gerasim Troeglazov (3dEyes**)
+
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <vlc_common.h>
+#include <vlc_plugin.h>
+#include <vlc_vout_display.h>
+#include <vlc_picture_pool.h>
+
+#include <SupportDefs.h>
+#include <MessageQueue.h>
+#include <Window.h>
+#include <Bitmap.h>
+#include <Screen.h>
+#include <View.h>
+#include <Rect.h>
+#include <Cursor.h>
+
+static uint32 platformHaikuScanCodes[] = {
+		KEY_ESC,		0x01,
+		KEY_F1,			0x02,
+		KEY_F2,			0x03,
+		KEY_F3,			0x04,
+		KEY_F4,			0x05,
+		KEY_F5,			0x06,
+		KEY_F6,			0x07,
+		KEY_F7,			0x08,
+		KEY_F8,			0x09,
+		KEY_F9,			0x0A,
+		KEY_F10,		0x0B,
+		KEY_F11,		0x0C,
+		KEY_F12,		0x0D,
+		KEY_PAUSE,		0x22,
+
+		'`', 			0x11,
+		'1',			0x12,
+		'2',			0x13,
+		'3',			0x14,
+		'4',			0x15,
+		'5',			0x16,
+		'6',			0x17,
+		'7',			0x18,
+		'8',			0x19,
+		'9',			0x1A,
+		'0',			0x1B,
+		'-',			0x1C,
+		'+',			0x1D,
+		KEY_BACKSPACE,	0x1E,
+		KEY_INSERT,		0x1F,
+		KEY_HOME,		0x20,
+		KEY_PAGEUP,		0x21,
+		'/',			0x23,
+		'*',			0x24,
+		'-',			0x25,		
+		                
+		KEY_TAB,		0x26,        
+		'q',			0x27,
+		'w',			0x28,
+		'e',			0x29,
+		'r',			0x2A,
+		't',			0x2B,
+		'y',			0x2C,
+		'u',			0x2D,
+		'i',			0x2E,
+		'o',			0x2F,
+		'p',			0x30,      
+		'[',			0x31,
+		']',			0x32,
+		'\\',			0x33,
+		KEY_DELETE,		0x34,
+		KEY_END,		0x35,
+		KEY_PAGEDOWN,	0x36, 
+		'7',			0x37,
+		'8',			0x38, //numpad
+		'9',			0x39, //numpad
+		'+',			0x3A, //numpad
+
+		'a',			0x3C,
+		's',			0x3D,
+		'd',			0x3E,
+		'f',			0x3F,
+		'g',			0x40,
+		'h',			0x41,
+		'j',			0x42,
+		'k',			0x43,
+		'l',			0x44,
+		';',			0x45,
+		'"',			0x46,
+		KEY_ENTER,		0x47,              
+		'4',			0x48, //numpad
+		'5',			0x49, //numpad
+		'6',			0x4A, //numpad
+
+		'z',			0x4C,
+		'x',			0x4D,
+		'c',			0x4E,
+		'v',			0x4F,
+		'b',			0x50,
+		'n',			0x51,
+		'm',			0x52,
+		',',			0x53,
+		'.',			0x54,
+		'/',			0x55,
+		KEY_UP,			0x57,	//cursor
+		'1',			0x58,	//numpad
+		'2',			0x59,   //numpad
+		'3',			0x5A,   //numpad
+		KEY_ENTER,		0x5B,   //numpad
+
+		' ',			0x5E,
+		KEY_LEFT,		0x61,   //cursor
+		KEY_DOWN,		0x62,   //cursor
+		KEY_RIGHT,		0x63,   //cursor
+		'0',			0x64,   //cursor
+		'.',			0x65,   //numpad
+		0,				0x00
+	};
+	
+static const struct {
+    int haiku;
+    int vlc;
+} platformHaikuMouseButtons[] = {
+    { B_PRIMARY_MOUSE_BUTTON, MOUSE_BUTTON_LEFT },
+    { B_TERTIARY_MOUSE_BUTTON, MOUSE_BUTTON_CENTER },
+    { B_SECONDARY_MOUSE_BUTTON, MOUSE_BUTTON_RIGHT },
+    { -1, -1 }
+};
+
+class FrameBufferView : public BView 
+{
+ public:
+		FrameBufferView(BRect rect, int width, int height);
+		~FrameBufferView();
+
+		virtual void 	MessageReceived(BMessage *message);
+		virtual void 	Draw(BRect rect);
+		
+		void 			Paint();
+		uint32			*GetBuffer();
+		uint32			GetBufferSize();
+		void			ResizeBitmap(int width, int height);
+		
+		int				Width() { return buffer_width; }
+		int				Height() { return buffer_height; }
+ private:
+ 		int				buffer_width;
+ 		int				buffer_height;
+		BView			*bufferView;
+		BBitmap 		*bufferBitmap;		
+};
+
+class VLCVideoWindow : public BWindow {
+	public:
+						VLCVideoWindow(BRect rect, const char* name);
+		virtual			~VLCVideoWindow();
+
+		virtual void 	DispatchMessage(BMessage *message, BHandler *handler);
+		bool			QuitRequested();
+		
+		FrameBufferView* View(void) { return frameBufferView; }
+		BMessageQueue*  Queue(void) { return queue; }
+		void			CloneAndPushMessage(BMessage *message);
+
+		void			SetFullscreen(bool fullscreen);
+		bool			IsFullscreen(void) {return is_fullscreen; }
+
+		void			HideCursor(bool hide);
+
+	private:
+		bool			is_fullscreen;
+		BRect			lastPosition;
+		BPoint			lastMouseClick;
+
+		FrameBufferView	*frameBufferView;
+		BMessageQueue 	*queue;
+		BCursor 		*emptyCursor;
+		bool			dragWindow;
+};
+
+FrameBufferView::FrameBufferView(BRect rect, int width, int height) : 
+	BView(rect, "FrameBufferView", B_FOLLOW_ALL, B_WILL_DRAW | B_FRAME_EVENTS)
+{
+	buffer_width = width;
+	buffer_height = height;
+	
+	BRect fbRect = BRect(0, 0, buffer_width - 1, buffer_height - 1);
+	bufferBitmap = new BBitmap(fbRect, B_RGB32, true);	
+}
+
+FrameBufferView::~FrameBufferView()
+{
+	delete bufferBitmap;
+}
+
+
+void
+FrameBufferView::MessageReceived(BMessage *message)
+{
+	switch (message->what) {
+		case B_MOUSE_MOVED:
+		case B_MOUSE_WHEEL_CHANGED:
+		{
+			Window()->PostMessage(message);
+			break;
+		}
+		case B_MOUSE_DOWN:		
+		case B_MOUSE_UP:
+		{
+			Window()->PostMessage(message);
+			break;
+		}
+		default:
+			BView::MessageReceived(message);
+			break;
+	}
+}
+
+void
+FrameBufferView::Draw(BRect rect)
+{
+	SetDrawingMode(B_OP_COPY);
+	DrawBitmap(bufferBitmap, rect, rect);
+}
+
+void 
+FrameBufferView::Paint()
+{
+	if(LockLooper())	{
+		SetDrawingMode(B_OP_COPY);
+		DrawBitmap(bufferBitmap);
+		UnlockLooper();
+	}
+}
+
+uint32 *
+FrameBufferView::GetBuffer()
+{
+	if(bufferBitmap == NULL)
+		return NULL;
+	return (uint32*)bufferBitmap->Bits();
+}
+
+uint32	
+FrameBufferView::GetBufferSize()
+{
+	if(bufferBitmap == NULL)
+		return 0;
+	return bufferBitmap->BitsLength();
+}
+
+void	
+FrameBufferView::ResizeBitmap(int w, int h)
+{
+	if(w == buffer_width && h == buffer_height && bufferBitmap != NULL)
+		return;
+	if(LockLooper()) {
+	 	delete bufferBitmap;
+		
+		buffer_width = w;
+		buffer_height = h;
+	
+		BRect	fbRect = BRect(0, 0, buffer_width - 1, buffer_height - 1);
+		bufferBitmap = new BBitmap(fbRect, B_RGB32, true);	
+		
+	 	UnlockLooper();
+	} 	 
+}
+
+
+VLCVideoWindow::VLCVideoWindow(BRect frame, const char* title)
+	: BWindow(frame, title, B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, 0),
+	is_fullscreen(false),
+	dragWindow(false)
+{
+	frameBufferView = new FrameBufferView(Bounds(), frame.Width(), frame.Height());
+	frameBufferView->SetViewColor(0, 0, 0);
+	AddChild(frameBufferView);
+	queue = new BMessageQueue();
+	emptyCursor = new BCursor(B_CURSOR_ID_NO_CURSOR);
+}
+
+
+VLCVideoWindow::~VLCVideoWindow()
+{
+	delete emptyCursor;
+	delete queue;
+}
+
+void 
+VLCVideoWindow::CloneAndPushMessage(BMessage *message)
+{
+	BMessage *clone = new BMessage(*message);
+	queue->Lock();
+	queue->AddMessage(clone);
+	queue->Unlock();
+}
+
+void 
+VLCVideoWindow::DispatchMessage(BMessage *message, BHandler *handler)
+{
+	switch (message->what) {
+		case B_MOUSE_DOWN:
+		{
+			uint32 buttons = 0;
+			message->FindInt32("buttons", (int32 *)&buttons);
+
+			if (buttons & B_PRIMARY_MOUSE_BUTTON) {
+				frameBufferView->SetMouseEventMask(B_POINTER_EVENTS, B_NO_POINTER_HISTORY);
+				message->FindPoint("where", &lastMouseClick);
+				dragWindow = true;
+			}
+			CloneAndPushMessage(message);
+			break;
+		}
+		case B_MOUSE_UP:
+		{
+			frameBufferView->SetViewCursor(B_CURSOR_SYSTEM_DEFAULT);
+			dragWindow = false;
+			CloneAndPushMessage(message);
+			BWindow::DispatchMessage(message, handler);
+			break;
+		}
+		case B_MOUSE_MOVED:
+		{
+			uint32 buttons = 0;
+			message->FindInt32("buttons", (int32 *)&buttons);
+			BPoint where;
+			message->FindPoint("where", &where);
+			BPoint screenWhere;
+			message->FindPoint("screen_where", &screenWhere);
+			
+			if (dragWindow
+			&& buttons & B_PRIMARY_MOUSE_BUTTON
+			&& (fabs(where.x - lastMouseClick.x) >= 0.5
+			|| fabs(where.y - lastMouseClick.y) >= 0.5)) {
+				BCursor cursor(B_CURSOR_ID_MOVE);
+				frameBufferView->SetViewCursor(&cursor);
+				MoveTo(screenWhere - lastMouseClick);
+				break;
+			}
+			CloneAndPushMessage(message);
+			break;
+		}
+		case B_ZOOM:
+		case B_WINDOW_RESIZED:
+		case B_MOUSE_WHEEL_CHANGED:
+		{
+			CloneAndPushMessage(message);
+			break;
+		}
+		case B_UNMAPPED_KEY_DOWN:
+		case B_KEY_DOWN:
+		{
+			CloneAndPushMessage(message);
+			BWindow::DispatchMessage(message, handler);
+			break;
+		}
+		default:
+		{
+			BWindow::DispatchMessage(message, handler);
+			break;
+		}
+	}
+}
+
+bool
+VLCVideoWindow::QuitRequested()
+{
+	BMessage message(B_QUIT_REQUESTED);	
+	CloneAndPushMessage(&message);
+	return false;
+}
+
+void
+VLCVideoWindow::SetFullscreen(bool fullscreen)
+{
+	if (fullscreen == is_fullscreen)
+		return;
+
+	if (fullscreen) {
+		BScreen screen(B_MAIN_SCREEN_ID);
+		lastPosition = Frame();
+		MoveTo(0,0);
+		ResizeTo(screen.Frame().Width() + 1, screen.Frame().Height() + 1);
+		Activate();
+	} else {
+		MoveTo(lastPosition.left, lastPosition.top);
+		ResizeTo(lastPosition.Width(), lastPosition.Height());
+	}
+
+	is_fullscreen = fullscreen;
+}
+
+void
+VLCVideoWindow::HideCursor(bool hide)
+{
+	if (hide && dragWindow)
+		return;
+	if (frameBufferView->LockLooper()) {
+		frameBufferView->SetViewCursor(hide ? emptyCursor : B_CURSOR_SYSTEM_DEFAULT);
+		frameBufferView->UnlockLooper();
+	}
+}
+
+
+extern "C" {
+	
+static int				Open( vlc_object_t * );
+static void				Close( vlc_object_t * );
+static picture_pool_t	*Pool(vout_display_t *, unsigned count);
+static void				Display(vout_display_t *, picture_t *, subpicture_t *);
+static int				Control(vout_display_t *, int, va_list);
+static void				Manage (vout_display_t *);
+
+}
+
+vlc_module_begin ()
+    set_shortname("Haiku")
+    set_category(CAT_VIDEO)
+    set_subcategory(SUBCAT_VIDEO_VOUT)
+    set_description("Haiku video output")
+    set_capability("vout display", 100 )
+    add_shortcut("haiku")
+    add_obsolete_string("haiku-video-driver")
+    set_callbacks(Open, Close)
+vlc_module_end ()
+
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+struct vout_display_sys_t {
+	vout_display_place_t place;
+    picture_pool_t *pool;
+    VLCVideoWindow *win;
+    uint32 lastMouseButtons;
+    int	resizeDisplayCount;
+};
+
+/*****************************************************************************
+ * OpenVideo: activates haiku vout display method
+ *****************************************************************************/
+static int Open(vlc_object_t *object)
+{
+    vout_display_t *vd = (vout_display_t *)object;
+    vout_display_sys_t *sys;
+
+    vd->sys = sys = (vout_display_sys_t*)calloc(1, sizeof(*sys));
+    if (!sys)
+        return VLC_EGENERIC;
+    sys->pool = NULL;
+    sys->lastMouseButtons = 0;
+    sys->resizeDisplayCount = 0;
+
+    video_format_t fmt;
+    video_format_ApplyRotation(&fmt, &vd->fmt);
+
+	BScreen screen(B_MAIN_SCREEN_ID);
+
+	int display_margin = 128;
+    int display_width = vd->cfg->display.width;
+    int display_height = vd->cfg->display.height;
+    
+    if (display_margin + display_width > screen.Frame().Width() - display_margin) {
+    	float zoom = (screen.Frame().Width() - display_margin * 2) / (float)display_width;
+    	display_width = (float)display_width * zoom;
+    	display_height = (float)display_height * zoom;
+    }
+    if (display_margin + display_height > screen.Frame().Height() - display_margin) {
+    	float zoom = (screen.Frame().Height() - display_margin * 2) / (float)display_height;
+    	display_width = (float)display_width * zoom;
+    	display_height = (float)display_height * zoom;
+    }
+
+    vout_display_DeleteWindow(vd, NULL);
+    
+    sys->win = new VLCVideoWindow(BRect(display_margin, display_margin, display_margin + display_width, display_margin + display_height), VOUT_TITLE);
+    sys->win->Show();
+
+    if (vd->cfg->display.title)
+    	sys->win->SetTitle(vd->cfg->display.title);
+    else
+    	sys->win->SetTitle(VOUT_TITLE);
+	
+    vout_display_cfg_t place_cfg = *vd->cfg;
+    place_cfg.display.width  = display_width;
+    place_cfg.display.height = display_height;
+    vout_display_PlacePicture(&sys->place, &vd->source, &place_cfg, true);	
+
+    fmt.i_chroma = VLC_CODEC_RGB32;
+    fmt.i_width  = display_width;
+    fmt.i_height = display_height;
+    fmt.i_rmask = 0x00ff0000;
+    fmt.i_gmask = 0x0000ff00;
+    fmt.i_bmask = 0x000000ff;
+    fmt.i_visible_width = fmt.i_width;
+    fmt.i_visible_height = fmt.i_height;
+    
+	vd->info.has_pictures_invalid = true;
+    vd->info.needs_hide_mouse = true;
+    
+    vd->fmt = fmt;
+
+    vd->pool    = Pool;
+    vd->prepare = NULL;
+    vd->display = Display;
+    vd->control = Control;
+    vd->manage  = Manage;
+
+	vout_display_SendEventDisplaySize(vd, display_width, display_height);
+
+    return VLC_SUCCESS;
+}
+
+static void Close(vlc_object_t *object)
+{
+    vout_display_t *vd = (vout_display_t *)object;
+    vout_display_sys_t *sys = vd->sys;
+
+	sys->win->Lock();
+	sys->win->Quit();
+
+    if (sys->pool)
+        picture_pool_Release(sys->pool);
+    free(sys);
+}
+
+static picture_pool_t *Pool(vout_display_t *vd, unsigned count)
+{
+    vout_display_sys_t *sys = vd->sys;
+    if (!sys->pool) {
+        picture_resource_t rsc;
+
+        memset(&rsc, 0, sizeof(rsc));
+        
+        memset((uint8_t*)sys->win->View()->GetBuffer(), 0, sys->win->View()->GetBufferSize());
+        
+        rsc.p[0].p_pixels = (uint8_t*)sys->win->View()->GetBuffer();
+        rsc.p[0].i_pitch = sys->win->View()->Width() * 4;
+        rsc.p[0].i_lines = sys->win->View()->Height();
+
+        picture_t *p_picture = picture_NewFromResource(&vd->fmt, &rsc);
+        if (!p_picture)
+            return NULL;
+
+        sys->pool = picture_pool_New(1, &p_picture);
+    }    
+    return sys->pool;
+}
+
+static void Display(vout_display_t *vd, picture_t *picture, subpicture_t *subpicture)
+{
+	vout_display_sys_t *sys = vd->sys;
+	sys->win->View()->Paint();
+    picture_Release(picture);
+}
+
+static int Control(vout_display_t *vd, int query, va_list args)
+{
+    vout_display_sys_t *sys = vd->sys;
+
+    switch (query)
+    {
+    	case VOUT_DISPLAY_HIDE_MOUSE:
+    		sys->win->HideCursor(true);
+	        return VLC_SUCCESS;
+	    case VOUT_DISPLAY_CHANGE_DISPLAY_SIZE:
+	    {
+	        const vout_display_cfg_t *cfg = va_arg(args, const vout_display_cfg_t *);        	
+	        if ((sys->resizeDisplayCount == 1 || sys->resizeDisplayCount == 2) && !cfg->is_fullscreen) {
+	        	sys->resizeDisplayCount++;
+	        	return VLC_EGENERIC;
+	        }
+			sys->win->View()->ResizeBitmap(cfg->display.width, cfg->display.height);
+			if (cfg->is_fullscreen) {
+				vout_display_SendEventPicturesInvalid(vd);
+				return VLC_EGENERIC;
+			} else {
+				sys->win->ResizeTo(cfg->display.width - 1, cfg->display.height - 1);
+			}
+        	vout_display_SendEventPicturesInvalid(vd);
+			sys->resizeDisplayCount++;
+        	return VLC_SUCCESS;
+    	}
+    	case VOUT_DISPLAY_CHANGE_ZOOM:
+    	case VOUT_DISPLAY_CHANGE_DISPLAY_FILLED:
+    	case VOUT_DISPLAY_CHANGE_SOURCE_ASPECT:
+    	{
+        	const vout_display_cfg_t *cfg;
+        	const video_format_t *source;
+
+	        if (query == VOUT_DISPLAY_CHANGE_SOURCE_ASPECT) {
+    	        source = va_arg(args, const video_format_t *);
+        	    cfg = vd->cfg;
+        	} else {
+            	source = &vd->source;
+            	cfg = va_arg(args, const vout_display_cfg_t *);
+        	}
+        	vout_display_SendEventPicturesInvalid(vd);
+        	return VLC_SUCCESS;
+    	}
+	    case VOUT_DISPLAY_RESET_PICTURES:
+	    {
+            vout_display_place_t place;
+            video_format_t src;
+
+            vout_display_PlacePicture(&place, &vd->source, vd->cfg, false);
+            video_format_ApplyRotation(&src, &vd->source);
+
+            vd->fmt.i_width  = src.i_width;
+            vd->fmt.i_height = src.i_height;
+            vd->fmt.i_visible_width  = place.width;
+            vd->fmt.i_visible_height = place.height;
+            vd->fmt.i_x_offset = place.x;
+            vd->fmt.i_y_offset = place.y;
+
+			if (sys->pool)
+	            picture_pool_Release(sys->pool);
+
+	        sys->pool = NULL;
+  
+	        return VLC_SUCCESS;
+	    }
+    	case VOUT_DISPLAY_CHANGE_SOURCE_CROP:
+        	return VLC_EGENERIC;
+    	case VOUT_DISPLAY_CHANGE_FULLSCREEN:
+    	{
+        	bool fs = va_arg(args, int);
+			sys->win->SetFullscreen(fs);
+	        return VLC_SUCCESS;
+    	}
+
+	    default:
+    	    msg_Err(vd, "Unsupported query");
+        	return VLC_EGENERIC;
+    }
+}
+
+static void Manage( vout_display_t *vd )
+{
+	vout_display_sys_t *sys = vd->sys;
+	
+	while (BMessage* request = sys->win->Queue()->NextMessage()) {
+		switch (request->what) {
+			case B_QUIT_REQUESTED:
+			{
+				vout_display_SendEventKey(vd, KEY_MEDIA_STOP);
+				break;
+			}
+			case B_MOUSE_WHEEL_CHANGED:
+			{
+				uint32 modifiers = 0;
+				request->FindInt32("modifiers", (int32 *)&modifiers);
+
+				int code = 0;
+
+				if (modifiers & B_SHIFT_KEY)
+					code |= KEY_MODIFIER_SHIFT;
+				if (modifiers & B_CONTROL_KEY)
+					code |= KEY_MODIFIER_ALT;
+				if (modifiers & B_COMMAND_KEY)
+					code |= KEY_MODIFIER_CTRL;
+
+				float dx = request->FindFloat("be:wheel_delta_x");
+				float dy = request->FindFloat("be:wheel_delta_y");
+				if (dx > 0.1)
+					vout_display_SendEventKey(vd, KEY_MOUSEWHEELRIGHT | code);
+				if (dx < -0.1)
+					vout_display_SendEventKey(vd, KEY_MOUSEWHEELLEFT | code);
+				if (dy > 0.1)
+					vout_display_SendEventKey(vd, KEY_MOUSEWHEELDOWN | code);
+				if (dy < -0.1)
+					vout_display_SendEventKey(vd, KEY_MOUSEWHEELUP | code);
+				break;
+			}
+			case B_MOUSE_DOWN:
+			{
+				uint32 buttons = 0;
+				request->FindInt32("buttons", (int32 *)&buttons);
+
+	            for (int i = 0; platformHaikuMouseButtons[i].haiku != -1; i++) {
+	                if (buttons & platformHaikuMouseButtons[i].haiku)
+                        vout_display_SendEventMousePressed(vd, platformHaikuMouseButtons[i].vlc);
+	            }
+
+				sys->lastMouseButtons = buttons;
+				break;
+			}
+			case B_MOUSE_UP:
+			{
+				uint32 buttons = 0;
+				request->FindInt32("buttons", (int32 *)&buttons);
+
+	            for (int i = 0; platformHaikuMouseButtons[i].haiku != -1; i++) {
+	                if (sys->lastMouseButtons & platformHaikuMouseButtons[i].haiku && !(buttons & platformHaikuMouseButtons[i].haiku))
+                        vout_display_SendEventMouseReleased(vd, platformHaikuMouseButtons[i].vlc);
+	            }
+				break;
+			}
+			case B_MOUSE_MOVED:
+			{
+				uint32 transit;
+				request->FindInt32("be:transit", (int32*)&transit);
+				if (transit == B_ENTERED_VIEW || transit == B_INSIDE_VIEW) {
+					BPoint where;
+					request->FindPoint("be:view_where", &where);
+		            vout_display_place_t place;
+        		    vout_display_PlacePicture(&place, &vd->source, vd->cfg, false);
+					where.x = (where.x - place.x) * vd->source.i_visible_width / place.width;
+					where.y = (where.y - place.y) * vd->source.i_visible_height / place.height;
+					vout_display_SendEventMouseMoved(vd, where.x, where.y);
+					sys->win->HideCursor(false);
+				}
+				break;
+			}
+			case B_ZOOM:
+			{
+//				vout_display_SendEventFullscreen(vd, true, false);
+				vout_display_SendEventKey(vd, 'f');
+				break;
+			}
+			case B_WINDOW_RESIZED:
+			{
+				int width = request->FindInt32("width");
+				int height = request->FindInt32("height");
+				vout_display_SendEventDisplaySize(vd, width + 1, height + 1);
+				break;
+			}
+			case B_UNMAPPED_KEY_DOWN:
+			case B_KEY_DOWN:
+			{
+				uint32 modifiers = request->FindInt32("modifiers");
+				uint32 key = request->FindInt32("key");
+
+				int code = KEY_UNSET;
+				int i = 0;
+				while (platformHaikuScanCodes[i]) {
+					if ( key == platformHaikuScanCodes[i + 1]) {
+						code = platformHaikuScanCodes[i];
+						break;
+					}
+					i += 2;
+				}
+				if (modifiers & B_SHIFT_KEY)
+					code |= KEY_MODIFIER_SHIFT;
+				if (modifiers & B_CONTROL_KEY)
+					code |= KEY_MODIFIER_ALT;
+				if (modifiers & B_COMMAND_KEY)
+					code |= KEY_MODIFIER_CTRL;
+
+				if (code != KEY_UNSET) {
+					vout_display_SendEventKey(vd, code);
+				}
+				break;
+			}
+			default:
+				break;
+		}
+		delete request;
+	}
+}
diff --git a/src/Makefile.am b/src/Makefile.am
index 502990c..f1c1a85 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -411,6 +411,16 @@ libvlccore_la_SOURCES += \
 	linux/dirs.c \
 	linux/thread.c
 else
+if HAVE_HAIKU
+libvlccore_la_SOURCES += \
+	haiku/dirs.cpp \
+	haiku/specific.c \
+	posix/error.c \
+	posix/netconf.c \
+	posix/getaddrinfo.c \
+	posix/thread.c
+libvlccore_la_LIBADD += -lgnu -lnetwork
+else
 if HAVE_DARWIN
 libvlccore_la_SOURCES += \
 	darwin/dirs.c \
@@ -444,6 +454,7 @@ endif
 endif
 endif
 endif
+endif
 
 if ENABLE_SOUT
 libvlccore_la_SOURCES += \
diff --git a/src/haiku/dirs.cpp b/src/haiku/dirs.cpp
new file mode 100644
index 0000000..712bf08
--- /dev/null
+++ b/src/haiku/dirs.cpp
@@ -0,0 +1,83 @@
+/*****************************************************************************
+ * dirs.c: XDG directories configuration
+ *****************************************************************************
+ * Copyright (C) 2001-2007 VLC authors and VideoLAN
+ * Copyright © 2007-2009 Rémi Denis-Courmont
+ *
+ * Authors: Gildas Bazin <gbazin@videolan.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <vlc_common.h>
+
+#include "../libvlc.h"
+#include "config/configuration.h"
+
+#include <unistd.h>
+#include <libgen.h>
+
+#include <FindDirectory.h>
+
+char *config_GetDataDir (void)
+{
+    return strdup (PKGDATADIR);
+}
+
+char *config_GetLibDir (void)
+{
+    return strdup (PKGLIBDIR);
+}
+
+static char *config_GetHaikuDir (directory_which which, char *leaf = NULL)
+{
+	char path[B_PATH_NAME_LENGTH];
+	find_directory(which, 0, false, path, B_PATH_NAME_LENGTH);
+	if (leaf != NULL) {
+		strcat(path, "/");
+		strcat(path, leaf);
+	}
+	return strdup (path);
+}
+
+char *config_GetUserDir (vlc_userdir_t type)
+{
+    switch (type)
+    {
+        case VLC_HOME_DIR:
+            break;
+        case VLC_CONFIG_DIR:
+        case VLC_DATA_DIR:
+            return config_GetHaikuDir (B_USER_SETTINGS_DIRECTORY, "vlc");
+        case VLC_CACHE_DIR:
+			return config_GetHaikuDir (B_USER_CACHE_DIRECTORY, "vlc");
+
+        case VLC_DESKTOP_DIR:
+        	return config_GetHaikuDir (B_DESKTOP_DIRECTORY);
+        case VLC_DOWNLOAD_DIR:
+        case VLC_TEMPLATES_DIR:
+        case VLC_PUBLICSHARE_DIR:
+        case VLC_DOCUMENTS_DIR:
+        case VLC_MUSIC_DIR:
+        case VLC_PICTURES_DIR:
+        case VLC_VIDEOS_DIR:
+			break;
+    }
+    return config_GetHaikuDir (B_USER_DIRECTORY);
+}
diff --git a/src/haiku/specific.c b/src/haiku/specific.c
new file mode 100644
index 0000000..1c26497
--- /dev/null
+++ b/src/haiku/specific.c
@@ -0,0 +1,35 @@
+/*****************************************************************************
+ * specific.c: stubs for POSIX OS-specific initialization
+ *****************************************************************************
+ * Copyright © 2008 Rémi Denis-Courmont
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <vlc_common.h>
+#include "../libvlc.h"
+#include "../lib/libvlc_internal.h"
+
+void system_Init (void)
+{
+}
+
+void system_Configure(libvlc_int_t *libvlc, int argc, const char *const argv[])
+{
+}
diff --git a/src/modules/bank.c b/src/modules/bank.c
index 2e67a0d..e927851 100644
--- a/src/modules/bank.c
+++ b/src/modules/bank.c
@@ -172,6 +172,7 @@ static vlc_plugin_t *module_InitStatic(vlc_plugin_cb entry)
     return lib;
 }
 
+/* Haiku bug #8288
 #if defined(__ELF__) || !HAVE_DYNAMIC_PLUGINS
 # ifdef __GNUC__
 __attribute__((weak))
@@ -192,9 +193,9 @@ static void module_InitStaticModules(void)
             vlc_plugin_store(lib);
     }
 }
-#else
+#else */
 static void module_InitStaticModules(void) { }
-#endif
+//#endif
 
 #ifdef HAVE_DYNAMIC_PLUGINS
 static const char vlc_entry_name[] = "vlc_entry" MODULE_SUFFIX;
diff --git a/src/network/io.c b/src/network/io.c
index 603624a..256030b 100644
--- a/src/network/io.c
+++ b/src/network/io.c
@@ -192,7 +192,9 @@ int *net_Listen (vlc_object_t *p_this, const char *psz_host,
         switch (ptr->ai_socktype)
         {
             case SOCK_STREAM:
+#ifdef SOCK_RDM
             case SOCK_RDM:
+#endif
             case SOCK_SEQPACKET:
 #ifdef SOCK_DCCP
             case SOCK_DCCP:
diff --git a/src/posix/error.c b/src/posix/error.c
index db51004..9ae11dd 100644
--- a/src/posix/error.c
+++ b/src/posix/error.c
@@ -48,7 +48,7 @@ static const char *vlc_strerror_l(int errnum, const char *lname)
         errno = saved_errno;
     }
 
-    const char *buf = strerror_l(errnum, loc);
+    const char *buf = strerror(errnum);
 
     freelocale(loc);
     return buf;
diff --git a/src/video_output/display.c b/src/video_output/display.c
index ba4dba0..49c7901 100644
--- a/src/video_output/display.c
+++ b/src/video_output/display.c
@@ -341,7 +341,7 @@ typedef struct {
 
     bool ch_zoom;
     vlc_rational_t zoom;
-#if defined(_WIN32) || defined(__OS2__)
+#if defined(_WIN32) || defined(__OS2__) || defined(__HAIKU__)
     unsigned width_saved;
     unsigned height_saved;
     bool ch_fullscreen;
@@ -600,7 +600,7 @@ static void VoutDisplayEvent(vout_display_t *vd, int event, va_list args)
                                      va_arg(args, const vlc_viewpoint_t *));
         break;
 
-#if defined(_WIN32) || defined(__OS2__)
+#if defined(_WIN32) || defined(__OS2__) || defined(__HAIKU__)
     case VOUT_DISPLAY_EVENT_FULLSCREEN: {
         const int is_fullscreen = (int)va_arg(args, int);
         const bool window_fullscreen = va_arg(args, int);
@@ -760,7 +760,7 @@ bool vout_ManageDisplay(vout_display_t *vd, bool allow_reset_pictures)
     for (;;) {
 
         vlc_mutex_lock(&osys->lock);
-#if defined(_WIN32) || defined(__OS2__)
+#if defined(_WIN32) || defined(__OS2__) || defined(__HAIKU__)
         bool ch_fullscreen  = osys->ch_fullscreen;
         bool is_fullscreen  = osys->is_fullscreen;
         osys->ch_fullscreen = false;
@@ -789,7 +789,7 @@ bool vout_ManageDisplay(vout_display_t *vd, bool allow_reset_pictures)
             !reset_pictures &&
             osys->is_display_filled == osys->cfg.is_display_filled &&
             !osys->ch_zoom &&
-#if defined(_WIN32) || defined(__OS2__)
+#if defined(_WIN32) || defined(__OS2__) || defined(__HAIKU__)
             !ch_fullscreen &&
             !ch_wm_state &&
 #endif
@@ -806,7 +806,7 @@ bool vout_ManageDisplay(vout_display_t *vd, bool allow_reset_pictures)
         }
 
         /* */
-#if defined(_WIN32) || defined(__OS2__)
+#if defined(_WIN32) || defined(__OS2__) || defined(__HAIKU__)
         if (ch_fullscreen) {
             if (osys->window_fullscreen
              || vout_display_Control(vd, VOUT_DISPLAY_CHANGE_FULLSCREEN,
@@ -826,7 +826,7 @@ bool vout_ManageDisplay(vout_display_t *vd, bool allow_reset_pictures)
 
         /* */
         if (ch_display_size) {
-#if defined(_WIN32) || defined(__OS2__)
+#if defined(_WIN32) || defined(__OS2__) || defined(__HAIKU__)
             osys->width_saved  = osys->cfg.display.width;
             osys->height_saved = osys->cfg.display.height;
 #endif
@@ -852,7 +852,7 @@ bool vout_ManageDisplay(vout_display_t *vd, bool allow_reset_pictures)
 
             vout_display_Control(vd, VOUT_DISPLAY_CHANGE_ZOOM, &osys->cfg);
         }
-#if defined(_WIN32) || defined(__OS2__)
+#if defined(_WIN32) || defined(__OS2__) || defined(__HAIKU__)
         /* */
         if (ch_wm_state) {
             if (vout_display_Control(vd, VOUT_DISPLAY_CHANGE_WINDOW_STATE, wm_state)) {
@@ -1154,7 +1154,7 @@ static vout_display_t *DisplayNew(vout_thread_t *vout,
 
     osys->zoom.num = cfg->zoom.num;
     osys->zoom.den = cfg->zoom.den;
-#if defined(_WIN32) || defined(__OS2__)
+#if defined(_WIN32) || defined(__OS2__) || defined(__HAIKU__)
     osys->is_fullscreen  = cfg->is_fullscreen;
     osys->width_saved    = cfg->display.width;
     osys->height_saved   = cfg->display.height;
@@ -1228,7 +1228,7 @@ void vout_DeleteDisplay(vout_display_t *vd, vout_display_state_t *state)
     if (state) {
         if (!osys->is_splitter)
             state->cfg = osys->cfg;
-#if defined(_WIN32) || defined(__OS2__)
+#if defined(_WIN32) || defined(__OS2__) || defined(__HAIKU__)
         state->wm_state = osys->wm_state;
 #endif
         state->sar = osys->sar_initial;
diff --git a/src/video_output/video_output.c b/src/video_output/video_output.c
index d936d42..8b9a976 100644
--- a/src/video_output/video_output.c
+++ b/src/video_output/video_output.c
@@ -570,7 +570,7 @@ void vout_ControlChangeViewpoint(vout_thread_t *vout,
 static void VoutGetDisplayCfg(vout_thread_t *vout, vout_display_cfg_t *cfg, const char *title)
 {
     /* Load configuration */
-#if defined(_WIN32) || defined(__OS2__)
+#if defined(_WIN32) || defined(__OS2__) || defined(__HAIKU__)
     cfg->is_fullscreen = var_GetBool(vout, "fullscreen")
                          || var_GetBool(vout, "video-wallpaper");
 #endif
@@ -1363,7 +1363,7 @@ static void ThreadChangeFullscreen(vout_thread_t *vout, bool fullscreen)
 {
     vout_window_t *window = vout->p->window;
 
-#if !defined(_WIN32) && !defined(__OS2__)
+#if !defined(_WIN32) && !defined(__OS2__) && !defined(__HAIKU__)
     if (window != NULL)
         vout_window_SetFullScreen(window, fullscreen);
 #else
@@ -1383,7 +1383,7 @@ static void ThreadChangeWindowState(vout_thread_t *vout, unsigned state)
 
     if (window != NULL)
         vout_window_SetState(window, state);
-#if defined(_WIN32) || defined(__OS2__)
+#if defined(_WIN32) || defined(__OS2__) || defined(__HAIKU__)
     else /* FIXME: remove this event */
     if (vout->p->display.vd != NULL)
         vout_display_SendWindowState(vout->p->display.vd, state);
@@ -1514,7 +1514,7 @@ static int ThreadStart(vout_thread_t *vout, vout_display_state_t *state)
     if (!state) {
         VoutGetDisplayCfg(vout, &state_default.cfg, vout->p->display.title);
 
-#if defined(_WIN32) || defined(__OS2__)
+#if defined(_WIN32) || defined(__OS2__) || defined(__HAIKU__)
         bool below = var_InheritBool(vout, "video-wallpaper");
         bool above = var_InheritBool(vout, "video-on-top");
 
@@ -1643,7 +1643,7 @@ static int ThreadReinit(vout_thread_t *vout,
 
     vout_ReinitInterlacingSupport(vout);
 
-#if defined(_WIN32) || defined(__OS2__)
+#if defined(_WIN32) || defined(__OS2__) || defined(__HAIKU__)
     if (!state.cfg.is_fullscreen)
 #endif
     {
diff --git a/src/video_output/window.c b/src/video_output/window.c
index ff482dc..fe3c06c 100644
--- a/src/video_output/window.c
+++ b/src/video_output/window.c
@@ -79,7 +79,7 @@ vout_window_t *vout_window_New(vlc_object_t *obj, const char *module,
     /* Hook for screensaver inhibition */
     if (var_InheritBool(obj, "disable-screensaver") &&
         (window->type == VOUT_WINDOW_TYPE_XID || window->type == VOUT_WINDOW_TYPE_HWND
-      || window->type == VOUT_WINDOW_TYPE_WAYLAND))
+      || window->type == VOUT_WINDOW_TYPE_WAYLAND || window->type == VOUT_WINDOW_TYPE_HAIKU))
     {
         w->inhibit = vlc_inhibit_Create(VLC_OBJECT (window));
         if (w->inhibit != NULL)
-- 
2.30.0

