Phonon Backend using VLC
authorJean-Baptiste Kempf <jb@videolan.org>
Sat, 8 Aug 2009 19:28:12 +0000 (21:28 +0200)
committerJean-Baptiste Kempf <jb@videolan.org>
Sun, 9 Aug 2009 12:44:30 +0000 (14:44 +0200)
This still uses CMake, because I am still lazy.
This has been tested on Linux, but I would like to port it to win32 (and so CMake might not be the best)
This is basically a copy of the KDE-playground code and started as the GSoC of last summer

41 files changed:
bindings/phonon/.gitignore [new file with mode: 0644]
bindings/phonon/cmake/modules/FindAutomoc4.cmake [new file with mode: 0644]
bindings/phonon/cmake/modules/FindPackageHandleStandardArgs.cmake [new file with mode: 0644]
bindings/phonon/cmake/modules/FindVLC.cmake [new file with mode: 0644]
bindings/phonon/cmake/modules/MacroEnsureVersion.cmake [new file with mode: 0644]
bindings/phonon/cmake/modules/MacroLogFeature.cmake [new file with mode: 0644]
bindings/phonon/cmake/modules/MacroOptionalFindPackage.cmake [new file with mode: 0644]
bindings/phonon/cmake/modules/PhononMacros.cmake [new file with mode: 0644]
bindings/phonon/vlc/.gitignore [new file with mode: 0644]
bindings/phonon/vlc/AUTHORS [new file with mode: 0644]
bindings/phonon/vlc/audiooutput.cpp [new file with mode: 0644]
bindings/phonon/vlc/audiooutput.h [new file with mode: 0644]
bindings/phonon/vlc/backend.cpp [new file with mode: 0644]
bindings/phonon/vlc/backend.h [new file with mode: 0644]
bindings/phonon/vlc/devicemanager.cpp [new file with mode: 0644]
bindings/phonon/vlc/devicemanager.h [new file with mode: 0644]
bindings/phonon/vlc/effect.cpp [new file with mode: 0644]
bindings/phonon/vlc/effect.h [new file with mode: 0644]
bindings/phonon/vlc/effectmanager.cpp [new file with mode: 0644]
bindings/phonon/vlc/effectmanager.h [new file with mode: 0644]
bindings/phonon/vlc/mediacontroller.cpp [new file with mode: 0644]
bindings/phonon/vlc/mediacontroller.h [new file with mode: 0644]
bindings/phonon/vlc/mediaobject.cpp [new file with mode: 0644]
bindings/phonon/vlc/mediaobject.h [new file with mode: 0644]
bindings/phonon/vlc/seekstack.cpp [new file with mode: 0644]
bindings/phonon/vlc/seekstack.h [new file with mode: 0644]
bindings/phonon/vlc/sinknode.cpp [new file with mode: 0644]
bindings/phonon/vlc/sinknode.h [new file with mode: 0644]
bindings/phonon/vlc/videowidget.cpp [new file with mode: 0644]
bindings/phonon/vlc/videowidget.h [new file with mode: 0644]
bindings/phonon/vlc/vlc.desktop [new file with mode: 0644]
bindings/phonon/vlc/vlcloader.cpp [new file with mode: 0644]
bindings/phonon/vlc/vlcloader.h [new file with mode: 0644]
bindings/phonon/vlc/vlcmediacontroller.cpp [new file with mode: 0644]
bindings/phonon/vlc/vlcmediacontroller.h [new file with mode: 0644]
bindings/phonon/vlc/vlcmediaobject.cpp [new file with mode: 0644]
bindings/phonon/vlc/vlcmediaobject.h [new file with mode: 0644]
bindings/phonon/vlc/vlcvideowidget.cpp [new file with mode: 0644]
bindings/phonon/vlc/vlcvideowidget.h [new file with mode: 0644]
bindings/phonon/vlc/widgetnopaintevent.cpp [new file with mode: 0644]
bindings/phonon/vlc/widgetnopaintevent.h [new file with mode: 0644]

