option(BUILD_CHUA_OPCODES "Build the chua opcodes" ON)
option(BUILD_DSSI_OPCODES "Build the DSSI opcodes" ON)
option(BUILD_FLUID_OPCODES "Build the fluidsynth opcodes" ON)
option(BUILD_JACK_OPCODES "Build the JACK related opcodes" ON)
option(BUILD_OSC_OPCODES "Build the OSC Opcodes" ON)
option(BUILD_WIIMOTE_OPCODES "Build the Wiimote opcodes" ON)
option(BUILD_P5GLOVE_OPCODES "Build the P5Glove opcodes" ON)
option(BUILD_SERIAL_OPCODES "Build the serial opcode" ON)
option(BUILD_PLATEREV_OPCODES "Build the platerev opcode" ON)
option(BUILD_VST4CS_OPCODES "Build the vst4cs opcodes" OFF)
option(BUILD_EXCITER_OPCODES "Build the exciter opcode" ON)
option(BUILD_BUCHLA_OPCODES "Build the Buchla filter opcode" ON)
option(BUILD_PADSYNTH_OPCODES "Build the Padsynth opcode" ON)
option(BUILD_SCANSYN_OPCODES "Build the scansyn opcodes" ON)
option(BUILD_SELECT_OPCODE "Build the select opcode" ON)
option(BUILD_STACK_OPCODES "Build the stack opcodes" ON)
option(BUILD_LINEAR_ALGEBRA_OPCODES "Build the linear algebra opcodes" ON)
option(BUILD_PVSGENDY_OPCODE "Build the pvsgendy opcode" OFF)
option(BUILD_MP3OUT_OPCODE "Build the mp3out opcode" ON)
option(BUILD_COUNTER_OPCODES "Build the serial opcode" ON)

message(STATUS "## Building Opcodes ##")
include(CheckIncludeFiles)
check_include_file(ladspa.h LADSPA_H)
find_library(JACK_LIBRARY jack)
find_library(JACKDMP_LIBRARY jackdmp)
check_include_file(jack/jack.h JACK_HEADER)

find_package(FLUIDSYNTH)
find_package(LIBLO)
find_package(ZLIB)
find_package(PNG)

check_include_file(wiiuse.h WIIUSE_H)
find_library(WIIUSE_LIB wiiuse)
check_include_file(p5glove.h P5GLOVE_H)
find_library(P5GLOVE_LIB p5glove)
check_include_file(lame.h LAME_HEADER)
find_library(LAME_LIB mp3lame)

## OPCODE LIBS WITH NO EXTERNAL DEPENDENCIES ##


make_plugin(sterrain sterrain.c)
make_plugin(cs_date date.c)
make_plugin(system_call system_call.c)
make_plugin(doppler doppler.cpp)
make_plugin(fractalnoise tl/fractalnoise.cpp)
make_plugin(ftsamplebank ftsamplebank.cpp)
make_plugin(getftargs getftargs.c)
make_plugin(liveconv liveconv.c)
##make_plugin(zak zak.c)
make_plugin(gtf gammatone.c)
make_plugin(lfsr lfsr.cpp)

make_plugin(fareygen fareygen.c)
make_plugin(quadbezier quadbezier.c)

## Experimental opcode -- JPFF
## make_plugin(mverb MV.c)

if(APPLE)
   make_plugin(arrayops arrayops.cpp)
   make_plugin(pvsops pvsops.cpp)
   make_plugin(trigenvsegs trigEnvSegs.cpp)
elseif(LINUX)
    include(CheckCXXCompilerFlag)
    CHECK_CXX_COMPILER_FLAG("-std=gnu++11" COMPILER_SUPPORTS_CXX11)
     if(COMPILER_SUPPORTS_CXX11)
       make_plugin(arrayops arrayops.cpp)
       set_target_properties(arrayops PROPERTIES COMPILE_FLAGS "-std=gnu++11")
       make_plugin(pvsops pvsops.cpp)
      set_target_properties(pvsops PROPERTIES COMPILE_FLAGS "-std=gnu++11")
       make_plugin(trigenvsegs trigEnvSegs.cpp)
      set_target_properties(trigenvsegs PROPERTIES COMPILE_FLAGS "-std=gnu++11")
     else()
        message(STATUS "Not building array operators as no C++11 support found.")
     endif()
