cmake_minimum_required(VERSION 3.6)
project(vgmstream NONE)

if(CMAKE_SYSTEM_NAME MATCHES Darwin)
    if ( (NOT DEFINED CMAKE_C_COMPILER) AND (NOT DEFINED ENV{CC}) AND (EXISTS /usr/bin/cc))
        set(CMAKE_C_COMPILER /usr/bin/cc)
    endif()
    if ( (NOT DEFINED CMAKE_CXX_COMPILER) AND (NOT DEFINED ENV{CXX}) AND (EXISTS /usr/bin/c++))
        set(CMAKE_CXX_COMPILER /usr/bin/c++)
    endif()
endif()

enable_language(C)
enable_language(CXX)

# TODO defautl out-of-source-builds not working properly?
# (like "cmake .." from ./build subdir creates makefiles on ./, unless using "cmake -S ..")
get_directory_property(hasParent PARENT_DIRECTORY)
if(hasParent)
  set(VGM_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR} PARENT_SCOPE)
  set(VGM_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR} PARENT_SCOPE)
endif()
set(VGM_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
set(VGM_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
set(CMAKE_MODULE_PATH ${VGM_SOURCE_DIR}/cmake;${CMAKE_MODULE_PATH})
include(vgmstream)

# Defaults for Windows, otherwise may be Program Files/vgmstream
if(WIN32)
  IF(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
    SET(CMAKE_INSTALL_PREFIX ${VGM_SOURCE_DIR} CACHE PATH "..." FORCE)
  ENDIF(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
endif()

function(set_mpeg onoff useForce)
  if(useForce)
    set(USE_FORCE_ FORCE)
  endif()
  set(USE_MPEG ${onoff} CACHE BOOL "Use libmpg123 for support of MPEG (MP1/MP2/MP3)" ${USE_FORCE_})
endfunction()

function(set_vorbis onoff useForce)
  if(useForce)
    set(USE_FORCE_ FORCE)
  endif()
  set(USE_VORBIS ${onoff} CACHE BOOL "Use libvorbis for support of Vorbis" ${USE_FORCE_})
endfunction()

function(set_ffmpeg onoff useForce)
  if(useForce)
    set(USE_FORCE_ FORCE)
  endif()
  set(USE_FFMPEG ${onoff} CACHE BOOL "Use FFmpeg for support of many codecs" ${USE_FORCE_})
endfunction()

# Options
set_mpeg(ON FALSE)
set_vorbis(ON FALSE)
set_ffmpeg(ON FALSE)

option(USE_G7221 "Use G7221 for support of ITU-T G.722.1 annex C" ON)
option(USE_G719 "Use libg719_decode for support ITU-T G.719" ON)
option(USE_ATRAC9 "Use LibAtrac9 for support of ATRAC9" ON)
option(USE_CELT "Use libcelt for support of FSB CELT versions 0.6.1 and 0.11.0" ON)
option(USE_SPEEX "Use libspeex for support of SPEEX" ON)

if(NOT WIN32)
	set(MPEG_PATH CACHE PATH "Path to mpg123")
	set(OGG_PATH CACHE PATH "Path to Ogg")
	set(VORBIS_PATH CACHE PATH "Path to Vorbis")
	set(FFMPEG_PATH CACHE PATH "Path to FFmpeg")
	set(G719_PATH CACHE PATH "Path to G.719 decoder")
	set(ATRAC9_PATH CACHE PATH "Path to LibAtrac9")
	set(SPEEX_PATH CACHE PATH "Path to SPEEX")
	set(CELT_0061_PATH CACHE PATH "Path to CELT version 0.6.1")
	set(CELT_0110_PATH CACHE PATH "Path to CELT version 0.11.0")
	set(LIBAO_PATH CACHE PATH "Path to libao")
endif()

# Build choices
option(BUILD_CLI "Build vgmstream CLI" ON)
if(WIN32)
	if(MSVC)
		option(BUILD_FB2K "Build foobar2000 component" ON)
		set(FB2K_SDK_PATH CACHE PATH "Path to foobar2000 SDK")
		set(WTL_INCLUDE_PATH CACHE PATH "Path to WTL include directory")
		set(FB2K_COMPONENT_INSTALL_PREFIX CACHE PATH "Path to foobar2000 component installation directory")
	endif()
	option(BUILD_WINAMP "Build Winamp plugin" ON)
	set(WINAMP_INSTALL_PREFIX CACHE PATH "Path to Winamp installation directory")
	option(BUILD_XMPLAY "Build XMPlay plugin" ON)
	set(XMPLAY_INSTALL_PREFIX CACHE PATH "Path to XMPlay installation directory")
else()
	if(EMSCRIPTEN)
		set(BUILD_STATIC ON)
	else()
		option(BUILD_STATIC "Build statically linked binary" OFF)
		if(BUILD_STATIC)
			option(BUILD_V123 "Build vgmstream123 player" OFF)
		else()
			option(BUILD_V123 "Build vgmstream123 player" ON)
		endif()
		option(BUILD_AUDACIOUS "Build Audacious plugin" ON)
	endif()
endif()

if(EMSCRIPTEN)
	set(BUILD_V123 OFF)
	set(BUILD_AUDACIOUS OFF)
	
	set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lworkerfs.js -s CASE_INSENSITIVE_FS -s ALLOW_MEMORY_GROWTH")
endif()

# Static builds will link all libraries statically
if(BUILD_STATIC)
	set(BUILD_SHARED_LIBS OFF)
	set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libgcc -static-libstdc++ -static")
	
	# Incompatible with static builds
	set(BUILD_AUDACIOUS OFF)
endif()

# Autodetect some paths
if(MSVC AND NOT FB2K_SDK_PATH AND IS_DIRECTORY "${VGM_SOURCE_DIR}/dependencies/foobar/")
    set(FB2K_SDK_PATH "${VGM_SOURCE_DIR}/dependencies/foobar/"  CACHE PATH "..." FORCE)
endif()
if(MSVC AND NOT WTL_INCLUDE_PATH AND IS_DIRECTORY "${VGM_SOURCE_DIR}/dependencies/wtl/")
    set(WTL_INCLUDE_PATH "${VGM_SOURCE_DIR}/dependencies/wtl/"  CACHE PATH "..." FORCE)
endif()

# Set autogenerated version
if(MSVC)
	set(VGM_VERSION_GENERATOR version-make.bat)
	add_custom_command(OUTPUT ${VGM_SOURCE_DIR}/version_auto.h
		COMMAND "${VGM_SOURCE_DIR}/${VGM_VERSION_GENERATOR}"
		DEPENDS ${VGM_SOURCE_DIR}/${VGM_VERSION_GENERATOR})
else()
	# linux uses 'sh' so git-less (src zip) builds can run without chmod -x (script)
	set(VGM_VERSION_GENERATOR version-make.sh)
	add_custom_command(OUTPUT ${VGM_SOURCE_DIR}/version_auto.h
		COMMAND sh "${VGM_SOURCE_DIR}/${VGM_VERSION_GENERATOR}"
		DEPENDS ${VGM_SOURCE_DIR}/${VGM_VERSION_GENERATOR})
endif()
add_custom_target(version_h ALL DEPENDS ${VGM_SOURCE_DIR}/version_auto.h)

include(FetchDependency)

include(dependencies/ffmpeg)
include(dependencies/mpg123)
include(dependencies/ogg)
include(dependencies/vorbis)
include(dependencies/libao)
include(dependencies/g719)
include(dependencies/atrac9)
include(dependencies/celt)
include(dependencies/speex)
include(dependencies/audacious)

if(USE_G7221)
	set(G7221_SOURCE "(built-in)")
else()
	unset(G7221_SOURCE)
endif()

if(WIN32)
	# Enable support for the resource compiler when using MinGW
	if(MINGW)
		enable_language(RC)
		# Not 100% sure this is needed, but in the past, MinGW's command for compiling resources was incorrect
		set(CMAKE_RC_COMPILE_OBJECT "<CMAKE_RC_COMPILER> <FLAGS> -O coff <DEFINES> -i <SOURCE> -o <OBJECT>")
	endif(MINGW)

	set(CMAKE_EXECUTABLE_SUFFIX .exe)
endif()

# Set compiler flags
if(CMAKE_CXX_COMPILER_ID MATCHES Clang OR CMAKE_CXX_COMPILER_ID MATCHES GNU)
	set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
	set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
	if(CMAKE_CXX_COMPILER_ID MATCHES Clang)
		set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-parentheses-equality -Wno-header-guard -Wno-unused-function -Wno-shift-negative-value -Wno-deprecated-register")
		set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-parentheses-equality -Wno-header-guard -Wno-unused-function -Wno-shift-negative-value -Wno-deprecated-register")
	elseif()
		if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 5.9)
			set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-misleading-indentation")
			set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-misleading-indentation")
		endif()
		if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.0)
			set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-attributes")
			set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-attributes")
		endif()
		if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 2.99)
			set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-function")
			set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-function")
		endif()
		set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-format -Wno-sign-compare")
		set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-format -Wno-sign-compare")
	endif()
elseif(MSVC)
	if(CMAKE_C_FLAGS MATCHES "/W[0-4]")
		string(REGEX REPLACE "/W[0-4]" "/W3" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
	else()
		set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W3")
	endif()
	if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
		string(REGEX REPLACE "/W[0-4]" "/W3" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
	else()
		set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W3")
	endif()
	set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /wd4005 /wd4018 /wd4244 /wd4302 /wd4838")
	set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4005 /wd4018 /wd4244 /wd4302 /wd4838")
endif()

add_subdirectory(src)
if(WIN32)
	add_subdirectory(ext_libs)
	if(BUILD_WINAMP)
		if(NOT WINAMP_INSTALL_PREFIX)
			set(WINAMP_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX}/winamp)
		endif()
		add_subdirectory(winamp)
	endif()
	if(BUILD_FB2K)
		if(NOT FB2K_SDK_PATH)
			message(FATAL_ERROR "The path to the foobar2000 SDK must be set. (Use FB2K_SDK_PATH)")
		endif()
		if(NOT WTL_INCLUDE_PATH)
			message(FATAL_ERROR "The path to the WTL include directory must be set. (Use WTL_INCLUDE_PATH)")
		endif()
		if(NOT FB2K_COMPONENT_INSTALL_PREFIX)
			set(FB2K_COMPONENT_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX}/fb2k)
		endif()
		include_external_msproject(fb2k_sdk ${FB2K_SDK_PATH}/foobar2000/SDK/foobar2000_SDK.vcxproj)
		include_external_msproject(fb2k_sdk_helpers ${FB2K_SDK_PATH}/foobar2000/helpers/foobar2000_sdk_helpers.vcxproj)
		include_external_msproject(fb2k_atl_helpers ${FB2K_SDK_PATH}/foobar2000/ATLHelpers/foobar2000_ATL_helpers.vcxproj)
		include_external_msproject(fb2k_component_client ${FB2K_SDK_PATH}/foobar2000/foobar2000_component_client/foobar2000_component_client.vcxproj)
		include_external_msproject(pfc ${FB2K_SDK_PATH}/pfc/pfc.vcxproj)
		add_subdirectory(fb2k)
	endif()
	if(BUILD_XMPLAY)
		if(NOT XMPLAY_INSTALL_PREFIX)
			set(XMPLAY_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX}/xmplay)
		endif()
		add_subdirectory(xmplay)
	endif()