diff --git a/bindings/phonon/.gitignore b/bindings/phonon/.gitignore
new file mode 100644 (file)
index 0000000..dc81908
--- /dev/null
@@ -0,0 +1,3 @@
+.svn
+Makefile
+CMakeTmp
diff --git a/bindings/phonon/cmake/modules/FindAutomoc4.cmake b/bindings/phonon/cmake/modules/FindAutomoc4.cmake
new file mode 100644 (file)
index 0000000..2b88e09
--- /dev/null
@@ -0,0 +1,81 @@
+# - Try to find automoc4
+# Once done this will define
+#
+#  AUTOMOC4_FOUND - automoc4 has been found
+#  AUTOMOC4_EXECUTABLE - the automoc4 tool
+#  AUTOMOC4_VERSION - the full version of automoc4
+#  AUTOMOC4_VERSION_MAJOR, AUTOMOC4_VERSION_MINOR, AUTOMOC4_VERSION_PATCH - AUTOMOC4_VERSION
+#                     broken into its components
+#
+# It also adds the following macros
+#  AUTOMOC4(<target> <SRCS_VAR>)
+#    Use this to run automoc4 on all files contained in the list <SRCS_VAR>.
+#
+#  AUTOMOC4_MOC_HEADERS(<target> header1.h header2.h ...)
+#    Use this to add more header files to be processed with automoc4.
+#
+#  AUTOMOC4_ADD_EXECUTABLE(<target_NAME> src1 src2 ...)
+#    This macro does the same as ADD_EXECUTABLE, but additionally
+#    adds automoc4 handling for all source files.
+#
+# AUTOMOC4_ADD_LIBRARY(<target_NAME> src1 src2 ...)
+#    This macro does the same as ADD_LIBRARY, but additionally
+#    adds automoc4 handling for all source files.
+
+# Internal helper macro, may change or be removed anytime:
+# _ADD_AUTOMOC4_TARGET(<target_NAME> <SRCS_VAR>)
+#
+# Since version 0.9.88:
+# The following two macros are only to be used for KDE4 projects
+# and do something which makes sure automoc4 works for KDE. Don't
+# use them anywhere else.
+# _AUTOMOC4_KDE4_PRE_TARGET_HANDLING(<target_NAME> <SRCS_VAR>)
+# _AUTOMOC4_KDE4_POST_TARGET_HANDLING(<target_NAME>)
+
+
+# Copyright (c) 2008-2009, Alexander Neundorf, <neundorf@kde.org>
+#
+# Redistribution and use is allowed according to the terms of the BSD license.
+# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
+
+
+# check if we are inside KDESupport and automoc is enabled
+if("${KDESupport_SOURCE_DIR}" STREQUAL "${CMAKE_SOURCE_DIR}")
+   # when building this project as part of kdesupport
+   set(AUTOMOC4_CONFIG_FILE "${KDESupport_SOURCE_DIR}/automoc/Automoc4Config.cmake")
+else("${KDESupport_SOURCE_DIR}" STREQUAL "${CMAKE_SOURCE_DIR}")
+   # when building this project outside kdesupport
+
+   # CMAKE_[SYSTEM_]PREFIX_PATH exists starting with cmake 2.6.0
+   file(TO_CMAKE_PATH "$ENV{CMAKE_PREFIX_PATH}" _env_CMAKE_PREFIX_PATH)
+   file(TO_CMAKE_PATH "$ENV{CMAKE_LIBRARY_PATH}" _env_CMAKE_LIBRARY_PATH)
+
+   find_file(AUTOMOC4_CONFIG_FILE NAMES Automoc4Config.cmake
+             PATH_SUFFIXES automoc4 lib/automoc4 lib64/automoc4
+             PATHS ${_env_CMAKE_PREFIX_PATH} ${CMAKE_PREFIX_PATH} ${CMAKE_SYSTEM_PREFIX_PATH}
+                   ${_env_CMAKE_LIBRARY_PATH} ${CMAKE_LIBRARY_PATH} ${CMAKE_SYSTEM_LIBRARY_PATH}
+                   ${CMAKE_INSTALL_PREFIX}
+             NO_DEFAULT_PATH )
+endif("${KDESupport_SOURCE_DIR}" STREQUAL "${CMAKE_SOURCE_DIR}")
+
+
+if(AUTOMOC4_CONFIG_FILE)
+   include(${AUTOMOC4_CONFIG_FILE})
+   set(AUTOMOC4_FOUND TRUE)
+else(AUTOMOC4_CONFIG_FILE)
+   set(AUTOMOC4_FOUND FALSE)
+endif(AUTOMOC4_CONFIG_FILE)
+
+if (AUTOMOC4_FOUND)
+   if (NOT Automoc4_FIND_QUIETLY)
+      message(STATUS "Found Automoc4: ${AUTOMOC4_EXECUTABLE}")
+   endif (NOT Automoc4_FIND_QUIETLY)
+else (AUTOMOC4_FOUND)
+   if (Automoc4_FIND_REQUIRED)
+      message(FATAL_ERROR "Did not find automoc4 (part of kdesupport).")
+   else (Automoc4_FIND_REQUIRED)
+      if (NOT Automoc4_FIND_QUIETLY)
+         message(STATUS "Did not find automoc4 (part of kdesupport).")
+      endif (NOT Automoc4_FIND_QUIETLY)
+   endif (Automoc4_FIND_REQUIRED)
+endif (AUTOMOC4_FOUND)
diff --git a/bindings/phonon/cmake/modules/FindPackageHandleStandardArgs.cmake b/bindings/phonon/cmake/modules/FindPackageHandleStandardArgs.cmake
new file mode 100644 (file)
index 0000000..9613b3d
--- /dev/null
@@ -0,0 +1,60 @@
+# FIND_PACKAGE_HANDLE_STANDARD_ARGS(NAME (DEFAULT_MSG|"Custom failure message") VAR1 ... )
+#
+# This macro is intended to be used in FindXXX.cmake modules files.
+# It handles the REQUIRED and QUIET argument to FIND_PACKAGE() and
+# it also sets the <UPPERCASED_NAME>_FOUND variable.
+# The package is found if all variables listed are TRUE.
+# Example:
+#
+#    FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibXml2 DEFAULT_MSG LIBXML2_LIBRARIES LIBXML2_INCLUDE_DIR)
+#
+# LibXml2 is considered to be found, if both LIBXML2_LIBRARIES and
+# LIBXML2_INCLUDE_DIR are valid. Then also LIBXML2_FOUND is set to TRUE.
+# If it is not found and REQUIRED was used, it fails with FATAL_ERROR,
+# independent whether QUIET was used or not.
+#
+# If it is found, the location is reported using the VAR1 argument, so
+# here a message "Found LibXml2: /usr/lib/libxml2.so" will be printed out.
+# If the second argument is DEFAULT_MSG, the message in the failure case will
+# be "Could NOT find LibXml2", if you don't like this message you can specify
+# your own custom failure message there.
+
+MACRO(FIND_PACKAGE_HANDLE_STANDARD_ARGS _NAME _FAIL_MSG _VAR1 )
+
+  IF("${_FAIL_MSG}" STREQUAL "DEFAULT_MSG")
+    IF (${_NAME}_FIND_REQUIRED)
+      SET(_FAIL_MESSAGE "Could not find REQUIRED package ${_NAME}")
+    ELSE (${_NAME}_FIND_REQUIRED)
+      SET(_FAIL_MESSAGE "Could not find OPTIONAL package ${_NAME}")
+    ENDIF (${_NAME}_FIND_REQUIRED)
+  ELSE("${_FAIL_MSG}" STREQUAL "DEFAULT_MSG")
+    SET(_FAIL_MESSAGE "${_FAIL_MSG}")
+  ENDIF("${_FAIL_MSG}" STREQUAL "DEFAULT_MSG")
+
+  STRING(TOUPPER ${_NAME} _NAME_UPPER)
+
+  SET(${_NAME_UPPER}_FOUND TRUE)
+  IF(NOT ${_VAR1})
+    SET(${_NAME_UPPER}_FOUND FALSE)
+  ENDIF(NOT ${_VAR1})
+
+  FOREACH(_CURRENT_VAR ${ARGN})
+    IF(NOT ${_CURRENT_VAR})
+      SET(${_NAME_UPPER}_FOUND FALSE)
+    ENDIF(NOT ${_CURRENT_VAR})
+  ENDFOREACH(_CURRENT_VAR)
+
+  IF (${_NAME_UPPER}_FOUND)
+    IF (NOT ${_NAME}_FIND_QUIETLY)
+        MESSAGE(STATUS "Found ${_NAME}: ${${_VAR1}}")
+    ENDIF (NOT ${_NAME}_FIND_QUIETLY)
+  ELSE (${_NAME_UPPER}_FOUND)
+    IF (${_NAME}_FIND_REQUIRED)
+        MESSAGE(FATAL_ERROR "${_FAIL_MESSAGE}")
+    ELSE (${_NAME}_FIND_REQUIRED)
+      IF (NOT ${_NAME}_FIND_QUIETLY)
+        MESSAGE(STATUS "${_FAIL_MESSAGE}")
+      ENDIF (NOT ${_NAME}_FIND_QUIETLY)
+    ENDIF (${_NAME}_FIND_REQUIRED)
+  ENDIF (${_NAME_UPPER}_FOUND)
+ENDMACRO(FIND_PACKAGE_HANDLE_STANDARD_ARGS)
diff --git a/bindings/phonon/cmake/modules/FindVLC.cmake b/bindings/phonon/cmake/modules/FindVLC.cmake
new file mode 100644 (file)
index 0000000..5d2b379
--- /dev/null
@@ -0,0 +1,54 @@
+# - Try to find VLC library
+# Once done this will define
+#
+#  VLC_FOUND - system has VLC
+#  VLC_INCLUDE_DIR - The VLC include directory
+#  VLC_LIBRARIES - The libraries needed to use VLC
+#  VLC_DEFINITIONS - Compiler switches required for using VLC
+#
+# Copyright (C) 2008, Tanguy Krotoff <tkrotoff@gmail.com>
+# Copyright (C) 2008, Lukas Durfina <lukas.durfina@gmail.com>
+# Copyright (c) 2009, Fathi Boudra <fboudra@gmail.com>
+#
+# Redistribution and use is allowed according to the terms of the BSD license.
+# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
+#
+
+if(VLC_INCLUDE_DIR AND VLC_LIBRARIES)
+   # in cache already
+   set(VLC_FIND_QUIETLY TRUE)
+endif(VLC_INCLUDE_DIR AND VLC_LIBRARIES)
+
+# use pkg-config to get the directories and then use these values
+# in the FIND_PATH() and FIND_LIBRARY() calls
+if(NOT WIN32)
+  find_package(PkgConfig)
+  pkg_check_modules(VLC libvlc>=1.0.0)
+  set(VLC_DEFINITIONS ${VLC_CFLAGS})
+endif(NOT WIN32)
+
+# TODO add argument support to pass version on find_package
+include(MacroEnsureVersion)
+macro_ensure_version(1.0.0 ${VLC_VERSION} VLC_VERSION_OK)
+if(VLC_VERSION_OK)
+  set(VLC_FOUND TRUE)
+  message(STATUS "VLC library found")
+else(VLC_VERSION_OK)
+  set(VLC_FOUND FALSE)
+  message(FATAL_ERROR "VLC library not found")
+endif(VLC_VERSION_OK)
+
+find_path(VLC_INCLUDE_DIR
+          NAMES vlc.h
+          PATHS ${VLC_INCLUDE_DIRS}
+          PATH_SUFFIXES vlc)
+
+find_library(VLC_LIBRARIES
+             NAMES vlc
+             PATHS ${VLC_LIBRARY_DIRS})
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(VLC DEFAULT_MSG VLC_INCLUDE_DIR VLC_LIBRARIES)
+
+# show the VLC_INCLUDE_DIR and VLC_LIBRARIES variables only in the advanced view
+mark_as_advanced(VLC_INCLUDE_DIR VLC_LIBRARIES)
diff --git a/bindings/phonon/cmake/modules/MacroEnsureVersion.cmake b/bindings/phonon/cmake/modules/MacroEnsureVersion.cmake
new file mode 100644 (file)
index 0000000..6797e5b
--- /dev/null
@@ -0,0 +1,117 @@
+# This file defines the following macros for developers to use in ensuring
+# that installed software is of the right version:
+#
+# MACRO_ENSURE_VERSION        - test that a version number is greater than
+#                               or equal to some minimum
+# MACRO_ENSURE_VERSION_RANGE - test that a version number is greater than
+#                               or equal to some minimum and less than some
+#                               maximum
+# MACRO_ENSURE_VERSION2       - deprecated, do not use in new code
+#
+
+# MACRO_ENSURE_VERSION
+# This macro compares version numbers of the form "x.y.z" or "x.y"
+# MACRO_ENSURE_VERSION( FOO_MIN_VERSION FOO_VERSION_FOUND FOO_VERSION_OK)
+# will set FOO_VERSION_OK to true if FOO_VERSION_FOUND >= FOO_MIN_VERSION
+# Leading and trailing text is ok, e.g.
+# MACRO_ENSURE_VERSION( "2.5.31" "flex 2.5.4a" VERSION_OK)
+# which means 2.5.31 is required and "flex 2.5.4a" is what was found on the system
+
+# Copyright (c) 2006, David Faure, <faure@kde.org>
+# Copyright (c) 2007, Will Stephenson <wstephenson@kde.org>
+#
+# Redistribution and use is allowed according to the terms of the BSD license.
+# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
+
+# MACRO_ENSURE_VERSION_RANGE
+# This macro ensures that a version number of the form
+# "x.y.z" or "x.y" falls within a range defined by
+# min_version <= found_version < max_version.
+# If this expression holds, FOO_VERSION_OK will be set TRUE
+#
+# Example: MACRO_ENSURE_VERSION_RANGE3( "0.1.0" ${FOOCODE_VERSION} "0.7.0" FOO_VERSION_OK )
+#
+# This macro will break silently if any of x,y,z are greater than 100.
+#
+# Copyright (c) 2007, Will Stephenson <wstephenson@kde.org>
+#
+# Redistribution and use is allowed according to the terms of the BSD license.
+# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
+
+# NORMALIZE_VERSION
+# Helper macro to convert version numbers of the form "x.y.z"
+# to an integer equal to 10^4 * x + 10^2 * y + z
+#
+# This macro will break silently if any of x,y,z are greater than 100.
+#
+# Copyright (c) 2006, David Faure, <faure@kde.org>
+# Copyright (c) 2007, Will Stephenson <wstephenson@kde.org>
+#
+# Redistribution and use is allowed according to the terms of the BSD license.
+# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
+
+# CHECK_RANGE_INCLUSIVE_LOWER
+# Helper macro to check whether x <= y < z
+#
+# Copyright (c) 2007, Will Stephenson <wstephenson@kde.org>
+#
+# Redistribution and use is allowed according to the terms of the BSD license.
+# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
+
+
+MACRO(NORMALIZE_VERSION _requested_version _normalized_version)
+    STRING(REGEX MATCH "[^0-9]*[0-9]+\\.[0-9]+\\.[0-9]+.*" _threePartMatch "${_requested_version}")
+    if (_threePartMatch)
+    # parse the parts of the version string
+        STRING(REGEX REPLACE "[^0-9]*([0-9]+)\\.[0-9]+\\.[0-9]+.*" "\\1" _major_vers "${_requested_version}")
+        STRING(REGEX REPLACE "[^0-9]*[0-9]+\\.([0-9]+)\\.[0-9]+.*" "\\1" _minor_vers "${_requested_version}")
+        STRING(REGEX REPLACE "[^0-9]*[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" _patch_vers "${_requested_version}")
+    else (_threePartMatch)
+        STRING(REGEX REPLACE "([0-9]+)\\.[0-9]+" "\\1" _major_vers "${_requested_version}")
+        STRING(REGEX REPLACE "[0-9]+\\.([0-9]+)" "\\1" _minor_vers "${_requested_version}")
+        set(_patch_vers "0")
+    endif (_threePartMatch)
+
+    # compute an overall version number which can be compared at once
+    MATH(EXPR ${_normalized_version} "${_major_vers}*10000 + ${_minor_vers}*100 + ${_patch_vers}")
+ENDMACRO(NORMALIZE_VERSION)
+
+MACRO(MACRO_CHECK_RANGE_INCLUSIVE_LOWER _lower_limit _value _upper_limit _ok)
+   if (${_value} LESS ${_lower_limit})
+      set( ${_ok} FALSE )
+  elseif (${_value} EQUAL ${_lower_limit})
+      set( ${_ok} TRUE )
+  elseif (${_value} EQUAL ${_upper_limit})
+      set( ${_ok} FALSE )
+  elseif (${_value} GREATER ${_upper_limit})
+      set( ${_ok} FALSE )
+  else (${_value} LESS ${_lower_limit})
+      set( ${_ok} TRUE )
+  endif (${_value} LESS ${_lower_limit})
+ENDMACRO(MACRO_CHECK_RANGE_INCLUSIVE_LOWER)
+
+MACRO(MACRO_ENSURE_VERSION requested_version found_version var_too_old)
+    NORMALIZE_VERSION( ${requested_version} req_vers_num )
+    NORMALIZE_VERSION( ${found_version} found_vers_num )
+
+    if (found_vers_num LESS req_vers_num)
+        set( ${var_too_old} FALSE )
+    else (found_vers_num LESS req_vers_num)
+        set( ${var_too_old} TRUE )
+    endif (found_vers_num LESS req_vers_num)
+
+ENDMACRO(MACRO_ENSURE_VERSION)
+
+MACRO(MACRO_ENSURE_VERSION2 requested_version2 found_version2 var_too_old2)
+    MACRO_ENSURE_VERSION( ${requested_version2} ${found_version2} ${var_too_old2})
+ENDMACRO(MACRO_ENSURE_VERSION2)
+
+MACRO(MACRO_ENSURE_VERSION_RANGE min_version found_version max_version var_ok)
+    NORMALIZE_VERSION( ${min_version} req_vers_num )
+    NORMALIZE_VERSION( ${found_version} found_vers_num )
+    NORMALIZE_VERSION( ${max_version} max_vers_num )
+
+    MACRO_CHECK_RANGE_INCLUSIVE_LOWER( ${req_vers_num} ${found_vers_num} ${max_vers_num} ${var_ok})
+ENDMACRO(MACRO_ENSURE_VERSION_RANGE)
+
+
diff --git a/bindings/phonon/cmake/modules/MacroLogFeature.cmake b/bindings/phonon/cmake/modules/MacroLogFeature.cmake
new file mode 100644 (file)
index 0000000..0cc8707
--- /dev/null
@@ -0,0 +1,125 @@
+# This file defines the Feature Logging macros.
+#
+# MACRO_LOG_FEATURE(VAR FEATURE DESCRIPTION URL [REQUIRED [MIN_VERSION [COMMENTS]]])
+#   Logs the information so that it can be displayed at the end
+#   of the configure run
+#   VAR : TRUE or FALSE, indicating whether the feature is supported
+#   FEATURE: name of the feature, e.g. "libjpeg"
+#   DESCRIPTION: description what this feature provides
+#   URL: home page
+#   REQUIRED: TRUE or FALSE, indicating whether the featue is required
+#   MIN_VERSION: minimum version number. empty string if unneeded
+#   COMMENTS: More info you may want to provide.  empty string if unnecessary
+#
+# MACRO_DISPLAY_FEATURE_LOG()
+#   Call this to display the collected results.
+#   Exits CMake with a FATAL error message if a required feature is missing
+#
+# Example:
+#
+# INCLUDE(MacroLogFeature)
+#
+# FIND_PACKAGE(JPEG)
+# MACRO_LOG_FEATURE(JPEG_FOUND "libjpeg" "Support JPEG images" "http://www.ijg.org" TRUE "3.2a" "")
+# ...
+# MACRO_DISPLAY_FEATURE_LOG()
+
+# Copyright (c) 2006, Alexander Neundorf, <neundorf@kde.org>
+# Copyright (c) 2006, Allen Winter, <winter@kde.org>
+#
+# Redistribution and use is allowed according to the terms of the BSD license.
+# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
+
+IF (NOT _macroLogFeatureAlreadyIncluded)
+   SET(_file ${CMAKE_BINARY_DIR}/MissingRequirements.txt)
+   IF (EXISTS ${_file})
+      FILE(REMOVE ${_file})
+   ENDIF (EXISTS ${_file})
+
+   SET(_file ${CMAKE_BINARY_DIR}/EnabledFeatures.txt)
+   IF (EXISTS ${_file})
+      FILE(REMOVE ${_file})
+   ENDIF (EXISTS ${_file})
+
+   SET(_file ${CMAKE_BINARY_DIR}/DisabledFeatures.txt)
+   IF (EXISTS ${_file})
+      FILE(REMOVE ${_file})
+  ENDIF (EXISTS ${_file})
+
+  SET(_macroLogFeatureAlreadyIncluded TRUE)
+ENDIF (NOT _macroLogFeatureAlreadyIncluded)
+
+
+MACRO(MACRO_LOG_FEATURE _var _package _description _url ) # _required _minvers _comments)
+
+   SET(_required "${ARGV4}")
+   SET(_minvers "${ARGV5}")
+   SET(_comments "${ARGV6}")
+
+   IF (${_var})
+     SET(_LOGFILENAME ${CMAKE_BINARY_DIR}/EnabledFeatures.txt)
+   ELSE (${_var})
+     IF (${_required} MATCHES "[Tt][Rr][Uu][Ee]")
+       SET(_LOGFILENAME ${CMAKE_BINARY_DIR}/MissingRequirements.txt)
+     ELSE (${_required} MATCHES "[Tt][Rr][Uu][Ee]")
+       SET(_LOGFILENAME ${CMAKE_BINARY_DIR}/DisabledFeatures.txt)
+     ENDIF (${_required} MATCHES "[Tt][Rr][Uu][Ee]")
+   ENDIF (${_var})
+
+   SET(_logtext "+ ${_package}")
+
+   IF (NOT ${_var})
+      IF (${_minvers} MATCHES ".*")
+        SET(_logtext "${_logtext}, ${_minvers}")
+      ENDIF (${_minvers} MATCHES ".*")
+      SET(_logtext "${_logtext}: ${_description} <${_url}>")
+      IF (${_comments} MATCHES ".*")
+        SET(_logtext "${_logtext}\n${_comments}")
+      ENDIF (${_comments} MATCHES ".*")
+#      SET(_logtext "${_logtext}\n") #double-space missing features?
+   ENDIF (NOT ${_var})
+   FILE(APPEND "${_LOGFILENAME}" "${_logtext}\n")
+
+ENDMACRO(MACRO_LOG_FEATURE)
+
+
+MACRO(MACRO_DISPLAY_FEATURE_LOG)
+
+   SET(_file ${CMAKE_BINARY_DIR}/MissingRequirements.txt)
+   IF (EXISTS ${_file})
+      FILE(READ ${_file} _requirements)
+      MESSAGE(STATUS "\n-----------------------------------------------------------------------------\n-- The following REQUIRED packages could NOT be located on your system.\n-- Please install them before continuing this software installation.\n-----------------------------------------------------------------------------\n${_requirements}-----------------------------------------------------------------------------")
+      FILE(REMOVE ${_file})
+      MESSAGE(FATAL_ERROR "Exiting: Missing Requirements")
+   ENDIF (EXISTS ${_file})
+
+   SET(_summary "\n")
+
+   SET(_elist 0)
+   SET(_file ${CMAKE_BINARY_DIR}/EnabledFeatures.txt)
+   IF (EXISTS ${_file})
+      SET(_elist 1)
+      FILE(READ ${_file} _enabled)
+      FILE(REMOVE ${_file})
+      SET(_summary "${_summary}-----------------------------------------------------------------------------\n-- The following external packages were located on your system.\n-- This installation will have the extra features provided by these packages.\n${_enabled}")
+   ENDIF (EXISTS ${_file})
+
+   SET(_dlist 0)
+   SET(_file ${CMAKE_BINARY_DIR}/DisabledFeatures.txt)
+   IF (EXISTS ${_file})
+      SET(_dlist 1)
+      FILE(READ ${_file} _disabled)
+      FILE(REMOVE ${_file})
+      SET(_summary "${_summary}-----------------------------------------------------------------------------\n-- The following OPTIONAL packages could NOT be located on your system.\n-- Consider installing them to enable more features from this software.\n${_disabled}")
+   ELSE (EXISTS ${_file})
+      IF (${_elist})
+        SET(_summary "${_summary}Congratulations! All external packages have been found.\n")
+      ENDIF (${_elist})
+   ENDIF (EXISTS ${_file})
+
+   IF (${_elist} OR ${_dlist})
+      SET(_summary "${_summary}-----------------------------------------------------------------------------\n")
+   ENDIF (${_elist} OR ${_dlist})
+   MESSAGE(STATUS "${_summary}")
+
+ENDMACRO(MACRO_DISPLAY_FEATURE_LOG)
diff --git a/bindings/phonon/cmake/modules/MacroOptionalFindPackage.cmake b/bindings/phonon/cmake/modules/MacroOptionalFindPackage.cmake
new file mode 100644 (file)
index 0000000..816cdb7
--- /dev/null
@@ -0,0 +1,28 @@
+# - MACRO_OPTIONAL_FIND_PACKAGE() combines FIND_PACKAGE() with an OPTION()
+# MACRO_OPTIONAL_FIND_PACKAGE( <name> [QUIT] )
+# This macro is a combination of OPTION() and FIND_PACKAGE(), it
+# works like FIND_PACKAGE(), but additionally it automatically creates
+# an option name WITH_<name>, which can be disabled via the cmake GUI.
+# or via -DWITH_<name>=OFF
+# The standard <name>_FOUND variables can be used in the same way
+# as when using the normal FIND_PACKAGE()
+
+# Copyright (c) 2006, Alexander Neundorf, <neundorf@kde.org>
+#
+# Redistribution and use is allowed according to the terms of the BSD license.
+# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
+
+
+MACRO (MACRO_OPTIONAL_FIND_PACKAGE _name )
+   OPTION(WITH_${_name} "Search for ${_name} package" ON)
+   if (WITH_${_name})
+      FIND_PACKAGE(${_name} ${ARGN})
+   else (WITH_${_name})
+      set(${_name}_FOUND)
+      set(${_name}_INCLUDE_DIR)
+      set(${_name}_INCLUDES)
+      set(${_name}_LIBRARY)
+      set(${_name}_LIBRARIES)
+   endif (WITH_${_name})
+ENDMACRO (MACRO_OPTIONAL_FIND_PACKAGE)
+
diff --git a/bindings/phonon/cmake/modules/PhononMacros.cmake b/bindings/phonon/cmake/modules/PhononMacros.cmake
new file mode 100644 (file)
index 0000000..2ef05a5
--- /dev/null
@@ -0,0 +1,206 @@
+
+# Phonon helper macros:
+#
+# macro (phonon_add_executable _target)
+# macro (PHONON_ADD_UNIT_TEST _test_NAME)
+# macro (PHONON_UPDATE_ICONCACHE)
+# macro (PHONON_UPDATE_ICONCACHE)
+# macro (_PHONON_ADD_ICON_INSTALL_RULE _install_SCRIPT _install_PATH _group _orig_NAME _install_NAME _l10n_SUBDIR)
+# macro (PHONON_INSTALL_ICONS _defaultpath )
+
+set(_global_add_executable_param)
+if (Q_WS_MAC)
+   set(_global_add_executable_param MACOSX_BUNDLE)
+endif (Q_WS_MAC)
+if (WIN32)
+   # no WIN32 here - all executables are command line executables
+   set(_global_add_executable_param)
+endif (WIN32)
+
+macro(phonon_add_executable _target)
+   set(_srcs ${ARGN})
+   automoc4_add_executable(${_target} ${_global_add_executable_param} ${_srcs})
+endmacro(phonon_add_executable _target)
+
+macro (PHONON_ADD_UNIT_TEST _test_NAME)
+   set(_srcList ${ARGN})
+   set(_nogui)
+   list(GET ${_srcList} 0 first_PARAM)
+   set(_add_executable_param ${_global_add_executable_param})
+   if(${first_PARAM} STREQUAL "NOGUI")
+      set(_nogui "NOGUI")
+      set(_add_executable_param)
+   endif(${first_PARAM} STREQUAL "NOGUI")
+
+   if (NOT PHONON_BUILD_TESTS)
+      set(_add_executable_param ${_add_executable_param} EXCLUDE_FROM_ALL)
+   endif (NOT PHONON_BUILD_TESTS)
+
+   automoc4_add_executable(${_test_NAME} ${_add_executable_param} ${_srcList})
+
+   if(NOT PHONON_TEST_OUTPUT)
+      set(PHONON_TEST_OUTPUT plaintext)
+   endif(NOT PHONON_TEST_OUTPUT)
+   set(PHONON_TEST_OUTPUT ${PHONON_TEST_OUTPUT} CACHE STRING "The output to generate when running the QTest unit tests")
+
+   set(using_qtest "")
+   foreach(_filename ${_srcList})
+      if(NOT using_qtest)
+         if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${_filename}")
+            file(READ ${_filename} file_CONTENT)
+            string(REGEX MATCH "QTEST_(KDE)?MAIN" using_qtest "${file_CONTENT}")
+         endif(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${_filename}")
+      endif(NOT using_qtest)
+   endforeach(_filename)
+
+   set(_executable ${EXECUTABLE_OUTPUT_PATH}/${_test_NAME})
+   if (Q_WS_MAC AND NOT _nogui)
+      set(_executable ${EXECUTABLE_OUTPUT_PATH}/${_test_NAME}.app/Contents/MacOS/${_test_NAME})
+   else (Q_WS_MAC AND NOT _nogui)
+      # Use .shell wrapper where available, to use uninstalled libs.
+      #if (UNIX)
+      #   set(_executable ${_executable}.shell)
+      #endif (UNIX)
+   endif (Q_WS_MAC AND NOT _nogui)
+
+   if (using_qtest AND PHONON_TEST_OUTPUT STREQUAL "xml")
+      add_test( ${_test_NAME} ${_executable} -xml -o ${_test_NAME}.tml)
+   else (using_qtest AND PHONON_TEST_OUTPUT STREQUAL "xml")
+      add_test( ${_test_NAME} ${_executable} )
+   endif (using_qtest AND PHONON_TEST_OUTPUT STREQUAL "xml")
+
+   if (NOT MSVC_IDE)   #not needed for the ide
+      # if the tests are EXCLUDE_FROM_ALL, add a target "buildtests" to build all tests
+      if (NOT PHONON_BUILD_TESTS)
+         get_directory_property(_buildtestsAdded BUILDTESTS_ADDED)
+         if(NOT _buildtestsAdded)
+            add_custom_target(buildtests)
+            set_directory_properties(PROPERTIES BUILDTESTS_ADDED TRUE)
+         endif(NOT _buildtestsAdded)
+         add_dependencies(buildtests ${_test_NAME})
+      endif (NOT PHONON_BUILD_TESTS)
+   endif (NOT MSVC_IDE)
+endmacro (PHONON_ADD_UNIT_TEST)
+
+macro (PHONON_UPDATE_ICONCACHE)
+    # Update mtime of hicolor icon theme dir.
+    # We don't always have touch command (e.g. on Windows), so instead create
+    #  and delete a temporary file in the theme dir.
+   install(CODE "
+    set(DESTDIR_VALUE \"\$ENV{DESTDIR}\")
+    if (NOT DESTDIR_VALUE)
+        file(WRITE \"${ICON_INSTALL_DIR}/hicolor/temp.txt\" \"update\")
+        file(REMOVE \"${ICON_INSTALL_DIR}/hicolor/temp.txt\")
+    endif (NOT DESTDIR_VALUE)
+    ")
+endmacro (PHONON_UPDATE_ICONCACHE)
+
+# a "map" of short type names to the directories
+# unknown names should give empty results
+# KDE 3 compatibility
+set(_PHONON_ICON_GROUP_mime       "mimetypes")
+set(_PHONON_ICON_GROUP_filesys    "places")
+set(_PHONON_ICON_GROUP_device     "devices")
+set(_PHONON_ICON_GROUP_app        "apps")
+set(_PHONON_ICON_GROUP_action     "actions")
+# KDE 4 / icon naming specification compatibility
+set(_PHONON_ICON_GROUP_mimetypes  "mimetypes")
+set(_PHONON_ICON_GROUP_places     "places")
+set(_PHONON_ICON_GROUP_devices    "devices")
+set(_PHONON_ICON_GROUP_apps       "apps")
+set(_PHONON_ICON_GROUP_actions    "actions")
+set(_PHONON_ICON_GROUP_categories "categories")
+set(_PHONON_ICON_GROUP_status     "status")
+set(_PHONON_ICON_GROUP_emblems    "emblems")
+set(_PHONON_ICON_GROUP_emotes     "emotes")
+set(_PHONON_ICON_GROUP_animations "animations")
+set(_PHONON_ICON_GROUP_intl       "intl")
+
+# a "map" of short theme names to the theme directory
+set(_PHONON_ICON_THEME_ox "oxygen")
+set(_PHONON_ICON_THEME_cr "crystalsvg")
+set(_PHONON_ICON_THEME_lo "locolor")
+set(_PHONON_ICON_THEME_hi "hicolor")
+
+macro (_PHONON_ADD_ICON_INSTALL_RULE _install_SCRIPT _install_PATH _group _orig_NAME _install_NAME _l10n_SUBDIR)
+
+   # if the string doesn't match the pattern, the result is the full string, so all three have the same content
+   if (NOT ${_group} STREQUAL ${_install_NAME} )
+      set(_icon_GROUP  ${_PHONON_ICON_GROUP_${_group}})
+      if(NOT _icon_GROUP)
+         set(_icon_GROUP "actions")
+      endif(NOT _icon_GROUP)
+#      message(STATUS "icon: ${_current_ICON} size: ${_size} group: ${_group} name: ${_name} l10n: ${_l10n_SUBDIR}")
+      install(FILES ${_orig_NAME} DESTINATION ${_install_PATH}/${_icon_GROUP}/${_l10n_SUBDIR}/ RENAME ${_install_NAME} )
+   endif (NOT ${_group} STREQUAL ${_install_NAME} )
+
+endmacro (_PHONON_ADD_ICON_INSTALL_RULE)
+
+
+macro (PHONON_INSTALL_ICONS _defaultpath )
+
+   # the l10n-subdir if language given as second argument (localized icon)
+   set(_lang ${ARGV1})
+   if(_lang)
+      set(_l10n_SUBDIR l10n/${_lang})
+   else(_lang)
+      set(_l10n_SUBDIR ".")
+   endif(_lang)
+
+   # first the png icons
+   file(GLOB _icons *.png)
+   foreach (_current_ICON ${_icons} )
+      # since CMake 2.6 regex matches are stored in special variables CMAKE_MATCH_x, if it didn't match, they are empty
+      string(REGEX MATCH "^.*/([a-zA-Z]+)([0-9]+)\\-([a-z]+)\\-(.+\\.png)$" _dummy  "${_current_ICON}")
+      set(_type  "${CMAKE_MATCH_1}")
+      set(_size  "${CMAKE_MATCH_2}")
+      set(_group "${CMAKE_MATCH_3}")
+      set(_name  "${CMAKE_MATCH_4}")
+
+      set(_theme_GROUP ${_PHONON_ICON_THEME_${_type}})
+      if( _theme_GROUP)
+         _PHONON_ADD_ICON_INSTALL_RULE(${CMAKE_CURRENT_BINARY_DIR}/install_icons.cmake
+                    ${_defaultpath}/${_theme_GROUP}/${_size}x${_size}
+                    ${_group} ${_current_ICON} ${_name} ${_l10n_SUBDIR})
+      endif( _theme_GROUP)
+   endforeach (_current_ICON)
+
+   # mng icons
+   file(GLOB _icons *.mng)
+   foreach (_current_ICON ${_icons} )
+      # since CMake 2.6 regex matches are stored in special variables CMAKE_MATCH_x, if it didn't match, they are empty
+      string(REGEX MATCH "^.*/([a-zA-Z]+)([0-9]+)\\-([a-z]+)\\-(.+\\.mng)$" _dummy  "${_current_ICON}")
+      set(_type  "${CMAKE_MATCH_1}")
+      set(_size  "${CMAKE_MATCH_2}")
+      set(_group "${CMAKE_MATCH_3}")
+      set(_name  "${CMAKE_MATCH_4}")
+
+      set(_theme_GROUP ${_PHONON_ICON_THEME_${_type}})
+      if( _theme_GROUP)
+         _PHONON_ADD_ICON_INSTALL_RULE(${CMAKE_CURRENT_BINARY_DIR}/install_icons.cmake
+                ${_defaultpath}/${_theme_GROUP}/${_size}x${_size}
+                ${_group} ${_current_ICON} ${_name} ${_l10n_SUBDIR})
+      endif( _theme_GROUP)
+   endforeach (_current_ICON)
+
+   # and now the svg icons
+   file(GLOB _icons *.svgz)
+   foreach (_current_ICON ${_icons} )
+      # since CMake 2.6 regex matches are stored in special variables CMAKE_MATCH_x, if it didn't match, they are empty
+      string(REGEX MATCH "^.*/([a-zA-Z]+)sc\\-([a-z]+)\\-(.+\\.svgz)$" _dummy "${_current_ICON}")
+      set(_type  "${CMAKE_MATCH_1}")
+      set(_group "${CMAKE_MATCH_2}")
+      set(_name  "${CMAKE_MATCH_3}")
+
+      set(_theme_GROUP ${_PHONON_ICON_THEME_${_type}})
+      if( _theme_GROUP)
+          _PHONON_ADD_ICON_INSTALL_RULE(${CMAKE_CURRENT_BINARY_DIR}/install_icons.cmake
+                            ${_defaultpath}/${_theme_GROUP}/scalable
+                            ${_group} ${_current_ICON} ${_name} ${_l10n_SUBDIR})
+      endif( _theme_GROUP)
+   endforeach (_current_ICON)
+
+   phonon_update_iconcache()
+
+endmacro (PHONON_INSTALL_ICONS)
+
diff --git a/bindings/phonon/vlc/.gitignore b/bindings/phonon/vlc/.gitignore
new file mode 100644 (file)
index 0000000..773218f
--- /dev/null
@@ -0,0 +1,4 @@
+.svn
+Makefile
+moc_*
+phonon_vlc_*
diff --git a/bindings/phonon/vlc/AUTHORS b/bindings/phonon/vlc/AUTHORS
new file mode 100644 (file)
index 0000000..ea17ee8
--- /dev/null
@@ -0,0 +1,3 @@
+Fathi Boudra <fabo@kde.org> (current maintainer)
+Lukas Durfina <lukas.durfina@gmail.com>
+Tanguy Krotoff <tkrotoff@gmail.com>
diff --git a/bindings/phonon/vlc/audiooutput.cpp b/bindings/phonon/vlc/audiooutput.cpp
new file mode 100644 (file)
index 0000000..e06b0d6
--- /dev/null
@@ -0,0 +1,103 @@
+/*****************************************************************************
+ * VLC backend for the Phonon library                                        *
+ * Copyright (C) 2007-2008 Tanguy Krotoff <tkrotoff@gmail.com>               *
+ * Copyright (C) 2008 Lukas Durfina <lukas.durfina@gmail.com>                *
+ * Copyright (C) 2009 Fathi Boudra <fabo@kde.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 3 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 package; if not, write to the Free Software       *
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA *
+ *****************************************************************************/
+
+#include "audiooutput.h"
+#include "devicemanager.h"
+#include "backend.h"
+
+#include "mediaobject.h"
+#include "vlcmediaobject.h"
+
+#include "vlcloader.h"
+
+namespace Phonon
+{
+namespace VLC {
+
+AudioOutput::AudioOutput(Backend *p_back, QObject * p_parent)
+        : SinkNode(p_parent),
+        f_volume(1.0),
+        p_backend(p_back)
+{
+    p_media_object = 0;
+}
+
+AudioOutput::~AudioOutput()
+{
+}
+
+qreal AudioOutput::volume() const
+{
+    return f_volume;
+}
+
+void AudioOutput::setVolume(qreal volume)
+{
+    if (vlc_instance) {
+        libvlc_audio_set_volume(vlc_instance, (int)(f_volume * 100), vlc_exception);
+        vlcExceptionRaised();
+        f_volume = volume;
+        emit volumeChanged(f_volume);
+    }
+}
+
+int AudioOutput::outputDevice() const
+{
+    return i_device;
+}
+
+bool AudioOutput::setOutputDevice(int device)
+{
+    if (i_device == device)
+        return true;
+
+    const QList<AudioDevice> deviceList = p_backend->deviceManager()->audioOutputDevices();
+    if (device >= 0 && device < deviceList.size()) {
+
+        i_device = device;
+        const QByteArray deviceName = deviceList.at(device).vlcId;
+        libvlc_audio_output_set(vlc_instance, (char *) deviceList.at(device).vlcId.data());
+        qDebug() << "set aout " << deviceList.at(device).vlcId.data();
+//         if (deviceName == DEFAULT_ID) {
+//             libvlc_audio_device_set(p_vlc_instance, DEFAULT, vlc_exception);
+//             vlcExceptionRaised();
+//         } else if (deviceName.startsWith(ALSA_ID)) {
+//             qDebug() << "setting ALSA " << deviceList.at(device).hwId.data();
+//             libvlc_audio_device_set(p_vlc_instance, ALSA, vlc_exception);
+//             vlcExceptionRaised();
+//             libvlc_audio_alsa_device_set(p_vlc_instance,
+//                                          deviceList.at(device).hwId,
+//                                          vlc_exception);
+//             vlcExceptionRaised();
+    }
+
+    return true;
+}
+
+#if (PHONON_VERSION >= PHONON_VERSION_CHECK(4, 2, 0))
+bool AudioOutput::setOutputDevice(const Phonon::AudioOutputDevice & device)
+{
+    return true;
+}
+#endif
+
+}
+} // Namespace Phonon::VLC
diff --git a/bindings/phonon/vlc/audiooutput.h b/bindings/phonon/vlc/audiooutput.h
new file mode 100644 (file)
index 0000000..54b738a
--- /dev/null
@@ -0,0 +1,69 @@
+/*****************************************************************************
+ * VLC backend for the Phonon library                                        *
+ * Copyright (C) 2007-2008 Tanguy Krotoff <tkrotoff@gmail.com>               *
+ * Copyright (C) 2008 Lukas Durfina <lukas.durfina@gmail.com>                *
+ * Copyright (C) 2009 Fathi Boudra <fabo@kde.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 3 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 package; if not, write to the Free Software       *
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA *
+ *****************************************************************************/
+
+#ifndef PHONON_VLC_AUDIOOUTPUT_H
+#define PHONON_VLC_AUDIOOUTPUT_H
+
+#include "sinknode.h"
+
+#include <phonon/audiooutputinterface.h>
+
+namespace Phonon
+{
+namespace VLC {
+class Backend;
+
+class AudioOutput : public SinkNode, public AudioOutputInterface
+{
+    Q_OBJECT
+    Q_INTERFACES(Phonon::AudioOutputInterface)
+
+public:
+
+    AudioOutput(Backend *p_back, QObject * p_parent);
+    ~AudioOutput();
+
+    qreal volume() const;
+    void setVolume(qreal volume);
+
+    int outputDevice() const;
+    bool setOutputDevice(int);
+#if (PHONON_VERSION >= PHONON_VERSION_CHECK(4, 2, 0))
+    bool setOutputDevice(const AudioOutputDevice & device);
+#endif
+
+signals:
+
+    void volumeChanged(qreal volume);
+    void audioDeviceFailed();
+
+private:
+
+    qreal f_volume;
+    int i_device;
+    Backend *p_backend;
+
+};
+
+}
+} // Namespace Phonon::VLC
+
+#endif // PHONON_VLC_AUDIOOUTPUT_H
diff --git a/bindings/phonon/vlc/backend.cpp b/bindings/phonon/vlc/backend.cpp
new file mode 100644 (file)
index 0000000..a907e6e
--- /dev/null
@@ -0,0 +1,395 @@
+/*****************************************************************************
+ * VLC backend for the Phonon library                                        *
+ * Copyright (C) 2007-2008 Tanguy Krotoff <tkrotoff@gmail.com>               *
+ * Copyright (C) 2008 Lukas Durfina <lukas.durfina@gmail.com>                *
+ * Copyright (C) 2009 Fathi Boudra <fabo@kde.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 3 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 package; if not, write to the Free Software       *
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA *
+ *****************************************************************************/
+
+#include "backend.h"
+
+#include "audiooutput.h"
+#include "mediaobject.h"
+#include "videowidget.h"
+#include "devicemanager.h"
+#include "effectmanager.h"
+#include "effect.h"
+#include "sinknode.h"
+#include "vlcloader.h"
+#include "vlcmediaobject.h"
+
+#include <QtCore/QSet>
+#include <QtCore/QVariant>
+#include <QtCore/QtPlugin>
+
+Q_EXPORT_PLUGIN2(phonon_vlc, Phonon::VLC::Backend)
+
+namespace Phonon
+{
+namespace VLC {
+
+Backend::Backend(QObject *parent, const QVariantList &)
+        : QObject(parent)
+        , m_deviceManager(0)
+        , m_effectManager(0)
+        , m_debugLevel(Warning)
+{
+    bool wasInit = vlcInit();
+
+    setProperty("identifier",     QLatin1String("phonon_vlc"));
+    setProperty("backendName",    QLatin1String("VLC"));
+    setProperty("backendComment", QLatin1String("VLC plugin for Phonon"));
+    setProperty("backendVersion", QLatin1String("0.1"));
+    setProperty("backendWebsite", QLatin1String("http://multimedia.kde.org/"));
+
+    // Check if we should enable debug output
+    QString debugLevelString = qgetenv("PHONON_VLC_DEBUG");
+    int debugLevel = debugLevelString.toInt();
+    if (debugLevel > 3) // 3 is maximum
+        debugLevel = 3;
+    m_debugLevel = (DebugLevel)debugLevel;
+
+    if (wasInit) {
+        logMessage(QString("Using VLC version %0").arg(libvlc_get_version()));
+    } else {
+        qWarning("Phonon::VLC::vlcInit: Failed to initialize VLC");
+    }
+
+    m_deviceManager = new DeviceManager(this);
+    m_effectManager = new EffectManager(this);
+}
+
+Backend::~Backend()
+{
+//    vlcRelease();
+}
+
+QObject *Backend::createObject(BackendInterface::Class c, QObject *parent, const QList<QVariant> &args)
+{
+    switch (c) {
+    case MediaObjectClass:
+        return new VLCMediaObject(parent);
+    case VolumeFaderEffectClass:
+//        return new VolumeFaderEffect(parent);
+        logMessage("createObject() : VolumeFaderEffect not implemented");
+        break;
+    case AudioOutputClass: {
+        AudioOutput *ao = new AudioOutput(this, parent);
+        m_audioOutputs.append(ao);
+        return ao;
+    }
+    case AudioDataOutputClass:
+//        return new AudioDataOutput(parent);
+        logMessage("createObject() : AudioDataOutput not implemented");
+        break;
+    case VisualizationClass:
+//        return new Visualization(parent);
+        logMessage("createObject() : Visualization not implemented");
+        break;
+    case VideoDataOutputClass:
+//        return new VideoDataOutput(parent);
+        logMessage("createObject() : VideoDataOutput not implemented");
+        break;
+    case EffectClass:
+        return new Effect(m_effectManager, args[0].toInt(), parent);
+    case VideoWidgetClass:
+        return new VideoWidget(qobject_cast<QWidget *>(parent));
+    default:
+        logMessage("createObject() : Backend object not available");
+    }
+    return 0;
+}
+
+bool Backend::supportsVideo() const
+{
+    return true;
+}
+
+bool Backend::supportsOSD() const
+{
+    return true;
+}
+
+bool Backend::supportsFourcc(quint32 fourcc) const
+{
+    return true;
+}
+
+bool Backend::supportsSubtitles() const
+{
+    return true;
+}
+
+QStringList Backend::availableMimeTypes() const
+{
+    if (m_supportedMimeTypes.isEmpty()) {
+        const_cast<Backend *>(this)->m_supportedMimeTypes
+        << QLatin1String("application/ogg")
+        << QLatin1String("application/vnd.rn-realmedia")
+        << QLatin1String("application/x-annodex")
+        << QLatin1String("application/x-flash-video")
+        << QLatin1String("application/x-quicktimeplayer")
+        << QLatin1String("audio/168sv")
+        << QLatin1String("audio/8svx")
+        << QLatin1String("audio/aiff")
+        << QLatin1String("audio/basic")
+        << QLatin1String("audio/mp3")
+        << QLatin1String("audio/mpeg")
+        << QLatin1String("audio/mpeg2")
+        << QLatin1String("audio/mpeg3")
+        << QLatin1String("audio/vnd.rn-realaudio")
+        << QLatin1String("audio/wav")
+        << QLatin1String("audio/x-16sv")
+        << QLatin1String("audio/x-8svx")
+        << QLatin1String("audio/x-aiff")
+        << QLatin1String("audio/x-basic")
+        << QLatin1String("audio/x-m4a")
+        << QLatin1String("audio/x-mp3")
+        << QLatin1String("audio/x-mpeg")
+        << QLatin1String("audio/x-mpeg2")
+        << QLatin1String("audio/x-mpeg3")
+        << QLatin1String("audio/x-mpegurl")
+        << QLatin1String("audio/x-ms-wma")
+        << QLatin1String("audio/x-ogg")
+        << QLatin1String("audio/x-pn-aiff")
+        << QLatin1String("audio/x-pn-au")
+        << QLatin1String("audio/x-pn-realaudio-plugin")
+        << QLatin1String("audio/x-pn-wav")
+        << QLatin1String("audio/x-pn-windows-acm")
+        << QLatin1String("audio/x-real-audio")
+        << QLatin1String("audio/x-realaudio")
+        << QLatin1String("audio/x-speex+ogg")
+        << QLatin1String("audio/x-wav")
+        << QLatin1String("image/ilbm")
+        << QLatin1String("image/png")
+        << QLatin1String("image/x-ilbm")
+        << QLatin1String("image/x-png")
+        << QLatin1String("video/anim")
+        << QLatin1String("video/avi")
+        << QLatin1String("video/mkv")
+        << QLatin1String("video/mng")
+        << QLatin1String("video/mp4")
+        << QLatin1String("video/mpeg")
+        << QLatin1String("video/mpg")
+        << QLatin1String("video/msvideo")
+        << QLatin1String("video/quicktime")
+        << QLatin1String("video/x-anim")
+        << QLatin1String("video/x-flic")
+        << QLatin1String("video/x-mng")
+        << QLatin1String("video/x-mpeg")
+        << QLatin1String("video/x-ms-asf")
+        << QLatin1String("video/x-ms-wmv")
+        << QLatin1String("video/x-msvideo")
+        << QLatin1String("video/x-quicktime");
+    }
+    return m_supportedMimeTypes;
+}
+
+QList<int> Backend::objectDescriptionIndexes(ObjectDescriptionType type) const
+{
+    QList<int> list;
+
+    switch (type) {
+    case Phonon::AudioOutputDeviceType: {
+        QList<AudioDevice> deviceList = deviceManager()->audioOutputDevices();
+        for (int dev = 0 ; dev < deviceList.size() ; ++dev)
+            list.append(deviceList[dev].id);
+        break;
+    }
+    break;
+    case Phonon::EffectType: {
+        QList<EffectInfo*> effectList = effectManager()->effects();
+        for (int eff = 0; eff < effectList.size(); ++eff)
+            list.append(eff);
+        break;
+    }
+    break;
+    default:
+        break;
+    }
+
+    return list;
+}
+
+QHash<QByteArray, QVariant> Backend::objectDescriptionProperties(ObjectDescriptionType type, int index) const
+{
+    QHash<QByteArray, QVariant> ret;
+
+    switch (type) {
+    case Phonon::AudioOutputDeviceType: {
+        QList<AudioDevice> audioDevices = deviceManager()->audioOutputDevices();
+        if (index >= 0 && index < audioDevices.size()) {
+            ret.insert("name", audioDevices[index].vlcId);
+            ret.insert("description", audioDevices[index].description);
+            ret.insert("icon", QLatin1String("audio-card"));
+        }
+    }
+    break;
+    case Phonon::EffectType: {
+        QList<EffectInfo*> effectList = effectManager()->effects();
+        if (index >= 0 && index <= effectList.size()) {
+            const EffectInfo *effect = effectList[ index ];
+            ret.insert("name", effect->name());
+            ret.insert("description", effect->description());
+            ret.insert("author", effect->author());
+        } else {
+            Q_ASSERT(1); // Since we use list position as ID, this should not happen
+        }
+    }
+    break;
+    default:
+        break;
+    }
+
+    return ret;
+}
+
+bool Backend::startConnectionChange(QSet<QObject *> objects)
+{
+    foreach(QObject *object, objects) {
+        logMessage(QString("Object: %0").arg(object->metaObject()->className()));
+    }
+
+    // There is nothing we can do but hope the connection changes will not take too long
+    // so that buffers would underrun
+    // But we should be pretty safe the way xine works by not doing anything here.
+    return true;
+}
+
+bool Backend::connectNodes(QObject *source, QObject *sink)
+{
+    logMessage(QString("Backend connected %0 to %1")
+               .arg(source->metaObject()->className())
+               .arg(sink->metaObject()->className()));
+
+    // Example:
+    // source = Phonon::VLC_MPlayer::MediaObject
+    // sink = Phonon::VLC_MPlayer::VideoWidget
+
+    // Example:
+    // source = Phonon::VLC_MPlayer::MediaObject
+    // sink = Phonon::VLC_MPlayer::AudioOutput
+
+    // Example:
+    // source = Phonon::VLC_MPlayer::MediaObject
+    // sink = Phonon::VLC_MPlayer::Effect
+
+    // Example:
+    // source = Phonon::VLC_MPlayer::Effect
+    // sink = Phonon::VLC_MPlayer::AudioOutput
+
+    SinkNode *sinkNode = qobject_cast<SinkNode *>(sink);
+    if (sinkNode) {
+        PrivateMediaObject *mediaObject = qobject_cast<PrivateMediaObject *>(source);
+        if (mediaObject) {
+            // Connect the SinkNode to a MediaObject
+            sinkNode->connectToMediaObject(mediaObject);
+            return true;
+        } else {
+            // FIXME try to find a better way...
+//            Effect *effect = qobject_cast<Effect *>(source);
+            return true;
+        }
+    }
+
+    logMessage(QString("Linking %0 to %1 failed")
+               .arg(source->metaObject()->className())
+               .arg(sink->metaObject()->className()),
+               Warning);
+
+    return false;
+}
+
+bool Backend::disconnectNodes(QObject *source, QObject *sink)
+{
+    SinkNode *sinkNode = qobject_cast<SinkNode *>(sink);
+    if (sinkNode) {
+        PrivateMediaObject *mediaObject = qobject_cast<PrivateMediaObject *>(source);
+        if (mediaObject) {
+            // Disconnect the SinkNode from a MediaObject
+            sinkNode->disconnectFromMediaObject(mediaObject);
+            return true;
+        } else {
+            // FIXME try to find a better way...
+//            Effect *effect = qobject_cast<Effect *>(source);
+            return true;
+        }
+    }
+
+    return false;
+}
+
+bool Backend::endConnectionChange(QSet<QObject *> objects)
+{
+    foreach(QObject *object, objects) {
+        logMessage(QString("Object: %0").arg(object->metaObject()->className()));
+    }
+
+    return true;
+}
+
+DeviceManager* Backend::deviceManager() const
+{
+    return m_deviceManager;
+}
+
+EffectManager* Backend::effectManager() const
+{
+    return m_effectManager;
+}
+
+/**
+ * Return a debuglevel that is determined by the
+ * PHONON_VLC_DEBUG environment variable.
+ *
+ *  Warning - important warnings
+ *  Info    - general info
+ *  Debug   - gives extra info
+ */
+Backend::DebugLevel Backend::debugLevel() const
+{
+    return m_debugLevel;
+}
+
+/**
+ * Print a conditional debug message based on the current debug level
+ * If obj is provided, classname and objectname will be printed as well
+ *
+ * see debugLevel()
+ */
+void Backend::logMessage(const QString &message, int priority, QObject *obj) const
+{
+    if (debugLevel() > 0) {
+        QString output;
+        if (obj) {
+            // Strip away namespace from className
+            QString className(obj->metaObject()->className());
+            int nameLength = className.length() - className.lastIndexOf(':') - 1;
+            className = className.right(nameLength);
+            output.sprintf("%s %s (%s %p)", message.toLatin1().constData(),
+                           obj->objectName().toLatin1().constData(),
+                           className.toLatin1().constData(), obj);
+        } else {
+            output = message;
+        }
+        if (priority <= (int)debugLevel()) {
+            qDebug() << QString("PVLC(%1): %2").arg(priority).arg(output);
+        }
+    }
+}
+
+}
+} // Namespace Phonon::VLC
diff --git a/bindings/phonon/vlc/backend.h b/bindings/phonon/vlc/backend.h
new file mode 100644 (file)
index 0000000..4cb5c91
--- /dev/null
@@ -0,0 +1,96 @@
+/*****************************************************************************
+ * VLC backend for the Phonon library                                        *
+ * Copyright (C) 2007-2008 Tanguy Krotoff <tkrotoff@gmail.com>               *
+ * Copyright (C) 2008 Lukas Durfina <lukas.durfina@gmail.com>                *
+ * Copyright (C) 2009 Fathi Boudra <fabo@kde.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 3 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 package; if not, write to the Free Software       *
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA *
+ *****************************************************************************/
+
+#ifndef Phonon_VLC_BACKEND_H
+#define Phonon_VLC_BACKEND_H
+
+#include "devicemanager.h"
+#include "audiooutput.h"
+
+#include <phonon/objectdescription.h>
+#include <phonon/backendinterface.h>
+
+#include <QtCore/QList>
+#include <QtCore/QPointer>
+#include <QtCore/QStringList>
+
+#ifdef MAKE_PHONON_VLC_LIB // We are building this library
+# define PHONON_VLC_EXPORT Q_DECL_EXPORT
+#else // We are using this library
+# define PHONON_VLC_EXPORT Q_DECL_IMPORT
+#endif
+
+namespace Phonon
+{
+namespace VLC {
+class AudioOutput;
+class EffectManager;
+
+class Backend : public QObject, public BackendInterface
+{
+    Q_OBJECT
+    Q_INTERFACES(Phonon::BackendInterface)
+
+public:
+
+    enum DebugLevel {NoDebug, Warning, Info, Debug};
+    Backend(QObject *parent = 0, const QVariantList & = QVariantList());
+    virtual ~Backend();
+
+    DeviceManager* deviceManager() const;
+    EffectManager* effectManager() const;
+
+    QObject *createObject(BackendInterface::Class, QObject *parent, const QList<QVariant> &args);
+
+    bool supportsVideo() const;
+    bool supportsOSD() const;
+    bool supportsFourcc(quint32 fourcc) const;
+    bool supportsSubtitles() const;
+    QStringList availableMimeTypes() const;
+
+    QList<int> objectDescriptionIndexes(ObjectDescriptionType type) const;
+    QHash<QByteArray, QVariant> objectDescriptionProperties(ObjectDescriptionType type, int index) const;
+
+    bool startConnectionChange(QSet<QObject *>);
+    bool connectNodes(QObject *, QObject *);
+    bool disconnectNodes(QObject *, QObject *);
+    bool endConnectionChange(QSet<QObject *>);
+
+    DebugLevel debugLevel() const;
+
+    void logMessage(const QString &message, int priority = 2, QObject *obj = 0) const;
+
+Q_SIGNALS:
+    void objectDescriptionChanged(ObjectDescriptionType);
+
+private:
+    mutable QStringList m_supportedMimeTypes;
+    QList<QPointer<AudioOutput> > m_audioOutputs;
+
+    DeviceManager *m_deviceManager;
+    EffectManager *m_effectManager;
+    DebugLevel m_debugLevel;
+};
+
+}
+} // namespace Phonon::VLC
+
+#endif // Phonon_VLC_BACKEND_H
diff --git a/bindings/phonon/vlc/devicemanager.cpp b/bindings/phonon/vlc/devicemanager.cpp
new file mode 100644 (file)
index 0000000..3bea98c
--- /dev/null
@@ -0,0 +1,152 @@
+/*  This file is part of the KDE project.
+
+    Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+    This library 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 or 3 of the License.
+
+    This library 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 library.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "devicemanager.h"
+#include "backend.h"
+//#include "videowidget.h"
+//#include "widgetrenderer.h"
+#include "vlcloader.h"
+
+/**
+ * This class manages the list of currently active output devices.
+ */
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace VLC {
+
+AudioDevice::AudioDevice(DeviceManager *manager, const QByteArray &deviceId, const QByteArray &hw_id)
+{
+    // Get an id
+    static int counter = 0;
+    id = counter++;
+    // Get name from device
+    if (vlcId == "default") {
+        description = "Default audio device";
+    } else {
+        vlcId = deviceId;
+        description = "";
+    }
+    hwId = hw_id;
+}
+
+DeviceManager::DeviceManager(Backend *parent)
+        : QObject(parent)
+        , m_backend(parent)
+{
+    updateDeviceList();
+}
+
+DeviceManager::~DeviceManager()
+{
+    m_audioDeviceList.clear();
+}
+
+bool DeviceManager::canOpenDevice() const
+{
+    return true;
+}
+
+/**
+ * Return a positive device id or -1 if device does not exist.
+ */
+int DeviceManager::deviceId(const QByteArray &nameId) const
+{
+    for (int i = 0 ; i < m_audioDeviceList.size() ; ++i) {
+        if (m_audioDeviceList[i].vlcId == nameId)
+            return m_audioDeviceList[i].id;
+    }
+    return -1;
+}
+
+/**
+ * Get a human-readable description from a device id.
+ */
+QByteArray DeviceManager::deviceDescription(int i_id) const
+{
+    for (int i = 0 ; i < m_audioDeviceList.size() ; ++i) {
+        if (m_audioDeviceList[i].id == i_id)
+            return m_audioDeviceList[i].description;
+    }
+    return QByteArray();
+}
+
+/**
+ * Update the current list of active devices.
+ */
+void DeviceManager::updateDeviceList()
+{
+    QList<QByteArray> list, list_hw;
+    list.append("default");
+    list_hw.append("");
+
+    // Get the list of available audio outputs
+    libvlc_audio_output_t *p_ao_list = libvlc_audio_output_list_get(
+                                           vlc_instance, vlc_exception);
+    vlcExceptionRaised();
+    libvlc_audio_output_t *p_start = p_ao_list;
+
+    while (p_ao_list) {
+        list.append(p_ao_list->psz_name);
+        list_hw.append("");
+        p_ao_list = p_ao_list->p_next;
+    }
+    libvlc_audio_output_list_release(p_start);
+
+    for (int i = 0 ; i < list.size() ; ++i) {
+        QByteArray nameId = list.at(i);
+        QByteArray hwId = list_hw.at(i);
+        if (deviceId(nameId) == -1) {
+            // This is a new device, add it
+            qDebug() << "add aout " << nameId.data();
+            m_audioDeviceList.append(AudioDevice(this, nameId, hwId));
+            emit deviceAdded(deviceId(nameId));
+        }
+    }
+    if (list.size() < m_audioDeviceList.size()) {
+        // A device was removed
+        for (int i = m_audioDeviceList.size() - 1 ; i >= 0 ; --i) {
+            QByteArray currId = m_audioDeviceList[i].vlcId;
+            bool b_found = false;
+            for (int k = list.size() - 1  ; k >= 0 ; --k) {
+                if (currId == list[k]) {
+                    b_found = true;
+                    break;
+                }
+            }
+            if (!b_found) {
+                emit deviceRemoved(deviceId(currId));
+                m_audioDeviceList.removeAt(i);
+            }
+        }
+    }
+}
+
+/**
+ * Return a list of hardware id.
+ */
+const QList<AudioDevice> DeviceManager::audioOutputDevices() const
+{
+    return m_audioDeviceList;
+}
+
+}
+}
+
+QT_END_NAMESPACE
diff --git a/bindings/phonon/vlc/devicemanager.h b/bindings/phonon/vlc/devicemanager.h
new file mode 100644 (file)
index 0000000..73a20d6
--- /dev/null
@@ -0,0 +1,74 @@
+/*  This file is part of the KDE project.
+
+    Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+    This library 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 or 3 of the License.
+
+    This library 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 library.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_VLC_DEVICEMANAGER_H
+#define Phonon_VLC_DEVICEMANAGER_H
+
+#include <phonon/audiooutputinterface.h>
+
+#include <QtCore/QObject>
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace VLC {
+
+class Backend;
+class DeviceManager;
+class AbstractRenderer;
+class VideoWidget;
+
+class AudioDevice
+{
+public :
+    AudioDevice(DeviceManager *s, const QByteArray &deviceId, const QByteArray &hw_id = "");
+    int id;
+    QByteArray vlcId;
+    QByteArray description;
+    QByteArray hwId;
+};
+
+class DeviceManager : public QObject
+{
+    Q_OBJECT
+
+public:
+    DeviceManager(Backend *parent);
+    virtual ~DeviceManager();
+    const QList<AudioDevice> audioOutputDevices() const;
+    int deviceId(const QByteArray &vlcId) const;
+    QByteArray deviceDescription(int id) const;
+
+signals:
+    void deviceAdded(int);
+    void deviceRemoved(int);
+
+public slots:
+    void updateDeviceList();
+
+private:
+    bool canOpenDevice() const;
+    Backend *m_backend;
+    QList <AudioDevice> m_audioDeviceList;
+};
+}
+} // namespace Phonon::VLC
+
+QT_END_NAMESPACE
+
+#endif // Phonon_VLC_DEVICEMANAGER_H
diff --git a/bindings/phonon/vlc/effect.cpp b/bindings/phonon/vlc/effect.cpp
new file mode 100644 (file)
index 0000000..f918fe1
--- /dev/null
@@ -0,0 +1,223 @@
+/*****************************************************************************
+ * VLC backend for the Phonon library                                        *
+ * Copyright (C) 2007-2008 Tanguy Krotoff <tkrotoff@gmail.com>               *
+ * Copyright (C) 2008 Lukas Durfina <lukas.durfina@gmail.com>                *
+ * Copyright (C) 2009 Fathi Boudra <fabo@kde.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 3 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 package; if not, write to the Free Software       *
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA *
+ *****************************************************************************/
+
+#include "effect.h"
+
+#include "effectmanager.h"
+
+#include "mediaobject.h"
+
+namespace Phonon
+{
+namespace VLC {
+
+Effect::Effect(EffectManager *p_em, int i_effectId, QObject *p_parent)
+        : SinkNode(p_parent)
+{
+    p_effectManager = p_em;
+    QList<EffectInfo *> effects = p_effectManager->effects();
+
+    if (i_effectId >= 0 && i_effectId < effects.size()) {
+        i_effect_filter = effects[ i_effectId ]->filter();
+        effect_type = effects[ i_effectId ]->type();
+        setupEffectParams();
+    } else {
+        // effect ID out of range
+        Q_ASSERT(0);
+    }
+}
+
+Effect::~Effect()
+{
+    parameterList.clear();
+}
+
+void Effect::connectToMediaObject(PrivateMediaObject *p_media_object)
+{
+    SinkNode::connectToMediaObject(p_media_object);
+
+    switch (effect_type) {
+    case EffectInfo::AudioEffect:
+//        libvlc_audio_filter_add(p_vlc_instance, (libvlc_audio_filter_names_t)i_effect_filter, vlc_exception);
+//        vlcExceptionRaised();
+        break;
+    case EffectInfo::VideoEffect:
+//        libvlc_video_filter_add(p_vlc_current_media_player, (libvlc_video_filter_names_t)i_effect_filter, vlc_exception);
+//        vlcExceptionRaised();
+        break;
+    }
+}
+
+void Effect::disconnectFromMediaObject(PrivateMediaObject *p_media_object)
+{
+    SinkNode::disconnectFromMediaObject(p_media_object);
+
+    switch (effect_type) {
+    case EffectInfo::AudioEffect:
+//        libvlc_audio_filter_remove(p_vlc_instance, (libvlc_audio_filter_names_t)i_effect_filter, vlc_exception);
+//        vlcExceptionRaised();
+        break;
+    case EffectInfo::VideoEffect:
+//        libvlc_video_filter_remove(p_vlc_current_media_player, (libvlc_video_filter_names_t)i_effect_filter, vlc_exception);
+//        vlcExceptionRaised();
+        break;
+    }
+}
+
+void Effect::setupEffectParams()
+{
+//    libvlc_filter_parameter_list_t *p_list;
+    switch (effect_type) {
+    case EffectInfo::AudioEffect:
+//        p_list = libvlc_audio_filter_get_parameters(p_vlc_instance, (libvlc_audio_filter_names_t)i_effect_filter, vlc_exception );
+//        vlcExceptionRaised();
+        break;
+    case EffectInfo::VideoEffect:
+//        p_list = libvlc_video_filter_get_parameters(p_vlc_instance, (libvlc_video_filter_names_t)i_effect_filter, vlc_exception );
+//        vlcExceptionRaised();
+        break;
+    }
+//    if( !p_list )
+//        return;
+
+    int i_index = 0;
+//    libvlc_filter_parameter_list_t *p_parameter_list = p_list;
+//    while (p_parameter_list) {
+//        switch (p_parameter_list->var_type) {
+//        case LIBVLC_BOOL: {
+//            const QString description = p_parameter_list->psz_description;
+//            parameterList.append(Phonon::EffectParameter(
+//                                     i_index,
+//                                     QString(p_parameter_list->psz_parameter_name),
+//                                     Phonon::EffectParameter::ToggledHint,   // hints
+//                                     QVariant((bool) p_parameter_list->default_value.b_bool),
+//                                     QVariant((bool) false),
+//                                     QVariant((bool) true),
+//                                     QVariantList(),
+//                                     description));
+//            break;
+//        }
+//        case LIBVLC_INT: {
+//            const QString description = p_parameter_list->psz_description;
+//            parameterList.append(Phonon::EffectParameter(
+//                                     i_index,
+//                                     QString(p_parameter_list->psz_parameter_name),
+//                                     EffectParameter::IntegerHint,   // hints
+//                                     QVariant((int) p_parameter_list->default_value.i_int),
+//                                     QVariant((int) p_parameter_list->min_value.i_int),
+//                                     QVariant((int) p_parameter_list->max_value.i_int),
+//                                     QVariantList(),
+//                                     description));
+//            break;
+//        }
+//        case LIBVLC_FLOAT: {
+//            const QString description = p_parameter_list->psz_description;
+//            parameterList.append(Phonon::EffectParameter(
+//                                     i_index,
+//                                     QString(p_parameter_list->psz_parameter_name),
+//                                     0,   // hints
+//                                     QVariant((double) p_parameter_list->default_value.f_float),
+//                                     QVariant((double) p_parameter_list->min_value.f_float),
+//                                     QVariant((double) p_parameter_list->max_value.f_float),
+//                                     QVariantList(),
+//                                     description));
+//            break;
+//        }
+//        case LIBVLC_STRING: {
+//            const QString description = p_parameter_list->psz_description;
+//            parameterList.append(Phonon::EffectParameter(
+//                                     i_index,
+//                                     QString(p_parameter_list->psz_parameter_name),
+//                                     0,   // hints
+//                                     QVariant((const char *) p_parameter_list->default_value.psz_string),
+//                                     NULL,
+//                                     NULL,
+//                                     QVariantList(),
+//                                     description));
+//            break;
+//        }
+//        }
+//        i_index++;
+//        p_parameter_list = p_parameter_list->p_next;
+//    }
+//    libvlc_filter_parameters_release(p_list);
+}
+
+QList<EffectParameter> Effect::parameters() const
+{
+    return parameterList;
+}
+
+QVariant Effect::parameterValue(const EffectParameter & param) const
+{
+    return QVariant();
+}
+
+void Effect::setParameterValue(const EffectParameter & param, const QVariant & newValue)
+{
+//    libvlc_value_t value;
+//    libvlc_var_type_t type;
+//    switch (param.type()) {
+//    case QVariant::Bool:
+//        value.b_bool = newValue.toBool();
+//        type = LIBVLC_BOOL;
+//        break;
+//    case QVariant::Int:
+//        value.i_int = newValue.toInt();
+//        type = LIBVLC_INT;
+//        break;
+//    case QVariant::Double:
+//        value.f_float = (float) newValue.toDouble();
+//        type = LIBVLC_FLOAT;
+//        break;
+//    case QVariant::String:
+//        value.psz_string = newValue.toString().toAscii().data();
+//        type = LIBVLC_STRING;
+//        break;
+//    default:
+//        break;
+//    }
+//    switch (effect_type) {
+//    case EffectInfo::AudioEffect:
+//        libvlc_audio_filter_set_parameter(
+//            p_vlc_instance,
+//            // (libvlc_audio_filter_names_t) i_effect_filter,
+//            param.name().toAscii().data(),
+//            type,
+//            value,
+//            vlc_exception);
+//        vlcExceptionRaised();
+//        break;
+//    case EffectInfo::VideoEffect:
+//        libvlc_video_filter_set_parameter(
+//            p_vlc_current_media_player,
+//            (libvlc_video_filter_names_t) i_effect_filter,
+//            param.name().toAscii().data(),
+//            type,
+//            value,
+//            vlc_exception);
+//        vlcExceptionRaised();
+//        break;
+//    }
+}
+
+}
+} // Namespace Phonon::VLC
diff --git a/bindings/phonon/vlc/effect.h b/bindings/phonon/vlc/effect.h
new file mode 100644 (file)
index 0000000..760aa0a
--- /dev/null
@@ -0,0 +1,67 @@
+/*****************************************************************************
+ * VLC backend for the Phonon library                                        *
+ * Copyright (C) 2007-2008 Tanguy Krotoff <tkrotoff@gmail.com>               *
+ * Copyright (C) 2008 Lukas Durfina <lukas.durfina@gmail.com>                *
+ * Copyright (C) 2009 Fathi Boudra <fabo@kde.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 3 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 package; if not, write to the Free Software       *
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA *
+ *****************************************************************************/
+
+#ifndef PHONON_VLC_EFFECT_H
+#define PHONON_VLC_EFFECT_H
+
+#include "sinknode.h"
+#include "effectmanager.h"
+
+#include <phonon/effectinterface.h>
+#include <phonon/effectparameter.h>
+
+namespace Phonon
+{
+namespace VLC {
+
+class EffectManager;
+
+
+class Effect : public SinkNode, public EffectInterface
+{
+    Q_OBJECT
+    Q_INTERFACES(Phonon::EffectInterface)
+
+public:
+
+    Effect(EffectManager *p_em, int i_effectId, QObject *p_parent);
+    ~Effect();
+
+    void setupEffectParams();
+    QList<EffectParameter> parameters() const;
+    QVariant parameterValue(const EffectParameter & param) const;
+    void setParameterValue(const EffectParameter & param, const QVariant & newValue);
+
+    void connectToMediaObject(PrivateMediaObject *p_media_object);
+    void disconnectFromMediaObject(PrivateMediaObject *p_media_object);
+
+private:
+
+    EffectManager *p_effectManager;
+    int i_effect_filter;
+    EffectInfo::Type effect_type;
+    QList<Phonon::EffectParameter> parameterList;
+};
+
+}
+} // Namespace Phonon::VLC
+
+#endif // PHONON_VLC_EFFECT_H
diff --git a/bindings/phonon/vlc/effectmanager.cpp b/bindings/phonon/vlc/effectmanager.cpp
new file mode 100644 (file)
index 0000000..e71c21a
--- /dev/null
@@ -0,0 +1,230 @@
+/*****************************************************************************
+ * VLC backend for the Phonon library                                        *
+ * Copyright (C) 2007-2008 Tanguy Krotoff <tkrotoff@gmail.com>               *
+ * Copyright (C) 2008 Lukas Durfina <lukas.durfina@gmail.com>                *
+ * Copyright (C) 2009 Fathi Boudra <fabo@kde.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 3 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 package; if not, write to the Free Software       *
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA *
+ *****************************************************************************/
+
+#include "effectmanager.h"
+#include "backend.h"
+
+namespace Phonon
+{
+namespace VLC {
+
+EffectInfo::EffectInfo(const QString &name, const QString &description, const QString &author, int filter, Type type)
+        : m_name(name)
+        , m_description(description)
+        , m_author(author)
+        , m_filter(filter)
+        , m_type(type) {}
+
+EffectManager::EffectManager(Backend *backend)
+        : QObject(backend)
+        , m_backend(backend)
+{
+//    m_equalizerEnabled = false;
+
+    // Audio effects - equalizer
+    // Only one of them can be used => last set
+    // It is clever used with combobox
+
+//    audioEffectList.append(new EffectInfo("(Audio) Equalizer", EQUALIZER, EffectInfo::AudioEffect));
+
+//    audioEffectList.append(new EffectInfo("(Audio) Headphone spalization",
+//                                          HEADPHONE_SPALIZATION, EffectInfo::AudioEffect,
+//                                          "This effect gives you the feeling that you are standing in a room "
+//                                          "with a complete 7.1 speaker set when using only a headphone, "
+//                                          "providing a more realistic sound experience. It should also be "
+//                                          "more comfortable and less tiring when listening to music for "
+//                                          "long periods of time.\nIt works with any source format from mono "
+//                                          "to 7.1."));
+
+//    audioEffectList.append(new EffectInfo("(Audio) Parametric equalizer",
+//                                          PARAMETRIC_EQUALIZER, EffectInfo::AudioEffect));
+
+//    audioEffectList.append(new EffectInfo("(Audio) Scaletempo",
+//                                          SCALETEMPO, EffectInfo::AudioEffect,
+//                                          "Scale audio tempo in sync with playback rate"));
+
+//    audioEffectList.append(new EffectInfo("(Audio) Spatializer",
+//                                          SPATIALIZER, EffectInfo::AudioEffect));
+
+//    audioEffectList.append(new EffectInfo("(Audio) Volume normalizer",
+//                                          VOLUME_NORMALIZER, EffectInfo::AudioEffect));
+
+//    audioEffectList.append(new EffectInfo("(Audio) Flat", FLAT, EffectInfo::AudioEffect));
+//    audioEffectList.append(new EffectInfo("(Audio) Classical", CLASSICAL, EffectInfo::AudioEffect));
+//    audioEffectList.append(new EffectInfo("(Audio) Club", CLUB, EffectInfo::AudioEffect));
+//    audioEffectList.append(new EffectInfo("(Audio) Dance", DANCE, EffectInfo::AudioEffect));
+//    audioEffectList.append(new EffectInfo("(Audio) Fullbass", FULLBASS, EffectInfo::AudioEffect));
+//    audioEffectList.append(new EffectInfo("(Audio) Fullbasstreble", FULLBASSTREBLE, EffectInfo::AudioEffect));
+//    audioEffectList.append(new EffectInfo("(Audio) Fulltreble", FULLTREBLE, EffectInfo::AudioEffect));
+//    audioEffectList.append(new EffectInfo("(Audio) Headphones", HEADPHONES, EffectInfo::AudioEffect));
+//    audioEffectList.append(new EffectInfo("(Audio) Large hall", LARGEHALL, EffectInfo::AudioEffect));
+//    audioEffectList.append(new EffectInfo("(Audio) Live", LIVE, EffectInfo::AudioEffect));
+//    audioEffectList.append(new EffectInfo("(Audio) Party", PARTY, EffectInfo::AudioEffect));
+//    audioEffectList.append(new EffectInfo("(Audio) Pop", POP, EffectInfo::AudioEffect));
+//    audioEffectList.append(new EffectInfo("(Audio) Reggae", REGGAE, EffectInfo::AudioEffect));
+//    audioEffectList.append(new EffectInfo("(Audio) Rock", ROCK, EffectInfo::AudioEffect));
+//    audioEffectList.append(new EffectInfo("(Audio) Ska", SKA, EffectInfo::AudioEffect));
+//    audioEffectList.append(new EffectInfo("(Audio) Soft", SOFT, EffectInfo::AudioEffect));
+//    audioEffectList.append(new EffectInfo("(Audio) Softrock", SOFTROCK, EffectInfo::AudioEffect));
+//    audioEffectList.append(new EffectInfo("(Audio) Techno", TECHNO, EffectInfo::AudioEffect));
+
+    // Video effects
+    // More than one can be used simultaneously
+    // It is clever used with checkbox
+
+//    videoEffectList.append(new EffectInfo("(Video) Atmo light", ATMOLIGHT, EffectInfo::VideoEffect,
+//                                          "AtmoLight Filter - "
+//                                          "This module allows to control an so called AtmoLight device "
+//                                          "connected to your computer.\n"
+//                                          "AtmoLight is the homegrown version of what Philips calls AmbiLight.\n"
+//                                          "If you need further information feel free to visit us at\n\n"
+//                                          "http://www.vdr-wiki.de/wiki/index.php/Atmo-plugin\n "
+//                                          "http://www.vdr-wiki.de/wiki/index.php/AtmoWin\n\n"
+//                                          "You can find there detailed descriptions on how to build it for yourself "
+//                                          "and where to get the required parts.\n"
+//                                          "You can also have a look at pictures and some movies showing such a device "
+//                                          "in live action.",
+//                                          "André Weber (WeberAndre@gmx.de)"));
+
+//    videoEffectList.append(new EffectInfo("(Video) Bluescreen", BLUESCREEN, EffectInfo::VideoEffect,
+//                                          "Bluescreen video filter", "Antoine Cellerier <dionoea at videolan tod org>"));
+
+//    videoEffectList.append(new EffectInfo("(Video) Color threshold", COLORTHRESHOLD, EffectInfo::VideoEffect,
+//                                          "Color threshold filter", "Sigmund Augdal <dnumgis@videolan.org>"));
+
+//    videoEffectList.append(new EffectInfo("(Video) Deinterlace", DEINTERLACE, EffectInfo::VideoEffect,
+//                                          "Deinterlacing video filter", "Sam Hocevar <sam@zoy.org"));
+
+//    videoEffectList.append(new EffectInfo("(Video) Erase", ERASE, EffectInfo::VideoEffect,
+//                                          "Erase video filter", "Antoine Cellerier <dionoea at videolan dot org>"));
+
+//    videoEffectList.append(new EffectInfo("(Video) Extract", EXTRACT, EffectInfo::VideoEffect,
+//                                          "Extract RGB component video filter",
+//                                          "Antoine Cellerier <dionoea at videolan dot org>"));
+
+//    videoEffectList.append(new EffectInfo("(Video) Gaussian blur", GAUSSIAN_BLUR, EffectInfo::VideoEffect,
+//                                          "Erase video filter", "Antoine Cellerier <dionoea at videolan dot org>"));
+
+//    videoEffectList.append(new EffectInfo("(Video) Gradient", GRADIENT, EffectInfo::VideoEffect,
+//                                          "Gradient video filter",
+//                                          "Samuel Hocevar <sam@zoy.org>, "
+//                                          "Antoine Cellerier <dionoea at videolan dot org>"));
+
+//    videoEffectList.append(new EffectInfo("(Video) Grain", GRAIN, EffectInfo::VideoEffect,
+//                                          "Grain video filter", "Antoine Cellerier <dionoea at videolan dot org>"));
+
+//    videoEffectList.append(new EffectInfo("(Video) Invert", INVERT, EffectInfo::VideoEffect,
+//                                          "Invert video filter - color inversion",
+//                                          "Samuel Hocevar <sam@zoy.org>"));
+
+//    videoEffectList.append(new EffectInfo("(Video) Motion blur", MOTIONBLUR, EffectInfo::VideoEffect,
+//                                          "Motion blur filter",
+//                                          "Sigmund Augdal Helberg <dnumgis@videolan.org>, "
+//                                          "Antoine Cellerier <dionoea at videolan dot org>"));
+
+//    videoEffectList.append(new EffectInfo("(Video) Motion detect", MOTIONDETECT, EffectInfo::VideoEffect,
+//                                          "Motion detect video filter",
+//                                          "Antoine Cellerier <dionoea at videolan dot org>"));
+
+//    videoEffectList.append(new EffectInfo("(Video) Noise", NOISE, EffectInfo::VideoEffect,
+//                                          "Noise video filter - add noise to image",
+//                                          "Antoine Cellerier <dionoea at videolan dot org>"));
+
+//    videoEffectList.append(new EffectInfo("(Video) Postprocess", POSTPROCESS, EffectInfo::VideoEffect,
+//                                          "Video post processing filter",
+//                                          "Laurent Aimar <fenrir@via.ecp.fr>, "
+//                                          "Gildas Bazin <gbazin@netcourrier.com>, "
+//                                          "Antoine Cellerier <dionoea at videolan dot org>"));
+
+//    videoEffectList.append(new EffectInfo("(Video) Psychedelic", PSYCHEDELIC, EffectInfo::VideoEffect,
+//                                          "Psychedelic video filter",
+//                                          "Samuel Hocevar <sam@zoy.org>, "
+//                                          "Antoine Cellerier <dionoea at videolan dot org>"));
+
+//    videoEffectList.append(new EffectInfo("(Video) Ripple", RIPPLE, EffectInfo::VideoEffect,
+//                                          "Ripple video filter",
+//                                          "Samuel Hocevar <sam@zoy.org>, "
+//                                          "Antoine Cellerier <dionoea at videolan dot org>"));
+
+//    videoEffectList.append(new EffectInfo("(Video) Rotate", ROTATE, EffectInfo::VideoEffect,
+//                                          "Rotate video filter",
+//                                          "Antoine Cellerier <dionoea at videolan dot org>"));
+
+//    videoEffectList.append(new EffectInfo("(Video) Seam carving", SEAM_CARVING, EffectInfo::VideoEffect,
+//                                          "Seam Carving for Content-Aware Image Resizing",
+//                                          "Antoine Cellerier <dionoea at videolan dot org>"));
+
+//    videoEffectList.append(new EffectInfo("(Video) Sharpen", SHARPEN, EffectInfo::VideoEffect,
+//                                          "Sharpen video filter - Augment contrast between contours.",
+//                                          "Jérémy DEMEULE <dj_mulder at djduron dot no-ip dot org>, "
+//                                          "Jean-Baptiste Kempf <jb at videolan dot org>"));
+
+//    videoEffectList.append(new EffectInfo("(Video) Wave", WAVE, EffectInfo::VideoEffect,
+//                                          "Wave video filter",
+//                                          "Samuel Hocevar <sam@zoy.org>, "
+//                                          "Antoine Cellerier <dionoea at videolan dot org>"));
+
+    updateEffects();
+}
+
+EffectManager::~EffectManager()
+{
+    qDeleteAll(m_audioEffectList);
+    m_audioEffectList.clear();
+    qDeleteAll(m_videoEffectList);
+    m_videoEffectList.clear();
+    qDeleteAll(m_effectList);
+    m_effectList.clear();
+}
+
+/**
+ * Returns a list of available audio effects
+ */
+const QList<EffectInfo *> EffectManager::audioEffects() const
+{
+    return m_audioEffectList;
+}
+
+/**
+ * Returns a list of available video effects
+ */
+const QList<EffectInfo *> EffectManager::videoEffects() const
+{
+    return m_videoEffectList;
+}
+
+/**
+ * Returns a list of available effects
+ */
+const QList<EffectInfo *> EffectManager::effects() const
+{
+    return m_effectList;
+}
+
+void EffectManager::updateEffects()
+{
+    m_effectList.clear();
+    m_effectList += m_audioEffectList;
+    m_effectList += m_videoEffectList;
+}
+
+}
+} // namespace Phonon::VLC
diff --git a/bindings/phonon/vlc/effectmanager.h b/bindings/phonon/vlc/effectmanager.h
new file mode 100644 (file)
index 0000000..4724b38
--- /dev/null
@@ -0,0 +1,101 @@
+/*****************************************************************************
+ * VLC backend for the Phonon library                                        *
+ * Copyright (C) 2007-2008 Tanguy Krotoff <tkrotoff@gmail.com>               *
+ * Copyright (C) 2008 Lukas Durfina <lukas.durfina@gmail.com>                *
+ * Copyright (C) 2009 Fathi Boudra <fabo@kde.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 3 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 package; if not, write to the Free Software       *
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA *
+ *****************************************************************************/
+
+#ifndef Phonon_VLC_EFFECTMANAGER_H
+#define Phonon_VLC_EFFECTMANAGER_H
+
+#include <phonon/effectinterface.h>
+#include <phonon/effectparameter.h>
+
+#include <QtCore/QObject>
+
+namespace Phonon
+{
+namespace VLC {
+class Backend;
+class EffectManager;
+
+class EffectInfo
+{
+public:
+
+    enum Type {AudioEffect, VideoEffect};
+
+    EffectInfo(const QString &name,
+               const QString &description,
+               const QString &author,
+               int filter,
+               Type type);
+
+    QString name() const {
+        return m_name;
+    }
+
+    QString description() const {
+        return m_description;
+    }
+
+    QString author() const {
+        return m_author;
+    }
+
+    int filter() const {
+        return m_filter;
+    }
+
+    Type type() const {
+        return m_type;
+    }
+
+private:
+    QString m_name;
+    QString m_description;
+    QString m_author;
+    int m_filter;
+    Type m_type;
+};
+
+class EffectManager : public QObject
+{
+    Q_OBJECT
+
+public:
+    EffectManager(Backend *parent);
+    virtual ~EffectManager();
+
+    const QList<EffectInfo *> audioEffects() const;
+    const QList<EffectInfo *> videoEffects() const;
+    const QList<EffectInfo *> effects() const;
+
+private:
+    void updateEffects();
+
+    Backend *m_backend;
+    QList<EffectInfo *> m_effectList;
+    QList<EffectInfo *> m_audioEffectList;
+    QList<EffectInfo *> m_videoEffectList;
+    bool m_equalizerEnabled;
+};
+
+}
+} // namespace Phonon::VLC
+
+#endif // Phonon_VLC_EFFECTMANAGER_H
diff --git a/bindings/phonon/vlc/mediacontroller.cpp b/bindings/phonon/vlc/mediacontroller.cpp
new file mode 100644 (file)
index 0000000..f38909b
--- /dev/null
@@ -0,0 +1,223 @@
+/*****************************************************************************
+ * VLC backend for the Phonon library                                        *
+ * Copyright (C) 2007-2008 Tanguy Krotoff <tkrotoff@gmail.com>               *
+ * Copyright (C) 2008 Lukas Durfina <lukas.durfina@gmail.com>                *
+ * Copyright (C) 2009 Fathi Boudra <fabo@kde.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 3 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 package; if not, write to the Free Software       *
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA *
+ *****************************************************************************/
+
+#include "mediacontroller.h"
+
+namespace Phonon
+{
+namespace VLC {
+
+MediaController::MediaController()
+{
+    clearMediaController();
+}
+
+MediaController::~MediaController()
+{
+}
+
+void MediaController::clearMediaController()
+{
+    current_audio_channel = Phonon::AudioChannelDescription();
+    available_audio_channels.clear();
+
+    current_subtitle = Phonon::SubtitleDescription();
+    available_subtitles.clear();
+
+//    current_chapter = Phonon::ChapterDescription();
+//    available_chapters.clear();
+    current_chapter = 0;
+    available_chapters = 0;
+
+//    current_title = Phonon::TitleDescription();
+//    available_titles.clear();
+    current_title = 0;
+    available_titles = 0;
+
+    i_current_angle = 0;
+    i_available_angles = 0;
+
+    b_autoplay_titles = false;
+}
+
+bool MediaController::hasInterface(Interface iface) const
+{
+    switch (iface) {
+    case AddonInterface::NavigationInterface:
+        return true;
+        break;
+    case AddonInterface::ChapterInterface:
+        return true;
+        break;
+    case AddonInterface::AngleInterface:
+        return true;
+        break;
+    case AddonInterface::TitleInterface:
+        return true;
+        break;
+    case AddonInterface::SubtitleInterface:
+        return true;
+        break;
+    case AddonInterface::AudioChannelInterface:
+        return true;
+        break;
+    default:
+        qCritical() << __FUNCTION__
+        << "Error: unsupported AddonInterface::Interface"
+        << iface;
+    }
+
+    return false;
+}
+
+QVariant MediaController::interfaceCall(Interface iface, int i_command, const QList<QVariant> & arguments)
+{
+    switch (iface) {
+    case AddonInterface::ChapterInterface:
+        switch (static_cast<AddonInterface::ChapterCommand>(i_command)) {
+//        case AddonInterface::availableChapters:
+//            return QVariant::fromValue(availableChapters());
+        case AddonInterface::availableChapters:
+            return availableChapters();
+//        case AddonInterface::currentChapter:
+//            return QVariant::fromValue(currentChapter());
+        case AddonInterface::chapter:
+            return currentChapter();
+//        case AddonInterface::setCurrentChapter:
+//            if( arguments.isEmpty() || !arguments.first().canConvert<ChapterDescription>()) {
+//                    qCritical() << __FUNCTION__ << "Error: arguments invalid";
+//                    return false;
+//                }
+//            setCurrentChapter(arguments.first().value<ChapterDescription>());
+//            return true;
+        case AddonInterface::setChapter:
+            if (arguments.isEmpty() || !arguments.first().canConvert(QVariant::Int)) {
+                qCritical() << __FUNCTION__ << "Error: arguments invalid";
+                return false;
+            }
+            setCurrentChapter(arguments.first().toInt());
+            return true;
+        default:
+            qCritical() << __FUNCTION__
+            << "Error: unsupported AddonInterface::ChapterInterface command:"
+            << i_command;
+        }
+        break;
+    case AddonInterface::TitleInterface:
+        switch (static_cast<AddonInterface::TitleCommand>(i_command)) {
+//        case AddonInterface::availableTitles:
+//            return QVariant::fromValue(availableTitles());
+        case AddonInterface::availableTitles:
+            return availableTitles();
+//        case AddonInterface::currentTitle:
+//            return QVariant::fromValue(currentTitle());
+        case AddonInterface::title:
+            return currentTitle();
+//        case AddonInterface::setCurrentTitle:
+//            if( arguments.isEmpty() || !arguments.first().canConvert<TitleDescription>()) {
+//                    qCritical() << __FUNCTION__ << "Error: arguments invalid";
+//                    return false;
+//            }
+//            setCurrentTitle(arguments.first().value<TitleDescription>());
+//            return true;
+        case AddonInterface::setTitle:
+            if (arguments.isEmpty() || !arguments.first().canConvert(QVariant::Int)) {
+                qCritical() << __FUNCTION__ << "Error: arguments invalid";
+                return false;
+            }
+            setCurrentTitle(arguments.first().toInt());
+            return true;
+        case AddonInterface::autoplayTitles:
+            return autoplayTitles();
+        case AddonInterface::setAutoplayTitles:
+            if (arguments.isEmpty() || !arguments.first().canConvert(QVariant::Bool)) {
+                qCritical() << __FUNCTION__ << "Error: arguments invalid";
+                return false;
+            }
+            setAutoplayTitles(arguments.first().toBool());
+            return true;
+        default:
+            qCritical() << __FUNCTION__
+            << "Error: unsupported AddonInterface::TitleInterface command:"
+            << i_command;
+        }
+        break;
+    case AddonInterface::AngleInterface:
+        switch (static_cast<AddonInterface::AngleCommand>(i_command)) {
+        case AddonInterface::availableAngles:
+        case AddonInterface::angle:
+        case AddonInterface::setAngle:
+            break;
+        default:
+            qCritical() << __FUNCTION__
+            << "Error: unsupported AddonInterface::AngleInterface command:"
+            << i_command;
+        }
+        break;
+    case AddonInterface::SubtitleInterface:
+        switch (static_cast<AddonInterface::SubtitleCommand>(i_command)) {
+        case AddonInterface::availableSubtitles:
+            return QVariant::fromValue(availableSubtitles());
+        case AddonInterface::currentSubtitle:
+            return QVariant::fromValue(currentSubtitle());
+        case AddonInterface::setCurrentSubtitle:
+            if (arguments.isEmpty() || !arguments.first().canConvert<SubtitleDescription>()) {
+                qCritical() << __FUNCTION__ << "Error: arguments invalid";
+                return false;
+            }
+            setCurrentSubtitle(arguments.first().value<SubtitleDescription>());
+            return true;
+        default:
+            qCritical() << __FUNCTION__
+            << "Error: unsupported AddonInterface::SubtitleInterface command:"
+            << i_command;
+        }
+        break;
+    case AddonInterface::AudioChannelInterface:
+        switch (static_cast<AddonInterface::AudioChannelCommand>(i_command)) {
+        case AddonInterface::availableAudioChannels:
+            return QVariant::fromValue(availableAudioChannels());
+        case AddonInterface::currentAudioChannel:
+            return QVariant::fromValue(currentAudioChannel());
+        case AddonInterface::setCurrentAudioChannel:
+            if (arguments.isEmpty() || !arguments.first().canConvert<AudioChannelDescription>()) {
+                qCritical() << __FUNCTION__ << "Error: arguments invalid";
+                return false;
+            }
+            setCurrentAudioChannel(arguments.first().value<AudioChannelDescription>());
+            return true;
+        default:
+            qCritical() << __FUNCTION__
+            << "Error: unsupported AddonInterface::AudioChannelInterface command:"
+            << i_command;
+        }
+        break;
+    default:
+        qCritical() << __FUNCTION__
+        << "Error: unsupported AddonInterface::Interface:"
+        << iface;
+    }
+
+    return QVariant();
+}
+
+}
+} // Namespace Phonon::VLC
diff --git a/bindings/phonon/vlc/mediacontroller.h b/bindings/phonon/vlc/mediacontroller.h
new file mode 100644 (file)
index 0000000..853e559
--- /dev/null
@@ -0,0 +1,139 @@
+/*****************************************************************************
+ * VLC backend for the Phonon library                                        *
+ * Copyright (C) 2007-2008 Tanguy Krotoff <tkrotoff@gmail.com>               *
+ * Copyright (C) 2008 Lukas Durfina <lukas.durfina@gmail.com>                *
+ * Copyright (C) 2009 Fathi Boudra <fabo@kde.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 3 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 package; if not, write to the Free Software       *
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA *
+ *****************************************************************************/
+
+#ifndef PHONON_VLC_MEDIACONTROLLER_H
+#define PHONON_VLC_MEDIACONTROLLER_H
+
+#include <phonon/addoninterface.h>
+#include <phonon/objectdescription.h>
+
+namespace Phonon
+{
+namespace VLC {
+
+/**
+ * Interface for AddonInterface.
+ *
+ * This class cannot inherit from QObject has MediaObject already inherit from QObject.
+ * This is a Qt limitation: there is no possibility to inherit virtual Qobject :/
+ * See http://doc.trolltech.com/qq/qq15-academic.html
+ * Phonon implementation got the same problem.
+ *
+ * @see VLCMediaController
+ * @see VLCMediaObject
+ * @see MediaObject
+ */
+class MediaController : public AddonInterface
+{
+public:
+
+    MediaController();
+    virtual ~MediaController();
+
+    bool hasInterface(Interface iface) const;
+
+    QVariant interfaceCall(Interface iface, int i_command, const QList<QVariant> & arguments = QList<QVariant>());
+
+    // MediaController signals
+    virtual void availableSubtitlesChanged() = 0;
+    virtual void availableAudioChannelsChanged() = 0;
+
+//    virtual void availableChaptersChanged() = 0;
+//    virtual void availableTitlesChanged() = 0;
+    virtual void availableChaptersChanged(int) = 0;
+    virtual void availableTitlesChanged(int) = 0;
+
+    virtual void availableAnglesChanged(int i_available_angles) = 0;
+    virtual void angleChanged(int i_angle_number) = 0;
+    virtual void chapterChanged(int i_chapter_number) = 0;
+    virtual void titleChanged(int i_title_number) = 0;
+
+protected:
+
+    // AudioChannel
+    virtual void setCurrentAudioChannel(const Phonon::AudioChannelDescription & audioChannel) = 0;
+    virtual QList<Phonon::AudioChannelDescription> availableAudioChannels() const = 0;
+    virtual Phonon::AudioChannelDescription currentAudioChannel() const = 0;
+
+    // Subtitle
+    virtual void setCurrentSubtitle(const Phonon::SubtitleDescription & subtitle) = 0;
+    virtual QList<Phonon::SubtitleDescription> availableSubtitles() const = 0;
+    virtual Phonon::SubtitleDescription currentSubtitle() const = 0;
+
+    // Angle
+    virtual void setCurrentAngle(int i_angle_number) = 0;
+    virtual int availableAngles() const = 0;
+    virtual int currentAngle() const = 0;
+
+    // Chapter
+//    virtual void setCurrentChapter( const Phonon::ChapterDescription & chapter ) = 0;
+//    virtual QList<Phonon::ChapterDescription> availableChapters() const = 0;
+//    virtual Phonon::ChapterDescription currentChapter() const = 0;
+    virtual void setCurrentChapter(int chapterNumber) = 0;
+    virtual int availableChapters() const = 0;
+    virtual int currentChapter() const = 0;
+
+    // Title
+//    virtual void setCurrentTitle( const Phonon::TitleDescription & title ) = 0;
+//    virtual QList<Phonon::TitleDescription> availableTitles() const = 0;
+//    virtual Phonon::TitleDescription currentTitle() const = 0;
+    virtual void setCurrentTitle(int titleNumber) = 0;
+    virtual int availableTitles() const = 0;
+    virtual int currentTitle() const = 0;
+
+    virtual void setAutoplayTitles(bool b_autoplay) = 0;
+    virtual bool autoplayTitles() const = 0;
+
+    /**
+     * Clear all (i.e availableSubtitles, availableChapters...).
+     *
+     * This is used each time we restart the video.
+     */
+    virtual void clearMediaController();
+
+    Phonon::AudioChannelDescription current_audio_channel;
+    QList<Phonon::AudioChannelDescription> available_audio_channels;
+
+    Phonon::SubtitleDescription current_subtitle;
+    QList<Phonon::SubtitleDescription> available_subtitles;
+
+//    Phonon::ChapterDescription current_chapter;
+//    QList<Phonon::ChapterDescription> available_chapters;
+    int current_chapter;
+    int available_chapters;
+
+//    Phonon::TitleDescription current_title;
+//    QList<Phonon::TitleDescription> available_titles;
+    int current_title;
+    int available_titles;
+
+    int i_current_angle;
+    int i_available_angles;
+
+    bool b_autoplay_titles;
+
+private:
+};
+
+}
+} // Namespace Phonon::VLC
+
+#endif // PHONON_VLC_MEDIACONTROLLER_H
diff --git a/bindings/phonon/vlc/mediaobject.cpp b/bindings/phonon/vlc/mediaobject.cpp
new file mode 100644 (file)
index 0000000..aad5103
--- /dev/null
@@ -0,0 +1,291 @@
+/*****************************************************************************
+ * VLC backend for the Phonon library                                        *
+ * Copyright (C) 2007-2008 Tanguy Krotoff <tkrotoff@gmail.com>               *
+ * Copyright (C) 2008 Lukas Durfina <lukas.durfina@gmail.com>                *
+ * Copyright (C) 2009 Fathi Boudra <fabo@kde.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 3 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 package; if not, write to the Free Software       *
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA *
+ *****************************************************************************/
+
+#include "mediaobject.h"
+
+#include "seekstack.h"
+
+#include <QtCore/QUrl>
+#include <QtCore/QMetaType>
+#include <QtCore/QTimer>
+
+//Time in milliseconds before sending aboutToFinish() signal
+//2 seconds
+static const int ABOUT_TO_FINISH_TIME = 2000;
+
+namespace Phonon
+{
+namespace VLC {
+
+MediaObject::MediaObject(QObject *p_parent)
+        : QObject(p_parent)
+{
+    currentState = Phonon::LoadingState;
+    i_video_widget_id = 0;
+    b_prefinish_mark_reached_emitted = false;
+    b_about_to_finish_emitted = false;
+    i_transition_time = 0;
+
+    // By default, no tick() signal
+    // FIXME: Not implemented yet
+    i_tick_interval = 0;
+
+    qRegisterMetaType<QMultiMap<QString, QString> >("QMultiMap<QString, QString>");
+
+    connect(this, SIGNAL(stateChanged(Phonon::State)),
+            SLOT(stateChangedInternal(Phonon::State)));
+
+    connect(this, SIGNAL(tickInternal(qint64)),
+            SLOT(tickInternalSlot(qint64)));
+}
+
+MediaObject::~MediaObject()
+{
+}
+
+void MediaObject::setVideoWidgetId(int i_widget_id)
+{
+    i_video_widget_id = i_widget_id;
+}
+
+void MediaObject::play()
+{
+    qDebug() << __FUNCTION__;
+
+    if (currentState == Phonon::PausedState) {
+        resume();
+    } else {
+        // Play the file
+        playInternal();
+    }
+}
+
+void MediaObject::seek(qint64 milliseconds)
+{
+    static SeekStack *p_stack = new SeekStack(this);
+
+    p_stack->pushSeek(milliseconds);
+
+    qint64 currentTime = this->currentTime();
+    qint64 totalTime = this->totalTime();
+
+    if (currentTime < totalTime - i_prefinish_mark) {
+        b_prefinish_mark_reached_emitted = false;
+    }
+    if (currentTime < totalTime - ABOUT_TO_FINISH_TIME) {
+        b_about_to_finish_emitted = false;
+    }
+}
+
+void MediaObject::tickInternalSlot(qint64 currentTime)
+{
+    qint64 totalTime = this->totalTime();
+
+    if (i_tick_interval > 0) {
+        // If _tickInternal == 0 means tick() signal is disabled
+        // Default is _tickInternal = 0
+        emit tick(currentTime);
+    }
+
+    if (currentState == Phonon::PlayingState) {
+        if (currentTime >= totalTime - i_prefinish_mark) {
+            if (!b_prefinish_mark_reached_emitted) {
+                b_prefinish_mark_reached_emitted = true;
+                emit prefinishMarkReached(totalTime - currentTime);
+            }
+        }
+        if (currentTime >= totalTime - ABOUT_TO_FINISH_TIME) {
+            if (!b_about_to_finish_emitted) {
+                // Track is about to finish
+                b_about_to_finish_emitted = true;
+                emit aboutToFinish();
+            }
+        }
+    }
+}
+
+void MediaObject::loadMedia(const QString & filename)
+{
+    // Default MediaObject state is Phonon::LoadingState
+    currentState = Phonon::LoadingState;
+
+    // Load the media
+    loadMediaInternal(filename);
+}
+
+void MediaObject::resume()
+{
+    pause();
+}
+
+qint32 MediaObject::tickInterval() const
+{
+    return i_tick_interval;
+}
+
+void MediaObject::setTickInterval(qint32 tickInterval)
+{
+    i_tick_interval = tickInterval;
+//    if (_tickInterval <= 0) {
+//        _tickTimer->setInterval(50);
+//    } else {
+//        _tickTimer->setInterval(_tickInterval);
+//    }
+}
+
+qint64 MediaObject::currentTime() const
+{
+    qint64 time = -1;
+    Phonon::State st = state();
+
+    switch (st) {
+    case Phonon::PausedState:
+        time = currentTimeInternal();
+        break;
+    case Phonon::BufferingState:
+        time = currentTimeInternal();
+        break;
+    case Phonon::PlayingState:
+        time = currentTimeInternal();
+        break;
+    case Phonon::StoppedState:
+        time = 0;
+        break;
+    case Phonon::LoadingState:
+        time = 0;
+        break;
+    case Phonon::ErrorState:
+        time = -1;
+        break;
+    default:
+        qCritical() << __FUNCTION__ << "Error: unsupported Phonon::State:" << st;
+    }
+
+    return time;
+}
+
+Phonon::State MediaObject::state() const
+{
+    return currentState;
+}
+
+Phonon::ErrorType MediaObject::errorType() const
+{
+    return Phonon::NormalError;
+}
+
+MediaSource MediaObject::source() const
+{
+    return mediaSource;
+}
+
+void MediaObject::setSource(const MediaSource & source)
+{
+    qDebug() << __FUNCTION__;
+
+    mediaSource = source;
+
+    switch (source.type()) {
+    case MediaSource::Invalid:
+        break;
+    case MediaSource::LocalFile:
+        loadMedia(mediaSource.fileName());
+        break;
+    case MediaSource::Url:
+        loadMedia(mediaSource.url().toString());
+        break;
+    case MediaSource::Disc:
+        switch (source.discType()) {
+        case Phonon::NoDisc:
+            qCritical() << __FUNCTION__
+            << "Error: the MediaSource::Disc doesn't specify which one (Phonon::NoDisc)";
+            return;
+        case Phonon::Cd:
+            loadMedia(mediaSource.deviceName());
+            break;
+        case Phonon::Dvd:
+            loadMedia("dvd://" + mediaSource.deviceName());
+            break;
+        case Phonon::Vcd:
+            loadMedia(mediaSource.deviceName());
+            break;
+        default:
+            qCritical() << __FUNCTION__ << "Error: unsupported MediaSource::Disc:" << source.discType();
+            break;
+        }
+        break;
+    case MediaSource::Stream:
+        break;
+    default:
+        qCritical() << __FUNCTION__
+        << "Error: unsupported MediaSource:"
+        << source.type();
+        break;
+    }
+}
+
+void MediaObject::setNextSource(const MediaSource & source)
+{
+    setSource(source);
+}
+
+qint32 MediaObject::prefinishMark() const
+{
+    return i_prefinish_mark;
+}
+
+void MediaObject::setPrefinishMark(qint32 msecToEnd)
+{
+    i_prefinish_mark = msecToEnd;
+    if (currentTime() < totalTime() - i_prefinish_mark) {
+        // Not about to finish
+        b_prefinish_mark_reached_emitted = false;
+    }
+}
+
+qint32 MediaObject::transitionTime() const
+{
+    return i_transition_time;
+}
+
+void MediaObject::setTransitionTime(qint32 time)
+{
+    i_transition_time = time;
+}
+
+void MediaObject::stateChangedInternal(Phonon::State newState)
+{
+    qDebug() << __FUNCTION__ << "newState:" << newState
+    << "previousState:" << currentState ;
+
+    if (newState == currentState) {
+        // State not changed
+        return;
+    }
+
+    // State changed
+    Phonon::State previousState = currentState;
+    currentState = newState;
+    emit stateChanged(currentState, previousState);
+}
+
+}
+} // Namespace Phonon::VLC
diff --git a/bindings/phonon/vlc/mediaobject.h b/bindings/phonon/vlc/mediaobject.h
new file mode 100644 (file)
index 0000000..01fdc6f
--- /dev/null
@@ -0,0 +1,126 @@
+/*****************************************************************************
+ * VLC backend for the Phonon library                                        *
+ * Copyright (C) 2007-2008 Tanguy Krotoff <tkrotoff@gmail.com>               *
+ * Copyright (C) 2008 Lukas Durfina <lukas.durfina@gmail.com>                *
+ * Copyright (C) 2009 Fathi Boudra <fabo@kde.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 3 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 package; if not, write to the Free Software       *
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA *
+ *****************************************************************************/
+
+#ifndef PHONON_VLC_MEDIAOBJECT_H
+#define PHONON_VLC_MEDIAOBJECT_H
+
+#include <phonon/mediaobjectinterface.h>
+
+#include <QtCore/QObject>
+
+namespace Phonon
+{
+namespace VLC {
+
+class SeekStack;
+
+class MediaObject : public QObject, public MediaObjectInterface
+{
+    Q_OBJECT
+    friend class SeekStack;
+
+public:
+
+    MediaObject(QObject *p_parent);
+    virtual ~MediaObject();
+
+    /**
+     * Widget Id where VLC will show the videos.
+     */
+    void setVideoWidgetId(int i_widget_id);
+
+    void play();
+    void seek(qint64 milliseconds);
+
+    qint32 tickInterval() const;
+    void setTickInterval(qint32 tickInterval);
+
+    qint64 currentTime() const;
+    Phonon::State state() const;
+    Phonon::ErrorType errorType() const;
+    MediaSource source() const;
+    void setSource(const MediaSource & source);
+    void setNextSource(const MediaSource & source);
+
+    qint32 prefinishMark() const;
+    void setPrefinishMark(qint32 msecToEnd);
+
+    qint32 transitionTime() const;
+    void setTransitionTime(qint32);
+
+signals:
+
+    void aboutToFinish();
+//    void bufferStatus( int i_percent_filled );
+//    void currentSourceChanged( const MediaSource & newSource );
+    void finished();
+    void hasVideoChanged(bool b_has_video);
+    void metaDataChanged(const QMultiMap<QString, QString> & metaData);
+    void prefinishMarkReached(qint32 msecToEnd);
+    void seekableChanged(bool b_is_seekable);
+    void stateChanged(Phonon::State newState, Phonon::State oldState);
+    void tick(qint64 time);
+    void totalTimeChanged(qint64 newTotalTime);
+
+    // Signal from VLCMediaObject
+    void stateChanged(Phonon::State newState);
+
+    void tickInternal(qint64 time);
+
+protected:
+
+    virtual void loadMediaInternal(const QString & filename) = 0;
+    virtual void playInternal() = 0;
+    virtual void seekInternal(qint64 milliseconds) = 0;
+
+    virtual qint64 currentTimeInternal() const = 0;
+
+    int i_video_widget_id;
+
+private slots:
+
+    void stateChangedInternal(Phonon::State newState);
+
+    void tickInternalSlot(qint64 time);
+
+private:
+
+    void loadMedia(const QString & filename);
+
+    void resume();
+
+    MediaSource mediaSource;
+
+    Phonon::State currentState;
+
+    qint32 i_prefinish_mark;
+    bool b_prefinish_mark_reached_emitted;
+
+    bool b_about_to_finish_emitted;
+
+    qint32 i_tick_interval;
+    qint32 i_transition_time;
+};
+
+}
+} // Namespace Phonon::VLC
+
+#endif // PHONON_VLC_MEDIAOBJECT_H
diff --git a/bindings/phonon/vlc/seekstack.cpp b/bindings/phonon/vlc/seekstack.cpp
new file mode 100644 (file)
index 0000000..a2eb145
--- /dev/null
@@ -0,0 +1,86 @@
+/*****************************************************************************
+ * VLC backend for the Phonon library                                        *
+ * Copyright (C) 2007-2008 Tanguy Krotoff <tkrotoff@gmail.com>               *
+ * Copyright (C) 2008 Lukas Durfina <lukas.durfina@gmail.com>                *
+ * Copyright (C) 2009 Fathi Boudra <fabo@kde.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 3 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 package; if not, write to the Free Software       *
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA *
+ *****************************************************************************/
+
+#include "seekstack.h"
+
+#include <QtCore/QTimer>
+#include <QtCore/QDebug>
+
+namespace Phonon
+{
+namespace VLC {
+
+SeekStack::SeekStack(MediaObject *mediaObject)
+        : QObject(mediaObject)
+{
+    p_media_object = mediaObject;
+
+    p_timer = new QTimer(this);
+    connect(p_timer, SIGNAL(timeout()),
+            SLOT(popSeek()));
+    p_timer->setInterval(1000);
+}
+
+SeekStack::~SeekStack()
+{
+}
+
+void SeekStack::pushSeek(qint64 milliseconds)
+{
+    qDebug() << __FUNCTION__ << "seek:" << milliseconds;
+
+    disconnect(p_media_object, SIGNAL(tickInternal(qint64)),
+               p_media_object, SLOT(tickInternalSlot(qint64)));
+
+    stack.push(milliseconds);
+
+    if (!p_timer->isActive()) {
+        p_timer->start();
+        popSeek();
+    }
+}
+
+void SeekStack::popSeek()
+{
+    if (stack.isEmpty()) {
+        p_timer->stop();
+        reconnectTickSignal();
+        return;
+    }
+
+    int i_milliseconds = stack.pop();
+    stack.clear();
+
+    qDebug() << __FUNCTION__ << "real seek:" << i_milliseconds;
+
+    p_media_object->seekInternal(i_milliseconds);
+
+    reconnectTickSignal();
+}
+
+void SeekStack::reconnectTickSignal()
+{
+    connect(p_media_object, SIGNAL(tickInternal(qint64)),
+            p_media_object, SLOT(tickInternalSlot(qint64)));
+}
+
+}
+} // Namespace Phonon::VLC
diff --git a/bindings/phonon/vlc/seekstack.h b/bindings/phonon/vlc/seekstack.h
new file mode 100644 (file)
index 0000000..595b41a
--- /dev/null
@@ -0,0 +1,70 @@
+/*****************************************************************************
+ * VLC backend for the Phonon library                                        *
+ * Copyright (C) 2007-2008 Tanguy Krotoff <tkrotoff@gmail.com>               *
+ * Copyright (C) 2008 Lukas Durfina <lukas.durfina@gmail.com>                *
+ * Copyright (C) 2009 Fathi Boudra <fabo@kde.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 3 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 package; if not, write to the Free Software       *
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA *
+ *****************************************************************************/
+
+#ifndef PHONON_VLC_SEEKSTACK_H
+#define PHONON_VLC_SEEKSTACK_H
+
+#include "mediaobject.h"
+
+#include <QtCore/QObject>
+#include <QtCore/QStack>
+
+class QTimer;
+
+namespace Phonon
+{
+namespace VLC {
+
+/**
+ * A queue of seek commands.
+ */
+class SeekStack : public QObject
+{
+    Q_OBJECT
+
+public:
+
+    SeekStack(MediaObject *mediaObject);
+    ~SeekStack();
+
+    void pushSeek(qint64 milliseconds);
+
+signals:
+
+private slots:
+
+    void popSeek();
+
+    void reconnectTickSignal();
+
+private:
+
+    MediaObject *p_media_object;
+
+    QTimer *p_timer;
+
+    QStack<qint64> stack;
+};
+
+}
+} // Namespace Phonon::VLC
+
+#endif // PHONON_VLC_SEEKSTACK_H
diff --git a/bindings/phonon/vlc/sinknode.cpp b/bindings/phonon/vlc/sinknode.cpp
new file mode 100644 (file)
index 0000000..dbba04c
--- /dev/null
@@ -0,0 +1,56 @@
+/*****************************************************************************
+ * VLC backend for the Phonon library                                        *
+ * Copyright (C) 2007-2008 Tanguy Krotoff <tkrotoff@gmail.com>               *
+ * Copyright (C) 2008 Lukas Durfina <lukas.durfina@gmail.com>                *
+ * Copyright (C) 2009 Fathi Boudra <fabo@kde.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 3 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 package; if not, write to the Free Software       *
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA *
+ *****************************************************************************/
+
+#include "sinknode.h"
+
+#include "mediaobject.h"
+
+namespace Phonon
+{
+namespace VLC {
+
+SinkNode::SinkNode(QObject *p_parent)
+        : QObject(p_parent)
+{
+    p_media_object = 0;
+}
+
+SinkNode::~SinkNode()
+{
+}
+
+void SinkNode::connectToMediaObject(PrivateMediaObject * mediaObject)
+{
+    if (p_media_object)
+        qCritical() << __FUNCTION__ << "p_media_object already connected";
+
+    p_media_object = mediaObject;
+}
+
+void SinkNode::disconnectFromMediaObject(PrivateMediaObject * mediaObject)
+{
+    if (p_media_object != mediaObject)
+        qCritical() << __FUNCTION__ << "SinkNode was not connected to mediaObject";
+}
+
+
+}
+} // Namespace Phonon::VLC_MPlayer
diff --git a/bindings/phonon/vlc/sinknode.h b/bindings/phonon/vlc/sinknode.h
new file mode 100644 (file)
index 0000000..10990e8
--- /dev/null
@@ -0,0 +1,59 @@
+/*****************************************************************************
+ * VLC backend for the Phonon library                                        *
+ * Copyright (C) 2007-2008 Tanguy Krotoff <tkrotoff@gmail.com>               *
+ * Copyright (C) 2008 Lukas Durfina <lukas.durfina@gmail.com>                *
+ * Copyright (C) 2009 Fathi Boudra <fabo@kde.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 3 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 package; if not, write to the Free Software       *
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA *
+ *****************************************************************************/
+
+#ifndef PHONON_VLC_SINKNODE_H
+#define PHONON_VLC_SINKNODE_H
+
+#include <QtCore/QObject>
+#include <QtCore/QString>
+
+namespace Phonon
+{
+namespace VLC {
+
+class VLCMediaObject;
+typedef VLCMediaObject PrivateMediaObject;
+
+class SinkNode : public QObject
+{
+    Q_OBJECT
+
+public:
+
+    SinkNode(QObject *p_parent);
+    virtual ~SinkNode();
+
+    virtual void connectToMediaObject(PrivateMediaObject *mediaObject);
+
+    virtual void disconnectFromMediaObject(PrivateMediaObject *mediaObject);
+
+protected:
+
+    PrivateMediaObject *p_media_object;
+
+private:
+
+};
+
+}
+} // Namespace Phonon::VLC
+
+#endif // PHONON_VLC_SINKNODE_H
diff --git a/bindings/phonon/vlc/videowidget.cpp b/bindings/phonon/vlc/videowidget.cpp
new file mode 100644 (file)
index 0000000..2afef53
--- /dev/null
@@ -0,0 +1,239 @@
+/*****************************************************************************
+ * VLC backend for the Phonon library                                        *
+ * Copyright (C) 2007-2008 Tanguy Krotoff <tkrotoff@gmail.com>               *
+ * Copyright (C) 2008 Lukas Durfina <lukas.durfina@gmail.com>                *
+ * Copyright (C) 2009 Fathi Boudra <fabo@kde.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 3 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 package; if not, write to the Free Software       *
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA *
+ *****************************************************************************/
+
+#include "videowidget.h"
+
+#include "mediaobject.h"
+#include "vlcmediaobject.h"
+
+#include "vlcloader.h"
+
+#include <QtGui/QWidget>
+#include <QtGui/QApplication>
+#include <QtGui/QDesktopWidget>
+#include <QtCore/QtDebug>
+
+namespace Phonon
+{
+namespace VLC {
+
+VideoWidget::VideoWidget(QWidget *p_parent)
+        : SinkNode(p_parent)
+{
+    p_video_widget = new Widget(p_parent);
+
+    aspect_ratio = Phonon::VideoWidget::AspectRatioAuto;
+    scale_mode = Phonon::VideoWidget::FitInView;
+
+    b_filter_adjust_activated = false;
+    f_brightness = 0.0;
+    f_contrast = 0.0;
+    f_hue = 0.0;
+    f_saturation = 0.0;
+}
+
+VideoWidget::~VideoWidget()
+{
+}
+
+void VideoWidget::connectToMediaObject(PrivateMediaObject *mediaObject)
+{
+    SinkNode::connectToMediaObject(mediaObject);
+
+    connect(mediaObject, SIGNAL(videoWidgetSizeChanged(int, int)),
+            SLOT(videoWidgetSizeChanged(int, int)));
+
+    mediaObject->setVideoWidgetId((int) p_video_widget->winId());
+}
+
+Phonon::VideoWidget::AspectRatio VideoWidget::aspectRatio() const
+{
+    return aspect_ratio;
+}
+
+// VLC accepted formats are x:y (4:3, 16:9, etc...) expressing the global image aspect
+void VideoWidget::setAspectRatio(Phonon::VideoWidget::AspectRatio aspect)
+{
+    // finish if no player
+    if (!vlc_current_media_player)
+        return;
+
+    aspect_ratio = aspect;
+
+    switch (aspect_ratio) {
+    case Phonon::VideoWidget::AspectRatioAuto: // Let the decoder find the aspect ratio automatically from the media file (this is the default)
+//        p_libvlc_video_set_aspect_ratio(p_vlc_current_media_player, "", vlc_exception);
+        vlcExceptionRaised();
+        break;
+    case Phonon::VideoWidget::AspectRatioWidget: // Fit the video into the widget making the aspect ratio depend solely on the size of the widget
+        // This way the aspect ratio is freely resizeable by the user
+//        p_libvlc_video_set_aspect_ratio(p_vlc_current_media_player, "", vlc_exception);
+        vlcExceptionRaised();
+        break;
+    case Phonon::VideoWidget::AspectRatio4_3:
+//        p_libvlc_video_set_aspect_ratio(p_vlc_current_media_player, "4:3", vlc_exception);
+        vlcExceptionRaised();
+        break;
+    case Phonon::VideoWidget::AspectRatio16_9:
+//        p_libvlc_video_set_aspect_ratio(p_vlc_current_media_player, "16:9", vlc_exception);
+        vlcExceptionRaised();
+        break;
+    default:
+        qCritical() << __FUNCTION__ << "error: unsupported AspectRatio:" << (int) aspect_ratio;
+    }
+}
+
+Phonon::VideoWidget::ScaleMode VideoWidget::scaleMode() const
+{
+    return scale_mode;
+}
+
+// The ScaleMode enumeration describes how to treat aspect ratio during resizing of video
+void VideoWidget::setScaleMode(Phonon::VideoWidget::ScaleMode scale)
+{
+    scale_mode = scale;
+    switch (scale_mode) {
+    case Phonon::VideoWidget::FitInView: // The video will be fitted to fill the view keeping aspect ratio
+        break;
+    case Phonon::VideoWidget::ScaleAndCrop: // The video is scaled
+        break;
+    default:
+        qWarning() << __FUNCTION__ << "unknow Phonon::VideoWidget::ScaleMode:" << scale_mode;
+    }
+}
+
+qreal VideoWidget::brightness() const
+{
+    return f_brightness;
+}
+
+void VideoWidget::setBrightness(qreal brightness)
+{
+    f_brightness = brightness;
+
+    // vlc takes brightness in range 0.0 - 2.0
+    if (vlc_current_media_player) {
+        if (!b_filter_adjust_activated) {
+//            p_libvlc_video_filter_add(p_vlc_current_media_player, ADJUST, vlc_exception);
+//            vlcExceptionRaised();
+            b_filter_adjust_activated = true;
+        }
+//        p_libvlc_video_set_brightness(p_vlc_current_media_player, f_brightness + 1.0, vlc_exception);
+//        vlcExceptionRaised();
+    }
+}
+
+qreal VideoWidget::contrast() const
+{
+    return f_contrast;
+}
+
+void VideoWidget::setContrast(qreal contrast)
+{
+    f_contrast = contrast;
+
+    // vlc takes contrast in range 0.0 - 2.0
+    float f_contrast = contrast;
+    if (vlc_current_media_player) {
+        if (!b_filter_adjust_activated) {
+//            p_libvlc_video_filter_add(p_vlc_current_media_player, ADJUST, vlc_exception);
+//            vlcExceptionRaised();
+            b_filter_adjust_activated = true;
+        }
+//        p_libvlc_video_set_contrast(p_vlc_current_media_player, f_contrast + 1.0, vlc_exception);
+//        vlcExceptionRaised();
+    }
+}
+
+qreal VideoWidget::hue() const
+{
+    return f_hue;
+}
+
+void VideoWidget::setHue(qreal hue)
+{
+    f_hue = hue;
+
+    // vlc takes hue in range 0 - 360 in integer
+    int i_hue = (f_hue + 1.0) * 180;
+    if (vlc_current_media_player) {
+        if (!b_filter_adjust_activated) {
+//            p_libvlc_video_filter_add(p_vlc_current_media_player, ADJUST, vlc_exception);
+//            vlcExceptionRaised();
+            b_filter_adjust_activated = true;
+        }
+//        p_libvlc_video_set_hue(p_vlc_current_media_player, i_hue, vlc_exception);
+//        vlcExceptionRaised();
+    }
+
+}
+
+qreal VideoWidget::saturation() const
+{
+    return f_saturation;
+}
+
+void VideoWidget::setSaturation(qreal saturation)
+{
+    f_saturation = saturation;
+
+    // vlc takes brightness in range 0.0 - 3.0
+    if (vlc_current_media_player) {
+        if (!b_filter_adjust_activated) {
+//            p_libvlc_video_filter_add(p_vlc_current_media_player, ADJUST, vlc_exception);
+//            vlcExceptionRaised();
+            b_filter_adjust_activated = true;
+        }
+//        p_libvlc_video_set_saturation(p_vlc_current_media_player, (f_saturation + 1.0) * 1.5, vlc_exception);
+//        vlcExceptionRaised();
+    }
+}
+
+Widget * VideoWidget::widget()
+{
+    return p_video_widget;
+}
+
+void VideoWidget::videoWidgetSizeChanged(int i_width, int i_height)
+{
+    qDebug() << __FUNCTION__ << "video width" << i_width << "height:" << i_height;
+
+    // It resizes dynamically the widget and the main window
+    // Note: I didn't find another way
+
+    QSize videoSize(i_width, i_height);
+    videoSize.boundedTo(QApplication::desktop()->availableGeometry().size());
+
+    p_video_widget->hide();
+    p_video_widget->setVideoSize(videoSize);
+#ifdef Q_OS_WIN
+    QWidget *p_parent = qobject_cast<QWidget *>(this->parent());
+    QSize previousSize = p_parent->minimumSize();
+    p_parent->setMinimumSize(videoSize);
+#endif
+    p_video_widget->show();
+#ifdef Q_OS_WIN
+    p_parent->setMinimumSize(previousSize);
+#endif
+}
+
+}
+} // Namespace Phonon::VLC
diff --git a/bindings/phonon/vlc/videowidget.h b/bindings/phonon/vlc/videowidget.h
new file mode 100644 (file)
index 0000000..89286c9
--- /dev/null
@@ -0,0 +1,91 @@
+/*****************************************************************************
+ * VLC backend for the Phonon library                                        *
+ * Copyright (C) 2007-2008 Tanguy Krotoff <tkrotoff@gmail.com>               *
+ * Copyright (C) 2008 Lukas Durfina <lukas.durfina@gmail.com>                *
+ * Copyright (C) 2009 Fathi Boudra <fabo@kde.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 3 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 package; if not, write to the Free Software       *
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA *
+ *****************************************************************************/
+
+#ifndef PHONON_VLC_VIDEOWIDGET_H
+#define PHONON_VLC_VIDEOWIDGET_H
+
+#include "sinknode.h"
+
+#include <phonon/videowidgetinterface.h>
+
+#include "vlcvideowidget.h"
+typedef Phonon::VLC::VLCVideoWidget Widget;
+
+
+namespace Phonon
+{
+namespace VLC {
+
+
+class VideoWidget : public SinkNode, public VideoWidgetInterface
+{
+    Q_OBJECT
+    Q_INTERFACES(Phonon::VideoWidgetInterface)
+public:
+
+    VideoWidget(QWidget *p_parent);
+    ~VideoWidget();
+
+    void connectToMediaObject(PrivateMediaObject * mediaObject);
+
+    Phonon::VideoWidget::AspectRatio aspectRatio() const;
+    void setAspectRatio(Phonon::VideoWidget::AspectRatio aspect);
+
+    Phonon::VideoWidget::ScaleMode scaleMode() const;
+    void setScaleMode(Phonon::VideoWidget::ScaleMode scale);
+
+    qreal brightness() const;
+    void setBrightness(qreal brightness);
+
+    qreal contrast() const;
+    void setContrast(qreal contrast);
+
+    qreal hue() const;
+    void setHue(qreal hue);
+
+    qreal saturation() const;
+    void setSaturation(qreal saturation);
+
+    Widget * widget();
+
+private slots:
+
+    void videoWidgetSizeChanged(int width, int height);
+
+private:
+
+    Widget *p_video_widget;
+
+    Phonon::VideoWidget::AspectRatio aspect_ratio;
+
+    Phonon::VideoWidget::ScaleMode scale_mode;
+
+    bool  b_filter_adjust_activated;
+    qreal f_brightness;
+    qreal f_contrast;
+    qreal f_hue;
+    qreal f_saturation;
+};
+
+}
+} // Namespace Phonon::VLC
+
+#endif // PHONON_VLC_VIDEOWIDGET_H
diff --git a/bindings/phonon/vlc/vlc.desktop b/bindings/phonon/vlc/vlc.desktop
new file mode 100644 (file)
index 0000000..e274edb
--- /dev/null
@@ -0,0 +1,30 @@
+[Desktop Entry]
+Type=Service
+X-KDE-ServiceTypes=PhononBackend
+MimeType=application/x-annodex;video/quicktime;video/x-quicktime;audio/x-m4a;application/x-quicktimeplayer;video/mkv;video/msvideo;video/x-msvideo;video/x-flic;audio/x-aiff;audio/aiff;audio/x-pn-aiff;audio/x-realaudio;audio/basic;audio/x-basic;audio/x-pn-au;audio/x-8svx;audio/8svx;audio/x-16sv;audio/168sv;image/x-ilbm;image/ilbm;video/x-anim;video/anim;image/png;image/x-png;video/mng;video/x-mng;audio/x-ogg;audio/x-speex+ogg;application/ogg;application/ogg;audio/vnd.rn-realaudio;audio/x-pn-realaudio-plugin;audio/x-real-audio;application/vnd.rn-realmedia;video/mpeg;video/x-mpeg;audio/x-wav;audio/wav;audio/x-pn-wav;audio/x-pn-windows-acm;audio/mpeg2;audio/x-mpeg2;audio/mpeg3;audio/x-mpeg3;audio/mpeg;audio/x-mpeg;x-mpegurl;audio/x-mpegurl;audio/mp3;audio/mpeg;video/x-ms-asf;application/x-flash-video;
+X-KDE-Library=phonon_vlc
+X-KDE-PhononBackendInfo-InterfaceVersion=1
+X-KDE-PhononBackendInfo-Version=0.1
+X-KDE-PhononBackendInfo-Website=http://www.videolan.org/
+Icon=phonon-vlc
+InitialPreference=10
+
+Name=VLC
+Name[x-test]=xxVLCxx
+
+Comment=Phonon VLC backend
+Comment[el]=Σύστημα υποστήριξης Phonon του VLC
+Comment[et]=Phononi VLC taustaprogramm
+Comment[fr]=Système de gestion VLC pour Phonon
+Comment[ga]=Inneall VLC Phonon
+Comment[gl]=Infraestrutura de VLC para Phonon
+Comment[km]=កម្មវិធី​ខាងក្រោយ​របស់ Phonon VLC
+Comment[nb]=Phonon VLC-motor
+Comment[nds]=Phonon-Hülpprogramm VLC
+Comment[nl]=VLC-backend (Phonon)
+Comment[pt]=Infra-estrutura do VLC para o Phonon
+Comment[pt_BR]=Infraestrutura Phonon VLC
+Comment[sv]=Phonon VLC-gränssnitt
+Comment[tr]=Phonon VLC arka ucu
+Comment[uk]=Сервер VLC Phonon
+Comment[x-test]=xxPhonon VLC backendxx
diff --git a/bindings/phonon/vlc/vlcloader.cpp b/bindings/phonon/vlc/vlcloader.cpp
new file mode 100644 (file)
index 0000000..d3856b3
--- /dev/null
@@ -0,0 +1,203 @@
+/*****************************************************************************
+ * VLC backend for the Phonon library                                        *
+ * Copyright (C) 2007-2008 Tanguy Krotoff <tkrotoff@gmail.com>               *
+ * Copyright (C) 2008 Lukas Durfina <lukas.durfina@gmail.com>                *
+ * Copyright (C) 2009 Fathi Boudra <fabo@kde.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 3 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 package; if not, write to the Free Software       *
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA *
+ *****************************************************************************/
+
+#include "vlcloader.h"
+
+#include <QtCore/QDebug>
+#include <QtCore/QDir>
+#include <QtCore/QLibrary>
+#include <QtCore/QSettings>
+#include <QtCore/QString>
+#include <QtCore/QStringList>
+
+// Global variables
+libvlc_instance_t *vlc_instance = 0;
+libvlc_exception_t *vlc_exception = new libvlc_exception_t();
+libvlc_media_player_t *vlc_current_media_player = 0;
+
+namespace Phonon
+{
+namespace VLC {
+
+bool vlcInit()
+{
+    // Global variables
+    vlc_instance = 0;
+    vlc_exception = new libvlc_exception_t();
+
+    QString path = vlcPath();
+    if (!path.isEmpty()) {
+        QString pluginsPath = path;
+#if defined(Q_OS_UNIX)
+        pluginsPath.append("/vlc");
+#elif defined(Q_OS_WIN)
+        pluginsPath.append("\plugins");
+#endif
+        // VLC command line options. See vlc --full-help
+        const char *vlcArgs[] = {
+            path.toLatin1().constData(),
+            "--plugin-path=", pluginsPath.toAscii().constData(),
+            "--verbose=2",
+            "--intf=dummy",
+            "--extraintf=logger",
+            "--ignore-config",
+            "--reset-plugins-cache",
+            "--no-media-library",
+            "--no-one-instance",
+            "--no-osd",
+            "--no-stats",
+            "--no-video-title-show"
+        };
+
+        libvlc_exception_init(vlc_exception);
+
+        // Create and initialize a libvlc instance (it should be done only once)
+        vlc_instance = libvlc_new(sizeof(vlcArgs) / sizeof(*vlcArgs),
+                                  vlcArgs,
+                                  vlc_exception);
+        vlcExceptionRaised();
+
+        return true;
+    } else {
+        return false;
+    }
+}
+
+void vlcRelease()
+{
+    libvlc_release(vlc_instance);
+    vlcExceptionRaised();
+    vlcUnload();
+}
+
+void vlcExceptionRaised()
+{
+    if (libvlc_exception_raised(vlc_exception)) {
+        qDebug() << "libvlc exception:" << libvlc_exception_get_message(vlc_exception);
+        libvlc_exception_clear(vlc_exception);
+    }
+}
+
+#if defined(Q_OS_UNIX)
+static bool libGreaterThan(const QString &lhs, const QString &rhs)
+{
+    QStringList lhsparts = lhs.split(QLatin1Char('.'));
+    QStringList rhsparts = rhs.split(QLatin1Char('.'));
+    Q_ASSERT(lhsparts.count() > 1 && rhsparts.count() > 1);
+
+    for (int i = 1; i < rhsparts.count(); ++i) {
+        if (lhsparts.count() <= i)
+            // left hand side is shorter, so it's less than rhs
+            return false;
+
+        bool ok = false;
+        int b = 0;
+        int a = lhsparts.at(i).toInt(&ok);
+        if (ok)
+            b = rhsparts.at(i).toInt(&ok);
+        if (ok) {
+            // both toInt succeeded
+            if (a == b)
+                continue;
+            return a > b;
+        } else {
+            // compare as strings;
+            if (lhsparts.at(i) == rhsparts.at(i))
+                continue;
+            return lhsparts.at(i) > rhsparts.at(i);
+        }
+    }
+
+    // they compared strictly equally so far
+    // lhs cannot be less than rhs
+    return true;
+}
+#endif
+
+static QStringList findAllLibVlc()
+{
+    QStringList paths;
+#if defined(Q_OS_UNIX)
+    paths = QString::fromLatin1(qgetenv("LD_LIBRARY_PATH"))
+            .split(QLatin1Char(':'), QString::SkipEmptyParts);
+    paths << QLatin1String("/usr/lib") << QLatin1String("/usr/local/lib");
+
+    QStringList foundVlcs;
+    foreach (const QString &path, paths) {
+        QDir dir = QDir(path);
+        QStringList entryList = dir.entryList(QStringList() << QLatin1String("libvlc.*"), QDir::Files);
+
+        qSort(entryList.begin(), entryList.end(), libGreaterThan);
+        foreach (const QString &entry, entryList)
+            foundVlcs << path + QLatin1Char('/') + entry;
+    }
+
+    return foundVlcs;
+#elif defined(Q_OS_WIN)
+    // Read VLC version and installation directory from Windows registry
+    QSettings settings(QSettings::SystemScope, "VideoLAN", "VLC");
+    QString vlcVersion = settings.value("Version").toString();
+    QString vlcInstallDir = settings.value("InstallDir").toString();
+    if (vlcVersion.startsWith("1.0") && !vlcInstallDir.isEmpty()) {
+        paths << vlcInstallDir + QLatin1Char('\') + "libvlc";
+        return paths;
+    } else {
+        return QString();
+    }
+#endif
+}
+
+static QLibrary *vlcLibrary = 0;
+
+QString vlcPath()
+{
+    static QString path;
+    if (!path.isEmpty()) {
+        return path;
+    }
+
+    vlcLibrary = new QLibrary();
+    QStringList paths = findAllLibVlc();
+    foreach(path, paths) {
+        vlcLibrary->setFileName(path);
+
+        if (vlcLibrary->resolve("libvlc_exception_init")) {
+            return path;
+        } else {
+            qDebug("Cannot resolve the symbol or load VLC library");
+        }
+        qWarning() << vlcLibrary->errorString();
+    }
+
+    vlcUnload();
+
+    return QString();
+}
+
+void vlcUnload()
+{
+    vlcLibrary->unload();
+    delete vlcLibrary;
+    vlcLibrary = 0;
+}
+
+}
+} // Namespace Phonon::VLC
diff --git a/bindings/phonon/vlc/vlcloader.h b/bindings/phonon/vlc/vlcloader.h
new file mode 100644 (file)
index 0000000..e47175a
--- /dev/null
@@ -0,0 +1,84 @@
+/*****************************************************************************
+ * VLC backend for the Phonon library                                        *
+ * Copyright (C) 2007-2008 Tanguy Krotoff <tkrotoff@gmail.com>               *
+ * Copyright (C) 2008 Lukas Durfina <lukas.durfina@gmail.com>                *
+ * Copyright (C) 2009 Fathi Boudra <fabo@kde.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 3 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 package; if not, write to the Free Software       *
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA *
+ *****************************************************************************/
+
+#ifndef PHONON_VLC_VLC_LOADER_H
+#define PHONON_VLC_VLC_LOADER_H
+
+#include <vlc/vlc.h>
+
+class QString;
+
+/**
+ * VLC library instance global variable.
+ */
+extern libvlc_instance_t *vlc_instance;
+
+/**
+ * VLC library exception handling global variable.
+ */
+extern libvlc_exception_t *vlc_exception;
+
+/**
+ * VLC library media player global variable.
+ */
+extern libvlc_media_player_t *vlc_current_media_player;
+
+namespace Phonon
+{
+namespace VLC {
+
+/**
+ * Get VLC path.
+ *
+ * @return the VLC path
+ */
+QString vlcPath();
+
+/**
+ * Unload VLC library.
+ */
+void vlcUnload();
+
+/**
+ * Check for a VLC library exception.
+ *
+ * show an error message when an exception has been raised.
+ */
+void vlcExceptionRaised();
+
+/**
+ * Initialize and launch VLC library.
+ *
+ * instance and exception handling global variables are initialized.
+ *
+ * @return VLC initialization result
+ */
+bool vlcInit();
+
+/**
+ * Stop VLC library.
+ */
+void vlcRelease();
+
+}
+} // Namespace Phonon::VLC
+
+#endif // PHONON_VLC_VLC_LOADER_H
diff --git a/bindings/phonon/vlc/vlcmediacontroller.cpp b/bindings/phonon/vlc/vlcmediacontroller.cpp
new file mode 100644 (file)
index 0000000..fea7939
--- /dev/null
@@ -0,0 +1,295 @@
+/*****************************************************************************
+ * VLC backend for the Phonon library                                        *
+ * Copyright (C) 2007-2008 Tanguy Krotoff <tkrotoff@gmail.com>               *
+ * Copyright (C) 2008 Lukas Durfina <lukas.durfina@gmail.com>                *
+ * Copyright (C) 2009 Fathi Boudra <fabo@kde.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 3 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 package; if not, write to the Free Software       *
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA *
+ *****************************************************************************/
+
+#include "vlcmediacontroller.h"
+
+#include "vlcloader.h"
+
+namespace Phonon
+{
+namespace VLC {
+
+VLCMediaController::VLCMediaController()
+        : MediaController()
+{
+    p_vlc_media_player = 0;
+}
+
+VLCMediaController::~VLCMediaController()
+{
+}
+
+void VLCMediaController::clearMediaController()
+{
+    current_audio_channel = Phonon::AudioChannelDescription();
+    available_audio_channels.clear();
+
+    current_subtitle = Phonon::SubtitleDescription();
+    available_subtitles.clear();
+
+    i_current_angle = 0;
+    i_available_angles = 0;
+
+//    current_chapter = Phonon::ChapterDescription();
+//    available_chapters.clear();
+    current_chapter = 0;
+    available_chapters = 0;
+
+//    current_title = Phonon::TitleDescription();
+//    available_titles.clear();
+    current_title = 0;
+    available_titles = 0;
+
+    b_autoplay_titles = false;
+
+    emit availableAudioChannelsChanged();
+    emit availableSubtitlesChanged();
+    emit availableTitlesChanged(0);
+    emit availableChaptersChanged(0);
+}
+
+// Add audio channel -> in libvlc it is track, it means audio in another language
+void VLCMediaController::audioChannelAdded(int id, const QString & lang)
+{
+    QHash<QByteArray, QVariant> properties;
+    properties.insert("name", lang);
+    properties.insert("description", "");
+
+    available_audio_channels << Phonon::AudioChannelDescription(id, properties);
+    emit availableAudioChannelsChanged();
+}
+
+// Add subtitle
+void VLCMediaController::subtitleAdded(int id, const QString & lang, const QString & type)
+{
+    QHash<QByteArray, QVariant> properties;
+    properties.insert("name", lang);
+    properties.insert("description", "");
+    properties.insert("type", type);
+
+    available_subtitles << Phonon::SubtitleDescription(id, properties);
+    emit availableSubtitlesChanged();
+}
+
+// Add title
+void VLCMediaController::titleAdded(int id, const QString & name)
+{
+//    QHash<QByteArray, QVariant> properties;
+//    properties.insert("name", name);
+//    properties.insert("description", "");
+
+//    available_titles << Phonon::TitleDescription(id, properties);
+    available_titles++;
+    emit availableTitlesChanged(available_titles);
+}
+
+// Add chapter
+void VLCMediaController::chapterAdded(int titleId, const QString & name)
+{
+//    QHash<QByteArray, QVariant> properties;
+//    properties.insert("name", name);
+//    properties.insert("description", "");
+
+//    available_chapters << Phonon::ChapterDescription(titleId, properties);
+    available_chapters++;
+    emit availableChaptersChanged(available_chapters);
+}
+
+// Audio channel
+
+void VLCMediaController::setCurrentAudioChannel(const Phonon::AudioChannelDescription & audioChannel)
+{
+    current_audio_channel = audioChannel;
+    libvlc_audio_set_track(p_vlc_media_player, audioChannel.index(), vlc_exception);
+    vlcExceptionRaised();
+}
+
+QList<Phonon::AudioChannelDescription> VLCMediaController::availableAudioChannels() const
+{
+    return available_audio_channels;
+}
+
+Phonon::AudioChannelDescription VLCMediaController::currentAudioChannel() const
+{
+    return current_audio_channel;
+}
+
+void VLCMediaController::refreshAudioChannels()
+{
+    current_audio_channel = Phonon::AudioChannelDescription();
+    available_audio_channels.clear();
+
+    libvlc_track_description_t * p_info = libvlc_audio_get_track_description(
+                                              p_vlc_media_player, vlc_exception);
+    vlcExceptionRaised();
+    while (p_info) {
+        audioChannelAdded(p_info->i_id, p_info->psz_name);
+        p_info = p_info->p_next;
+    }
+    libvlc_track_description_release(p_info);
+}
+
+// Subtitle
+
+void VLCMediaController::setCurrentSubtitle(const Phonon::SubtitleDescription & subtitle)
+{
+    current_subtitle = subtitle;
+//    int id = current_subtitle.index();
+    QString type = current_subtitle.property("type").toString();
+
+    if (type == "file") {
+        QString filename = current_subtitle.property("name").toString();
+        if (!filename.isEmpty()) {
+            libvlc_video_set_subtitle_file(p_vlc_media_player,
+                                           filename.toAscii().data(),
+                                           vlc_exception);
+            vlcExceptionRaised();
+
+            // There is no subtitle event inside libvlc so let's send our own event...
+            available_subtitles << current_subtitle;
+            emit availableSubtitlesChanged();
+        }
+    } else {
+        libvlc_video_set_spu(p_vlc_media_player, subtitle.index(), vlc_exception);
+        vlcExceptionRaised();
+    }
+}
+
+QList<Phonon::SubtitleDescription> VLCMediaController::availableSubtitles() const
+{
+    return available_subtitles;
+}
+
+Phonon::SubtitleDescription VLCMediaController::currentSubtitle() const
+{
+    return current_subtitle;
+}
+
+void VLCMediaController::refreshSubtitles()
+{
+    current_subtitle = Phonon::SubtitleDescription();
+    available_subtitles.clear();
+
+    libvlc_track_description_t *p_info = libvlc_video_get_spu_description(
+                                             p_vlc_media_player, vlc_exception);
+    vlcExceptionRaised();
+    while (p_info) {
+        subtitleAdded(p_info->i_id, p_info->psz_name, "");
+        p_info = p_info->p_next;
+    }
+    libvlc_track_description_release(p_info);
+}
+
+// Title
+
+//void VLCMediaController::setCurrentTitle( const Phonon::TitleDescription & title )
+void VLCMediaController::setCurrentTitle(int title)
+{
+    current_title = title;
+
+//    libvlc_media_player_set_title(p_vlc_media_player, title.index(), vlc_exception);
+    libvlc_media_player_set_title(p_vlc_media_player, title, vlc_exception);
+    vlcExceptionRaised();
+}
+
+//QList<Phonon::TitleDescription> VLCMediaController::availableTitles() const
+int VLCMediaController::availableTitles() const
+{
+    return available_titles;
+}
+
+//Phonon::TitleDescription VLCMediaController::currentTitle() const
+int VLCMediaController::currentTitle() const
+{
+    return current_title;
+}
+
+void VLCMediaController::setAutoplayTitles(bool autoplay)
+{
+    b_autoplay_titles = autoplay;
+}
+
+bool VLCMediaController::autoplayTitles() const
+{
+    return b_autoplay_titles;
+}
+
+// Chapter
+
+//void VLCMediaController::setCurrentChapter(const Phonon::ChapterDescription &chapter)
+void VLCMediaController::setCurrentChapter(int chapter)
+{
+    current_chapter = chapter;
+//    libvlc_media_player_set_chapter(p_vlc_media_player, chapter.index(), vlc_exception);
+    libvlc_media_player_set_chapter(p_vlc_media_player, chapter, vlc_exception);
+    vlcExceptionRaised();
+}
+
+//QList<Phonon::ChapterDescription> VLCMediaController::availableChapters() const
+int VLCMediaController::availableChapters() const
+{
+    return available_chapters;
+}
+
+//Phonon::ChapterDescription VLCMediaController::currentChapter() const
+int VLCMediaController::currentChapter() const
+{
+    return current_chapter;
+}
+
+// We need to rebuild available chapters when title is changed
+void VLCMediaController::refreshChapters(int i_title)
+{
+//    current_chapter = Phonon::ChapterDescription();
+//    available_chapters.clear();
+    current_chapter = 0;
+    available_chapters = 0;
+
+    // Get the description of available chapters for specific title
+    libvlc_track_description_t *p_info = libvlc_video_get_chapter_description(
+                                             p_vlc_media_player, i_title, vlc_exception);
+    vlcExceptionRaised();
+    while (p_info) {
+        chapterAdded(p_info->i_id, p_info->psz_name);
+        p_info = p_info->p_next;
+    }
+    libvlc_track_description_release(p_info);
+}
+
+// Angle
+
+void VLCMediaController::setCurrentAngle(int angleNumber)
+{
+    i_current_angle = angleNumber;
+}
+
+int VLCMediaController::availableAngles() const
+{
+    return i_available_angles;
+}
+
+int VLCMediaController::currentAngle() const
+{
+    return i_current_angle;
+}
+
+}
+} // Namespace Phonon::VLC
diff --git a/bindings/phonon/vlc/vlcmediacontroller.h b/bindings/phonon/vlc/vlcmediacontroller.h
new file mode 100644 (file)
index 0000000..bc41346
--- /dev/null
@@ -0,0 +1,95 @@
+/*****************************************************************************
+ * VLC backend for the Phonon library                                        *
+ * Copyright (C) 2007-2008 Tanguy Krotoff <tkrotoff@gmail.com>               *
+ * Copyright (C) 2008 Lukas Durfina <lukas.durfina@gmail.com>                *
+ * Copyright (C) 2009 Fathi Boudra <fabo@kde.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 3 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 package; if not, write to the Free Software       *
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA *
+ *****************************************************************************/
+
+#ifndef PHONON_VLC_VLCMEDIA_CONTROLLER_H
+#define PHONON_VLC_VLCMEDIA_CONTROLLER_H
+
+#include "mediacontroller.h"
+#include "vlcloader.h"
+
+namespace Phonon
+{
+namespace VLC {
+
+/**
+ * MediaController specific code for VLC.
+ */
+class VLCMediaController : public MediaController
+{
+public:
+    VLCMediaController();
+    virtual ~VLCMediaController();
+
+    void audioChannelAdded(int id, const QString & lang);
+    void subtitleAdded(int id, const QString & lang, const QString & type);
+    void titleAdded(int id, const QString & name);
+    void chapterAdded(int titleId, const QString & name);
+
+protected:
+    virtual void clearMediaController();
+
+    // AudioChannel
+    void setCurrentAudioChannel(const Phonon::AudioChannelDescription & audioChannel);
+    QList<Phonon::AudioChannelDescription> availableAudioChannels() const;
+    Phonon::AudioChannelDescription currentAudioChannel() const;
+    void refreshAudioChannels();
+
+    // Subtitle
+    void setCurrentSubtitle(const Phonon::SubtitleDescription & subtitle);
+    QList<Phonon::SubtitleDescription> availableSubtitles() const;
+    Phonon::SubtitleDescription currentSubtitle() const;
+    void refreshSubtitles();
+
+    // Angle
+    void setCurrentAngle(int angleNumber);
+    int availableAngles() const;
+    int currentAngle() const;
+
+    // Chapter
+//    void setCurrentChapter( const Phonon::ChapterDescription & chapter );
+//    QList<Phonon::ChapterDescription> availableChapters() const;
+//    Phonon::ChapterDescription currentChapter() const;
+    void setCurrentChapter(int chapterNumber);
+    int availableChapters() const;
+    int currentChapter() const;
+    void refreshChapters(int i_title);
+
+    // Title
+//    void setCurrentTitle( const Phonon::TitleDescription & title );
+//    QList<Phonon::TitleDescription> availableTitles() const;
+//    Phonon::TitleDescription currentTitle() const;
+    void setCurrentTitle(int titleNumber);
+    int availableTitles() const;
+    int currentTitle() const;
+
+    void setAutoplayTitles(bool autoplay);
+    bool autoplayTitles() const;
+
+    // MediaPlayer
+    libvlc_media_player_t *p_vlc_media_player;
+
+private:
+};
+
+}
+} // Namespace Phonon::VLC
+
+#endif
diff --git a/bindings/phonon/vlc/vlcmediaobject.cpp b/bindings/phonon/vlc/vlcmediaobject.cpp
new file mode 100644 (file)
index 0000000..3c2286f
--- /dev/null
@@ -0,0 +1,435 @@
+/*****************************************************************************
+ * VLC backend for the Phonon library                                        *
+ * Copyright (C) 2007-2008 Tanguy Krotoff <tkrotoff@gmail.com>               *
+ * Copyright (C) 2008 Lukas Durfina <lukas.durfina@gmail.com>                *
+ * Copyright (C) 2009 Fathi Boudra <fabo@kde.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 3 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 package; if not, write to the Free Software       *
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA *
+ *****************************************************************************/
+
+#include "vlcmediaobject.h"
+
+#include "videowidget.h"
+
+#include "vlcloader.h"
+
+#include <QtCore/QTimer>
+#include <QtCore/QtDebug>
+
+namespace Phonon
+{
+namespace VLC {
+
+// VLC returns a strange position
+// We have to multiply by VLC_POSITION_RESOLUTION
+static const int vlcPositionResolution = 1000;
+
+VLCMediaObject::VLCMediaObject(QObject * parent)
+        : MediaObject(parent), VLCMediaController()
+{
+    // Create an empty Media Player object
+    p_vlc_media_player = libvlc_media_player_new(vlc_instance, vlc_exception);
+    vlcExceptionRaised();
+    p_vlc_media_player_event_manager = 0;
+
+    // Media
+    p_vlc_media = 0;
+    p_vlc_media_event_manager = 0;
+
+    // Media Discoverer
+    p_vlc_media_discoverer = 0;
+    p_vlc_media_discoverer_event_manager = 0;
+
+    i_total_time = 0;
+    b_has_video = false;
+    b_seekable = false;
+}
+
+VLCMediaObject::~VLCMediaObject()
+{
+//    unloadMedia();
+    libvlc_media_player_release(p_vlc_media_player);
+}
+
+void VLCMediaObject::unloadMedia()
+{
+//    if( p_vlc_media_player ) {
+//        libvlc_media_player_release(p_vlc_media_player);
+//        p_vlc_media_player = 0;
+//    }
+
+    if (p_vlc_media) {
+        libvlc_media_release(p_vlc_media);
+        p_vlc_media = 0;
+    }
+}
+
+void VLCMediaObject::loadMediaInternal(const QString & filename)
+{
+    qDebug() << __FUNCTION__ << filename;
+
+    // Create a media with the given MRL
+    p_vlc_media = libvlc_media_new(vlc_instance, filename.toAscii(), vlc_exception);
+    vlcExceptionRaised();
+
+    // Set the media that will be used by the media player
+    libvlc_media_player_set_media(p_vlc_media_player, p_vlc_media, vlc_exception);
+    vlcExceptionRaised();
+
+    // No need to keep the media now
+//    libvlc_media_release(p_vlc_media);
+
+    // connectToAllVLCEvents() at the end since it needs p_vlc_media_player
+    connectToAllVLCEvents();
+
+    b_play_request_reached = false;
+
+    // Optimization: wait to see if play() is run just after loadMedia()
+    //               100 milliseconds should be fine
+    QTimer::singleShot(100, this, SLOT(loadMediaInternal()));
+
+    // Get meta data (artist, title, etc...)
+    updateMetaData();
+
+    // Update available audio channels/subtitles/angles/chapters/etc...
+    // i.e everything from MediaController
+    // There is no audio channel/subtitle/angle/chapter events inside libvlc
+    // so let's send our own events...
+    // This will reset the GUI
+    clearMediaController();
+}
+
+void VLCMediaObject::loadMediaInternal()
+{
+    if (b_play_request_reached) {
+        // The media is playing, no need to load it
+        return;
+    }
+
+    emit stateChanged(Phonon::StoppedState);
+}
+
+void VLCMediaObject::setVLCWidgetId()
+{
+    // Get our media player to use our window
+#if defined(Q_OS_UNIX)
+    libvlc_media_player_set_xwindow(p_vlc_media_player, i_video_widget_id, vlc_exception);
+#elif defined(Q_OS_WIN)
+    libvlc_media_player_set_hwnd(p_vlc_media_player, i_video_widget_id, vlc_exception);
+#elif defined(Q_OS_MAC)
+    libvlc_media_player_set_agl(p_vlc_media_player, i_video_widget_id, vlc_exception);
+#endif
+    vlcExceptionRaised();
+}
+
+void VLCMediaObject::playInternal()
+{
+    b_play_request_reached = true;
+
+    // Clear subtitles/chapters/etc...
+    clearMediaController();
+
+    vlc_current_media_player = p_vlc_media_player;
+
+    setVLCWidgetId();
+
+    // Play
+    libvlc_media_player_play(p_vlc_media_player, vlc_exception);
+    vlcExceptionRaised();
+}
+
+void VLCMediaObject::pause()
+{
+    libvlc_media_player_pause(p_vlc_media_player, vlc_exception);
+    vlcExceptionRaised();
+}
+
+void VLCMediaObject::stop()
+{
+    libvlc_media_player_stop(p_vlc_media_player, vlc_exception);
+    vlcExceptionRaised();
+//    unloadMedia();
+}
+
+void VLCMediaObject::seekInternal(qint64 milliseconds)
+{
+    qDebug() << __FUNCTION__ << milliseconds;
+    libvlc_media_player_set_time(p_vlc_media_player, milliseconds, vlc_exception);
+    vlcExceptionRaised();
+}
+
+QString VLCMediaObject::errorString() const
+{
+    return libvlc_exception_get_message(vlc_exception);
+}
+
+bool VLCMediaObject::hasVideo() const
+{
+    return b_has_video;
+}
+
+bool VLCMediaObject::isSeekable() const
+{
+    return b_seekable;
+}
+
+void VLCMediaObject::connectToAllVLCEvents()
+{
+    // Get the event manager from which the media player send event
+    p_vlc_media_player_event_manager = libvlc_media_player_event_manager(p_vlc_media_player, vlc_exception);
+    libvlc_event_type_t eventsMediaPlayer[] = {
+        libvlc_MediaPlayerPlaying,
+        libvlc_MediaPlayerPaused,
+        libvlc_MediaPlayerEndReached,
+        libvlc_MediaPlayerStopped,
+        libvlc_MediaPlayerEncounteredError,
+        libvlc_MediaPlayerTimeChanged,
+        libvlc_MediaPlayerTitleChanged,
+        libvlc_MediaPlayerPositionChanged,
+        libvlc_MediaPlayerSeekableChanged,
+        libvlc_MediaPlayerPausableChanged,
+    };
+    int i_nbEvents = sizeof(eventsMediaPlayer) / sizeof(*eventsMediaPlayer);
+    for (int i = 0; i < i_nbEvents; i++) {
+        libvlc_event_attach(p_vlc_media_player_event_manager, eventsMediaPlayer[i],
+                            libvlc_callback, this, vlc_exception);
+        vlcExceptionRaised();
+    }
+
+
+    // Get event manager from media descriptor object
+    p_vlc_media_event_manager = libvlc_media_event_manager(p_vlc_media, vlc_exception);
+    libvlc_event_type_t eventsMedia[] = {
+        libvlc_MediaMetaChanged,
+        libvlc_MediaSubItemAdded,
+        libvlc_MediaDurationChanged,
+        // FIXME libvlc does not know this event
+//    libvlc_MediaPreparsedChanged,
+        libvlc_MediaFreed,
+        libvlc_MediaStateChanged,
+    };
+    i_nbEvents = sizeof(eventsMedia) / sizeof(*eventsMedia);
+    for (int i = 0; i < i_nbEvents; i++) {
+        libvlc_event_attach(p_vlc_media_event_manager, eventsMedia[i], libvlc_callback, this, vlc_exception);
+        vlcExceptionRaised();
+    }
+
+    // Get event manager from media service discoverer object
+    // FIXME why libvlc_media_discoverer_event_manager() does not take a libvlc_exception_t ?
+//    p_vlc_media_discoverer_event_manager = libvlc_media_discoverer_event_manager(p_vlc_media_discoverer);
+//    libvlc_event_type_t eventsMediaDiscoverer[] = {
+//        libvlc_MediaDiscovererStarted,
+//        libvlc_MediaDiscovererEnded
+//    };
+//    nbEvents = sizeof(eventsMediaDiscoverer) / sizeof(*eventsMediaDiscoverer);
+//    for (int i = 0; i < nbEvents; i++) {
+//        libvlc_event_attach(p_vlc_media_discoverer_event_manager, eventsMediaDiscoverer[i], libvlc_callback, this, vlc_exception);
+//    }
+}
+
+void VLCMediaObject::libvlc_callback(const libvlc_event_t *p_event, void *p_user_data)
+{
+    static int i_first_time_media_player_time_changed = 0;
+    static bool b_media_player_title_changed = false;
+
+    VLCMediaObject *p_vlc_mediaObject = (VLCMediaObject *) p_user_data;
+
+//    qDebug() << (int)pp_vlc_mediaObject << "event:" << libvlc_event_type_name(event->type);
+
+    // Media player events
+    if (p_event->type == libvlc_MediaPlayerTimeChanged) {
+
+        i_first_time_media_player_time_changed++;
+
+        // FIXME It is ugly. It should be solved by some events in libvlc
+        if (i_first_time_media_player_time_changed == 15) {
+            // Update metadata
+            p_vlc_mediaObject->updateMetaData();
+
+            // Is this media player seekable
+            bool b_seekable = libvlc_media_player_is_seekable(p_vlc_mediaObject->p_vlc_media_player, vlc_exception);
+            vlcExceptionRaised();
+            if (b_seekable != p_vlc_mediaObject->b_seekable) {
+                qDebug() << "libvlc_callback(): isSeekable:" << b_seekable;
+                p_vlc_mediaObject->b_seekable = b_seekable;
+                emit p_vlc_mediaObject->seekableChanged(p_vlc_mediaObject->b_seekable);
+            }
+
+            // Get current video width
+            int i_width = libvlc_video_get_width(p_vlc_mediaObject->p_vlc_media_player, vlc_exception);
+            vlcExceptionRaised();
+
+            // Get current video height
+            int i_height = libvlc_video_get_height(p_vlc_mediaObject->p_vlc_media_player, vlc_exception);
+            vlcExceptionRaised();
+            emit p_vlc_mediaObject->videoWidgetSizeChanged(i_width, i_height);
+
+            // Does this media player have a video output
+            bool b_has_video = libvlc_media_player_has_vout(p_vlc_mediaObject->p_vlc_media_player, vlc_exception);
+            vlcExceptionRaised();
+            if (b_has_video != p_vlc_mediaObject->b_has_video) {
+                p_vlc_mediaObject->b_has_video = b_has_video;
+                emit p_vlc_mediaObject->hasVideoChanged(p_vlc_mediaObject->b_has_video);
+            }
+
+            if (b_has_video) {
+                // Give info about audio tracks
+                p_vlc_mediaObject->refreshAudioChannels();
+                // Give info about subtitle tracks
+                p_vlc_mediaObject->refreshSubtitles();
+
+                // Get movie chapter count
+                // It is not a title/chapter media if there is no chapter
+                if (libvlc_media_player_get_chapter_count(
+                            p_vlc_mediaObject->p_vlc_media_player, vlc_exception) > 0) {
+                    vlcExceptionRaised();
+                    // Give info about title
+                    // only first time, no when title changed
+                    if (!b_media_player_title_changed) {
+                        libvlc_track_description_t *p_info = libvlc_video_get_title_description(
+                                                                 p_vlc_mediaObject->p_vlc_media_player, vlc_exception);
+                        vlcExceptionRaised();
+                        while (p_info) {
+                            p_vlc_mediaObject->titleAdded(p_info->i_id, p_info->psz_name);
+                            p_info = p_info->p_next;
+                        }
+                        libvlc_track_description_release(p_info);
+                    }
+
+                    // Give info about chapters for actual title 0
+                    if (b_media_player_title_changed)
+                        p_vlc_mediaObject->refreshChapters(libvlc_media_player_get_title(
+                                                               p_vlc_mediaObject->p_vlc_media_player, vlc_exception));
+                    else
+                        p_vlc_mediaObject->refreshChapters(0);
+                }
+                if (b_media_player_title_changed)
+                    b_media_player_title_changed = false;
+            }
+
+            // Bugfix with Qt mediaplayer example
+            // Now we are in playing state
+            emit p_vlc_mediaObject->stateChanged(Phonon::PlayingState);
+        }
+
+        emit p_vlc_mediaObject->tickInternal(p_vlc_mediaObject->currentTime());
+    }
+
+    if (p_event->type == libvlc_MediaPlayerPlaying) {
+        if (p_vlc_mediaObject->state() != Phonon::LoadingState) {
+            // Bugfix with Qt mediaplayer example
+            emit p_vlc_mediaObject->stateChanged(Phonon::PlayingState);
+        }
+    }
+
+    if (p_event->type == libvlc_MediaPlayerPaused) {
+        emit p_vlc_mediaObject->stateChanged(Phonon::PausedState);
+    }
+
+    if (p_event->type == libvlc_MediaPlayerEndReached) {
+        i_first_time_media_player_time_changed = 0;
+        p_vlc_mediaObject->clearMediaController();
+        emit p_vlc_mediaObject->stateChanged(Phonon::StoppedState);
+        emit p_vlc_mediaObject->finished();
+    }
+
+    if (p_event->type == libvlc_MediaPlayerStopped) {
+        i_first_time_media_player_time_changed = 0;
+        p_vlc_mediaObject->clearMediaController();
+        emit p_vlc_mediaObject->stateChanged(Phonon::StoppedState);
+    }
+
+    if (p_event->type == libvlc_MediaPlayerTitleChanged) {
+        i_first_time_media_player_time_changed = 0;
+        b_media_player_title_changed = true;
+    }
+
+    // Media events
+
+    if (p_event->type == libvlc_MediaDurationChanged) {
+        // Get duration of media descriptor object item
+        libvlc_time_t totalTime = libvlc_media_get_duration(p_vlc_mediaObject->p_vlc_media, vlc_exception);
+        vlcExceptionRaised();
+        totalTime = totalTime / vlcPositionResolution;
+
+        if (totalTime != p_vlc_mediaObject->i_total_time) {
+            p_vlc_mediaObject->i_total_time = totalTime;
+            emit p_vlc_mediaObject->totalTimeChanged(p_vlc_mediaObject->i_total_time);
+        }
+    }
+
+    if (p_event->type == libvlc_MediaMetaChanged) {
+    }
+}
+
+void VLCMediaObject::updateMetaData()
+{
+    QMultiMap<QString, QString> metaDataMap;
+
+    metaDataMap.insert(QLatin1String("ARTIST"),
+                       QString::fromUtf8(libvlc_media_get_meta(p_vlc_media, libvlc_meta_Artist, vlc_exception)));
+    vlcExceptionRaised();
+    metaDataMap.insert(QLatin1String("ALBUM"),
+                       QString::fromUtf8(libvlc_media_get_meta(p_vlc_media, libvlc_meta_Album, vlc_exception)));
+    vlcExceptionRaised();
+    metaDataMap.insert(QLatin1String("TITLE"),
+                       QString::fromUtf8(libvlc_media_get_meta(p_vlc_media, libvlc_meta_Title, vlc_exception)));
+    vlcExceptionRaised();
+    metaDataMap.insert(QLatin1String("DATE"),
+                       QString::fromUtf8(libvlc_media_get_meta(p_vlc_media, libvlc_meta_Date, vlc_exception)));
+    vlcExceptionRaised();
+    metaDataMap.insert(QLatin1String("GENRE"),
+                       QString::fromUtf8(libvlc_media_get_meta(p_vlc_media, libvlc_meta_Genre, vlc_exception)));
+    vlcExceptionRaised();
+    metaDataMap.insert(QLatin1String("TRACKNUMBER"),
+                       QString::fromUtf8(libvlc_media_get_meta(p_vlc_media, libvlc_meta_TrackNumber, vlc_exception)));
+    vlcExceptionRaised();
+    metaDataMap.insert(QLatin1String("DESCRIPTION"),
+                       QString::fromUtf8(libvlc_media_get_meta(p_vlc_media, libvlc_meta_Description, vlc_exception)));
+    vlcExceptionRaised();
+    metaDataMap.insert(QLatin1String("COPYRIGHT"),
+                       QString::fromUtf8(libvlc_media_get_meta(p_vlc_media, libvlc_meta_TrackNumber, vlc_exception)));
+    vlcExceptionRaised();
+    metaDataMap.insert(QLatin1String("URL"),
+                       QString::fromUtf8(libvlc_media_get_meta(p_vlc_media, libvlc_meta_URL, vlc_exception)));
+    vlcExceptionRaised();
+    metaDataMap.insert(QLatin1String("ENCODEDBY"),
+                       QString::fromUtf8(libvlc_media_get_meta(p_vlc_media, libvlc_meta_EncodedBy, vlc_exception)));
+
+    qDebug() << "updateMetaData(): artist:"
+    << libvlc_media_get_meta(p_vlc_media, libvlc_meta_Artist, vlc_exception);
+    vlcExceptionRaised();
+    qDebug() << "updateMetaData(): title:"
+    << libvlc_media_get_meta(p_vlc_media, libvlc_meta_Title, vlc_exception);
+    vlcExceptionRaised();
+
+    emit metaDataChanged(metaDataMap);
+}
+
+qint64 VLCMediaObject::totalTime() const
+{
+    return i_total_time;
+}
+
+qint64 VLCMediaObject::currentTimeInternal() const
+{
+    libvlc_time_t time = libvlc_media_player_get_time(p_vlc_media_player, vlc_exception);
+    vlcExceptionRaised();
+
+    return time;
+}
+
+}
+} // Namespace Phonon::VLC
diff --git a/bindings/phonon/vlc/vlcmediaobject.h b/bindings/phonon/vlc/vlcmediaobject.h
new file mode 100644 (file)
index 0000000..0972fbd
--- /dev/null
@@ -0,0 +1,160 @@
+/*****************************************************************************
+ * VLC backend for the Phonon library                                        *
+ * Copyright (C) 2007-2008 Tanguy Krotoff <tkrotoff@gmail.com>               *
+ * Copyright (C) 2008 Lukas Durfina <lukas.durfina@gmail.com>                *
+ * Copyright (C) 2009 Fathi Boudra <fabo@kde.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 3 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 package; if not, write to the Free Software       *
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA *
+ *****************************************************************************/
+
+#ifndef PHONON_VLC_VLCMEDIAOBJECT_H
+#define PHONON_VLC_VLCMEDIAOBJECT_H
+
+#include "vlcmediacontroller.h"
+
+#include "mediaobject.h"
+
+#include <phonon/mediaobjectinterface.h>
+#include <phonon/addoninterface.h>
+
+#include <QtCore/QObject>
+#include <QtCore/QString>
+#include <QtCore/QMultiMap>
+
+namespace Phonon
+{
+namespace VLC {
+
+/**
+ * VLC MediaObject.
+ *
+ * This is the "brain" of the VLC backend.
+ * VLCMediaObject uses libvlc in order to send commands and receive events from the VLC.
+ *
+ * Encapsulates VLC specific code.
+ * Take care of libvlc events via libvlc_callback()
+ *
+ * @see MediaObject
+ */
+class VLCMediaObject : public MediaObject, public VLCMediaController
+{
+    Q_OBJECT
+    Q_INTERFACES(Phonon::MediaObjectInterface  Phonon::AddonInterface)
+
+public:
+
+    VLCMediaObject(QObject * parent);
+    ~VLCMediaObject();
+
+    void pause();
+    void stop();
+
+    bool hasVideo() const;
+    bool isSeekable() const;
+
+    qint64 totalTime() const;
+
+    QString errorString() const;
+
+signals:
+
+    // MediaController signals
+    void availableSubtitlesChanged();
+    void availableAudioChannelsChanged();
+
+//    void availableChaptersChanged();
+//    void availableTitlesChanged();
+    void availableChaptersChanged(int);
+    void availableTitlesChanged(int);
+
+    void availableAnglesChanged(int availableAngles);
+    void angleChanged(int angleNumber);
+    void chapterChanged(int chapterNumber);
+    void titleChanged(int titleNumber);
+
+    /**
+     * New widget size computed by VLC.
+     *
+     * It should be applied to the widget that contains the VLC video.
+     */
+    void videoWidgetSizeChanged(int i_width, int i_height);
+
+protected:
+
+    void loadMediaInternal(const QString & filename);
+    void playInternal();
+    void seekInternal(qint64 milliseconds);
+
+    qint64 currentTimeInternal() const;
+
+private slots:
+
+    void loadMediaInternal();
+
+private:
+
+    /**
+     * Connect libvlc_callback() to all vlc events.
+     *
+     * @see libvlc_callback()
+     */
+    void connectToAllVLCEvents();
+
+    /**
+     * Retrieve meta data of a file (i.e ARTIST, TITLE, ALBUM, etc...).
+     */
+    void updateMetaData();
+
+    /**
+     * Libvlc callback.
+     *
+     * Receive all vlc events.
+     *
+     * Warning: owned by libvlc thread.
+     *
+     * @see connectToAllVLCEvents()
+     * @see libvlc_event_attach()
+     */
+    static void libvlc_callback(const libvlc_event_t *p_event, void *p_user_data);
+
+    void unloadMedia();
+
+    void setVLCWidgetId();
+
+    // MediaPlayer
+//    libvlc_media_player_t * p_vlc_media_player;
+    libvlc_event_manager_t * p_vlc_media_player_event_manager;
+
+    // Media
+    libvlc_media_t * p_vlc_media;
+    libvlc_event_manager_t * p_vlc_media_event_manager;
+
+    // MediaDiscoverer
+    libvlc_media_discoverer_t * p_vlc_media_discoverer;
+    libvlc_event_manager_t * p_vlc_media_discoverer_event_manager;
+
+    bool b_play_request_reached;
+
+    qint64 i_total_time;
+
+    bool b_has_video;
+
+    bool b_seekable;
+};
+
+}
+} // Namespace Phonon::VLC
+
+#endif
diff --git a/bindings/phonon/vlc/vlcvideowidget.cpp b/bindings/phonon/vlc/vlcvideowidget.cpp
new file mode 100644 (file)
index 0000000..e21767e
--- /dev/null
@@ -0,0 +1,66 @@
+/*****************************************************************************
+ * VLC backend for the Phonon library                                        *
+ * Copyright (C) 2007-2008 Tanguy Krotoff <tkrotoff@gmail.com>               *
+ * Copyright (C) 2008 Lukas Durfina <lukas.durfina@gmail.com>                *
+ * Copyright (C) 2009 Fathi Boudra <fabo@kde.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 3 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 package; if not, write to the Free Software       *
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA *
+ *****************************************************************************/
+
+#include "vlcvideowidget.h"
+
+#include <QtGui/QResizeEvent>
+#include <QtCore/QDebug>
+
+namespace Phonon
+{
+namespace VLC {
+
+VLCVideoWidget::VLCVideoWidget(QWidget *p_parent)
+        : WidgetNoPaintEvent(p_parent)
+{
+    // Set background color
+    setBackgroundColor(Qt::black);
+}
+
+VLCVideoWidget::~VLCVideoWidget()
+{
+}
+
+void VLCVideoWidget::resizeEvent(QResizeEvent *p_event)
+{
+    qDebug() << "resizeEvent" << p_event->size();
+}
+
+void VLCVideoWidget::setAspectRatio(double f_aspect_ratio)
+{
+}
+
+void VLCVideoWidget::setScaleAndCropMode(bool b_scale_and_crop)
+{
+}
+
+void VLCVideoWidget::setVideoSize(const QSize & size)
+{
+    videoSize = size;
+}
+
+QSize VLCVideoWidget::sizeHint() const
+{
+    return videoSize;
+}
+
+}
+} // Namespace Phonon::VLC
diff --git a/bindings/phonon/vlc/vlcvideowidget.h b/bindings/phonon/vlc/vlcvideowidget.h
new file mode 100644 (file)
index 0000000..d8e9d21
--- /dev/null
@@ -0,0 +1,65 @@
+/*****************************************************************************
+ * VLC backend for the Phonon library                                        *
+ * Copyright (C) 2007-2008 Tanguy Krotoff <tkrotoff@gmail.com>               *
+ * Copyright (C) 2008 Lukas Durfina <lukas.durfina@gmail.com>                *
+ * Copyright (C) 2009 Fathi Boudra <fabo@kde.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 3 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 package; if not, write to the Free Software       *
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA *
+ *****************************************************************************/
+
+#ifndef PHONON_VLC_VLCVIDEOWIDGET_H
+#define PHONON_VLC_VLCVIDEOWIDGET_H
+
+#include "widgetnopaintevent.h"
+
+#include <QtGui/QWidget>
+
+class QResizeEvent;
+
+namespace Phonon
+{
+namespace VLC {
+
+/**
+ * Widget where to show VLC video.
+ */
+class VLCVideoWidget : public WidgetNoPaintEvent
+{
+    Q_OBJECT
+public:
+
+    VLCVideoWidget(QWidget *p_parent);
+    ~VLCVideoWidget();
+
+    void setVideoSize(const QSize & videoSize);
+    void setAspectRatio(double f_aspect_ratio);
+    void setScaleAndCropMode(bool b_scale_and_crop);
+
+    QSize sizeHint() const;
+
+private:
+
+    void resizeEvent(QResizeEvent *p_event);
+
+    /**
+     * Original size of the video, needed for sizeHint().
+     */
+    QSize videoSize;
+};
+
+}
+} // Namespace Phonon::VLC_MPlayer
+
+#endif // PHONON_VLC_MPLAYER_VLCVIDEOWIDGET_H
diff --git a/bindings/phonon/vlc/widgetnopaintevent.cpp b/bindings/phonon/vlc/widgetnopaintevent.cpp
new file mode 100644 (file)
index 0000000..4f6931e
--- /dev/null
@@ -0,0 +1,63 @@
+/*****************************************************************************
+ * VLC backend for the Phonon library                                        *
+ * Copyright (C) 2007-2008 Tanguy Krotoff <tkrotoff@gmail.com>               *
+ * Copyright (C) 2008 Lukas Durfina <lukas.durfina@gmail.com>                *
+ * Copyright (C) 2009 Fathi Boudra <fabo@kde.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 3 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 package; if not, write to the Free Software       *
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA *
+ *****************************************************************************/
+
+#include "widgetnopaintevent.h"
+
+#include <QtGui/QPainter>
+
+namespace Phonon
+{
+namespace VLC {
+
+WidgetNoPaintEvent::WidgetNoPaintEvent(QWidget *p_parent)
+        : QWidget(p_parent)
+{
+    // When resizing fill with black (backgroundRole color) the rest is done by paintEvent
+    setAttribute(Qt::WA_OpaquePaintEvent);
+
+    // Disable Qt composition management as MPlayer draws onto the widget directly
+    setAttribute(Qt::WA_PaintOnScreen);
+
+    // Indicates that the widget has no background,
+    // i.e. when the widget receives paint events, the background is not automatically repainted.
+    setAttribute(Qt::WA_NoSystemBackground);
+
+    // Required for dvdnav
+    setMouseTracking(true);
+}
+
+void WidgetNoPaintEvent::paintEvent(QPaintEvent *p_event)
+{
+    // FIXME this makes the video flicker
+    // Make everything backgroundRole color
+    QPainter painter(this);
+    painter.eraseRect(rect());
+}
+
+void WidgetNoPaintEvent::setBackgroundColor(const QColor & color)
+{
+    QPalette p = palette();
+    p.setColor(backgroundRole(), color);
+    setPalette(p);
+}
+
+}
+} // Namespace Phonon::VLC
diff --git a/bindings/phonon/vlc/widgetnopaintevent.h b/bindings/phonon/vlc/widgetnopaintevent.h
new file mode 100644 (file)
index 0000000..1e87691
--- /dev/null
@@ -0,0 +1,58 @@
+/*****************************************************************************
+ * VLC backend for the Phonon library                                        *
+ * Copyright (C) 2007-2008 Tanguy Krotoff <tkrotoff@gmail.com>               *
+ * Copyright (C) 2008 Lukas Durfina <lukas.durfina@gmail.com>                *
+ * Copyright (C) 2009 Fathi Boudra <fabo@kde.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 3 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 package; if not, write to the Free Software       *
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA *
+ *****************************************************************************/
+
+#ifndef PHONON_VLC_WIDGETNOPAINTEVENT_H
+#define PHONON_VLC_WIDGETNOPAINTEVENT_H
+
+#include <QtGui/QWidget>
+
+namespace Phonon
+{
+namespace VLC {
+
+/**
+ * Utility class: special widget for playing videos.
+ *
+ * Does not handle paintEvent()
+ */
+class WidgetNoPaintEvent : public QWidget
+{
+    Q_OBJECT
+public:
+
+    WidgetNoPaintEvent(QWidget *p_parent);
+
+    /**
+     * Sets the background color.
+     *
+     * I don't know which one is best: 0x020202 or Qt::black...
+     */
+    void setBackgroundColor(const QColor & color);
+
+private:
+
+    void paintEvent(QPaintEvent *p_event);
+};
+
+}
+} // Namespace Phonon::VLC
+
+#endif // PHONON_VLC_WIDGETNOPAINTEVENT_H