else()
    make_plugin(arrayops arrayops.cpp)
    make_plugin(pvsops pvsops.cpp)
    make_plugin(trigenvsegs trigEnvSegs.cpp)
    if(WIN32 AND NOT MSVC)
      set_target_properties(arrayops PROPERTIES COMPILE_FLAGS
      "-std=gnu++11")
      set_target_properties(pvsops PROPERTIES COMPILE_FLAGS "-std=gnu++11")
      set_target_properties(trigenvsegs PROPERTIES COMPILE_FLAGS "-std=gnu++11")
      endif()
endif()

make_plugin(mixer mixer.cpp)
make_plugin(signalflowgraph signalflowgraph.cpp)
make_plugin(ampmidid ampmidid.cpp)


if(BUILD_PADSYNTH_OPCODES)
if(APPLE)
  make_plugin(padsynth padsynth_gen.cpp)
  set_target_properties(padsynth PROPERTIES COMPILE_FLAGS "-std=gnu++11 -stdlib=libc++"
    LINK_FLAGS "-std=gnu++11 -stdlib=libc++")
elseif(LINUX)
    include(CheckCXXCompilerFlag)
    CHECK_CXX_COMPILER_FLAG("-std=gnu++11" COMPILER_SUPPORTS_CXX11)
    CHECK_CXX_COMPILER_FLAG("-std=gnu++0x" COMPILER_SUPPORTS_CXX0X)
    if(COMPILER_SUPPORTS_CXX11)
        make_plugin(padsynth padsynth_gen.cpp)
        set_target_properties(padsynth PROPERTIES COMPILE_FLAGS "-std=gnu++11")
    elseif(COMPILER_SUPPORTS_CXX0X)
        make_plugin(padsynth padsynth_gen.cpp)
        set_target_properties(padsynth PROPERTIES COMPILE_FLAGS "-std=gnu++0x")
    else()
        message(STATUS "Not building padsynth as no C++11 support found.")
    endif()
else()
    make_plugin(padsynth padsynth_gen.cpp)

    if(WIN32 AND NOT MSVC)
      set_target_properties(padsynth PROPERTIES COMPILE_FLAGS "-std=gnu++11"
        LINK_FLAGS "-std=gnu++11")
    endif()
endif()
endif()


make_plugin(cellular cellular.c)

if(BUILD_COUNTER_OPCODES)
   make_plugin(counter counter.c)
endif()

if(BUILD_SERIAL_OPCODES)
   make_plugin(serial serial.c)
endif()

if(BUILD_PLATEREV_OPCODES)
  make_plugin(platerev platerev.c ${MATH_LIBRARY})
endif()

if(BUILD_SCANSYN_OPCODES)
    set(scansyn_SRCS
        scansyn.c scansynx.c)
    make_plugin(scansyn "${scansyn_SRCS}" ${MATH_LIBRARY})
endif()

if(UNIX)
    make_plugin(control control.c)
    make_plugin(urandom urandom.c)
endif()

if(LINUX)
    make_plugin(joystick linuxjoystick.c)
endif()

## OPCODES WITH EXTERNAL DEPENDENCIES ##

check_deps(BUILD_CHUA_OPCODES EIGEN3_FOUND)
if(BUILD_CHUA_OPCODES)
    make_plugin(chua chua/ChuaOscillator.cpp)
    target_link_libraries(chua PRIVATE Eigen3::Eigen)
 if(APPLE)
   set_target_properties(chua PROPERTIES COMPILE_FLAGS "-Wno-unused-local-typedef")
 endif()
endif()

check_deps(BUILD_DSSI_OPCODES LINUX)
if(BUILD_DSSI_OPCODES)
    set(dssi_SRC dssi4cs/src/load.c dssi4cs/src/dssi4cs.c)
    make_plugin(dssi4cs "${dssi_SRC}" dl)
endif()

if(BUILD_FLUID_OPCODES AND FLUIDSYNTH_FOUND)
    make_plugin(fluidOpcodes fluidOpcodes/fluidOpcodes.cpp)
    target_include_directories(fluidOpcodes PRIVATE ${FLUIDSYNTH_INCLUDE_DIR})
    target_link_libraries(fluidOpcodes ${FLUIDSYNTH_LIBRARIES})
endif()

set(JACK_LIB ${JACK_LIBRARY})
if(NOT JACK_LIB)
  set(JACK_LIB ${JACKDMP_LIBRARY})
endif()