else()
	if(BUILD_AUDACIOUS)
		add_subdirectory(audacious)
	endif()
endif()
if(BUILD_CLI)
	if(WIN32)
		add_subdirectory(ext_libs/Getopt)
	endif()
	add_subdirectory(cli)
endif()

# Option Summary
message(STATUS " Option Summary")
message(STATUS "=================")
message(STATUS "        MPEG: ${USE_MPEG} ${MPEG_SOURCE}")
message(STATUS "      Vorbis: ${USE_VORBIS} ${VORBIS_SOURCE}")
message(STATUS "      FFmpeg: ${USE_FFMPEG} ${FFMPEG_SOURCE}")
message(STATUS "     G.722.1: ${USE_G7221} ${G7221_SOURCE}")
message(STATUS "       G.719: ${USE_G719} ${G719_SOURCE}")
message(STATUS "      ATRAC9: ${USE_ATRAC9} ${ATRAC9_SOURCE}")
message(STATUS "    FSB CELT: ${USE_CELT} ${CELT_SOURCE}")
message(STATUS "       SPEEX: ${USE_SPEEX} ${SPEEX_SOURCE}")
if(NOT WIN32)
	message(STATUS "       LIBAO: ${BUILD_V123} ${LIBAO_SOURCE}")
endif()
message(STATUS "")