check_deps(BUILD_JACK_OPCODES JACK_HEADER JACK_LIB)
if(BUILD_JACK_OPCODES)
    set(jack_LIBS ${PTHREAD_LIBRARY})
    if(JACKDMP_LIBRARY)
        list(APPEND jack_LIBS ${JACKDMP_LIBRARY})
    else()
        list(APPEND jack_LIBS ${JACK_LIBRARY})
    endif()
    make_plugin(jacko jacko.cpp "${jack_LIBS}")
    set_target_properties(jacko PROPERTIES COMPILE_FLAGS
   "-std=c++11")
    make_plugin(jackTransport jackTransport.c "${jack_LIBS}")
endif()

check_deps(BUILD_LINEAR_ALGEBRA_OPCODES USE_DOUBLE)
if(BUILD_LINEAR_ALGEBRA_OPCODES AND GMM_FOUND)
    make_plugin(linear_algebra linear_algebra.cpp)
    target_include_directories(linear_algebra PRIVATE ${GMM_INCLUDE_DIR})
    if (MSVC)
        target_compile_options(linear_algebra PRIVATE "/D_SCL_SECURE_NO_DEPRECATE")
    endif()
    message(STATUS "Building linear algebra opcodes")
endif()

if(BUILD_OSC_OPCODES AND LIBLO_FOUND)
    make_plugin(osc OSC.c)
    if(WIN32)
      target_link_libraries(osc ${LIBLO_LIBRARIES})
	  # FIXME how to build a static version of this?
      if(BUILD_STATIC_LIBRARY AND NOT MSVC)
        add_library(pthread_static STATIC IMPORTED)
        set_target_properties(pthread_static PROPERTIES IMPORTED_LOCATION ${PTHREAD_LIBRARY})
        target_link_libraries(osc pthread_static)
      elseif(NOT MSVC)
        target_link_libraries(osc ${PTHREAD_LIBRARY})
      endif()
      target_link_libraries(osc wsock32 ws2_32 iphlpapi)
    elseif(HAIKU)
      target_link_libraries(osc ${LIBLO_LIBRARIES})
    else()
      target_link_libraries(osc ${LIBLO_LIBRARIES} pthread)
    endif()
    add_dependency_to_framework(osc ${LIBLO_LIBRARIES})
endif()

check_deps(BUILD_WIIMOTE_OPCODES WIIUSE_H WIIUSE_LIB)
if(BUILD_WIIMOTE_OPCODES)
    make_plugin(wiimote wiimote.c ${WIIUSE_LIB})
    add_dependency_to_framework(wiimote ${WIIUSE_LIB})

endif()

if(BUILD_EXCITER_OPCODES)
    make_plugin(exciter exciter.c)
endif()

if(BUILD_BUCHLA_OPCODES)
    make_plugin(buchla buchla.c)
endif()

check_deps(BUILD_P5GLOVE_OPCODES P5GLOVE_H)
if(BUILD_P5GLOVE_OPCODES)
    make_plugin(p5g p5glove.c ${P5GLOVE_LIB})
endif()

if(BUILD_SELECT_OPCODE)
    make_plugin(select select.c)
endif()

if(BUILD_STACK_OPCODES)
    make_plugin(stackops stackops.c)
endif()

if(BUILD_PVSGENDY_OPCODES)
    make_plugin(pvsgendy pvsgendy.c)
endif()

check_deps(BUILD_MP3OUT_OPCODE LAME_HEADER)
if(BUILD_MP3OUT_OPCODE)
    make_plugin(mp3out lame.c ${LAME_LIB})
endif()


# OGG Opcode previously was built only for OLPC
#if(VORBISFILE_LIBRARY)
#    set(vorbis_LIBS ${libcsound_LIBS} ${VORBISFILE_LIBRARY})
#    make_plugin(ogg ogg.c "${vorbis_LIBS}")
#endif()


#if(APPLE)
#foreach(TARG ampmidid doppler mixer signalflowgraph arrayops pvsops
#ftsamplebank padsynth)
#set_target_properties(${TARG} PROPERTIES COMPILE_FLAGS "-std=c++11
#-stdlib=libc++"
#   LINK_FLAGS "-std=c++11 -stdlib=libc++")
#endforeach(TARG)
#endif()

add_subdirectory(stk)
add_subdirectory(cuda)
add_subdirectory(opencl)
add_subdirectory(hdf5)
add_subdirectory(websockets)
add_subdirectory(framebuffer)
add_subdirectory(emugens)