# Build Summary
message(STATUS "        Building")
message(STATUS "=========================")
if(WIN32)
	message(STATUS "                 CLI: ${BUILD_CLI}")
	message(STATUS "foobar2000 component: ${BUILD_FB2K}")
	message(STATUS "       Winamp plugin: ${BUILD_WINAMP}")
	message(STATUS "       XMPlay plugin: ${BUILD_XMPLAY}")
else()
	message(STATUS "             CLI: ${BUILD_CLI}")
	message(STATUS "    vgmstream123: ${BUILD_V123}")
	message(STATUS "Audacious plugin: ${BUILD_AUDACIOUS} ${AUDACIOUS_SOURCE}")
	message(STATUS "  Static linking: ${BUILD_STATIC}")
endif()
message(STATUS "")

# Install Summary
message(STATUS "      Install Paths")
message(STATUS "=========================")
if(WIN32)
	if(BUILD_CLI)
		message(STATUS "                 CLI: ${CMAKE_INSTALL_PREFIX}/bin")
	endif()
	if(BUILD_FB2K)
		message(STATUS "foobar2000 component: ${FB2K_COMPONENT_INSTALL_PREFIX}")
	endif()
	if(BUILD_WINAMP)
		message(STATUS "       Winamp plugin: ${WINAMP_INSTALL_PREFIX}")
	endif()
	if(BUILD_XMPLAY)
		message(STATUS "       XMPlay plugin: ${XMPLAY_INSTALL_PREFIX}")
	endif()
else()
	if(BUILD_CLI)
		message(STATUS "CLI/vgmstream123: ${CMAKE_INSTALL_PREFIX}/bin")
	endif()
	if(BUILD_AUDACIOUS)
		message(STATUS "Audacious plugin: ${AUDACIOUS_PLUGIN_DIR}/Input")
	endif()
endif()
message(STATUS "")