# REAL TIME AUDIO AND MIDI

message(STATUS "")
message(STATUS "## REALTIME AUDIO AND MIDI ##")

option(USE_PULSEAUDIO "Build the PulseAudio I/O module" ON)
option(USE_PORTAUDIO "Build the PortAudio I/O module" ON)
option(USE_PORTMIDI "Build the PortMIDI I/O module" ON)
option(USE_IPMIDI "Build the IPMIDI I/O module" ON)
option(USE_JACK "Build the jack I/O module and opcodes" ON)
option(USE_ALSA "Build the ALSA I/O module" ON)
# option(USE_COREAUDIO "Build the CoreAudio I/O module" ON)
option(USE_COREMIDI "Build the CoreMIDI I/O Module" ON)
option(USE_AUDIOUNIT "Build the CoreAudio AudioUnit I/O module (requires CoreAudio)" ON)
option(USE_FLTK "Use FLTK for graphs and widget opcodes" ON)
option(BUILD_VIRTUAL_KEYBOARD "Build Virtual MIDI keyboard" ON)
option(NEED_PORTTIME "porttime library separate from portmidi" ON)

set(CMAKE_REQUIRED_INCLUDES /usr/local/include)

# FIND LIBRARIES AND HEADERS

if(USE_ALSA)
    find_library(ALSA_LIBRARY asound)
    check_include_file(alsa/asoundlib.h ALSA_HEADER)
endif()
if(USE_PORTAUDIO)
    find_path(PORTAUDIO_INCLUDE_PATH portaudio.h)
    find_library(PORTAUDIO_LIBRARY NAMES portaudio portaudio_x64)

    if(PORTAUDIO_INCLUDE_PATH AND PORTAUDIO_LIBRARY)
        try_run(PORTAUDIO_V19 PORTAUDIO_TEST_COMPILED
            ${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/../cmake/portaudio_test.c
            CMAKE_FLAGS -DLINK_LIBRARIES:STRING=${PORTAUDIO_LIBRARY}
            COMPILE_DEFINITIONS "-I${PORTAUDIO_INCLUDE_PATH}"
            COMPILE_OUTPUT_VARIABLE OUTPUT)
        if(NOT PORTAUDIO_TEST_COMPILED AND NOT WIN32)
            set(PORTAUDIO_V19 false)
        endif()
    else()
        set(PORTAUDIO_V19 false)
    endif()
endif()
if(USE_PORTMIDI)
    find_path(PORTMIDI_INCLUDE_PATH portmidi.h)
    find_library(PORTMIDI_LIBRARY portmidi)
    if(NOT WIN32)
        if(NEED_PORTTIME)
            find_library(PORTTIME_LIBRARY porttime)
        endif()
    endif()
endif()
if(USE_JACK)
    find_library(JACK_LIBRARY jack)
    find_library(JACKDMP_LIBRARY jackdmp)
    check_include_file(jack/jack.h JACK_HEADER)
endif()
if(USE_PULSEAUDIO)
    find_library(PULSEAUDIO_LIBRARY pulse)
    find_library(PULSESIMPLE_LIBRARY pulse-simple)
    check_include_file(pulse/simple.h PULSEAUDIO_HEADER)
endif()
# if(USE_COREAUDIO)
#    find_path(COREAUDIO_INCLUDE_PATH CoreAudio.h)
#    find_library(COREAUDIO_LIBRARY CoreAudio)
# endif()
if(USE_COREMIDI)
    find_path(COREMIDI_INCLUDE_PATH CoreMidi.h)
    find_library(COREMIDI_LIBRARY CoreMidi)
    find_library(COREFOUNDATION_LIBRARY CoreFoundation)
endif()
if(USE_AUDIOUNIT)
    find_path(AUDIOUNIT_INCLUDE_PATH AudioUnit.h)
    find_library(AUDIOUNIT_LIBRARY AudioUnit)
    find_library(COREFOUNDATION_LIBRARY CoreFoundation)
    find_path(COREAUDIO_INCLUDE_PATH CoreAudio.h)
    find_library(COREAUDIO_LIBRARY CoreAudio)
endif()

# BUILD TARGETS

# check_deps(USE_COREAUDIO APPLE COREAUDIO_INCLUDE_PATH COREAUDIO_LIBRARY)
# if(USE_COREAUDIO)
#    make_plugin(rtcoreaudio rtcoreaudio.c)
#    target_include_directories(rtcoreaudio PRIVATE ${COREAUDIO_INCLUDE_PATH})
#    target_link_libraries(rtcoreaudio ${COREAUDIO_LIBRARY})
# endif()

check_deps(USE_COREMIDI APPLE COREMIDI_INCLUDE_PATH COREMIDI_LIBRARY COREFOUNDATION_LIBRARY)
if(USE_COREMIDI)
    make_plugin(cmidi cmidi.c)
    target_include_directories(cmidi PRIVATE ${COREMIDI_INCLUDE_PATH})
    target_link_libraries(cmidi ${COREMIDI_LIBRARY} ${COREFOUNDATION_LIBRARY})
endif()

check_deps(USE_AUDIOUNIT APPLE COREAUDIO_INCLUDE_PATH COREAUDIO_LIBRARY AUDIOUNIT_INCLUDE_PATH AUDIOUNIT_LIBRARY COREFOUNDATION_LIBRARY)
if(USE_AUDIOUNIT)
    make_plugin(rtauhal rtauhal.c)
    target_include_directories(rtauhal PRIVATE ${AUDIOUNIT_INCLUDE_PATH})
    target_link_libraries(rtauhal ${AUDIOUNIT_LIBRARY} ${COREFOUNDATION_LIBRARY} ${COREAUDIO_LIBRARY})
endif()

check_deps(USE_ALSA ALSA_HEADER ALSA_LIBRARY PTHREAD_LIBRARY)
if(USE_ALSA)
    set(rtalsa_LIBS
        ${ALSA_LIBRARY} ${PTHREAD_LIBRARY} m)
    make_plugin(rtalsa rtalsa.c ${rtalsa_LIBS})
endif()

if(WIN32)
    message(STATUS "Building Windows MME plugin(rtwinmm).")
    if(MSVC)
      make_plugin(rtwinmm rtwinmm.c)
      target_link_libraries(rtwinmm winmm.lib)
      target_link_libraries(rtwinmm gdi32)
      target_link_libraries(rtwinmm kernel32)
    else()
      set(rtwinmm_LIBS
          winmm gdi32 kernel32) # should probably do checks for these libs
      make_plugin(rtwinmm rtwinmm.c "${rtwinmm_LIBS}")
    endif()
endif()


check_deps(USE_PULSEAUDIO PULSEAUDIO_HEADER PULSEAUDIO_LIBRARY PULSESIMPLE_LIBRARY)
if(USE_PULSEAUDIO)
    make_plugin(rtpulse rtpulse.c ${PULSEAUDIO_LIBRARY} ${PULSESIMPLE_LIBRARY})
endif()

if(WIN32)
    check_deps(USE_PORTAUDIO PORTAUDIO_INCLUDE_PATH PORTAUDIO_LIBRARY)
else()
    check_deps(USE_PORTAUDIO PORTAUDIO_INCLUDE_PATH PORTAUDIO_LIBRARY PORTAUDIO_TEST_COMPILED)
endif()
if(USE_PORTAUDIO AND PORTAUDIO_V19 MATCHES 1)
    message(STATUS "Building rtpa module.")
    make_plugin(rtpa rtpa.c)
    target_include_directories(rtpa PRIVATE ${PORTAUDIO_INCLUDE_PATH})
    if(BUILD_STATIC_LIBRARY)
        if(WIN32)
            set_source_files_properties(rtpa.c PROPERTIES LANGUAGE CXX)
            target_link_libraries(rtpa winmm dsound setupapi ${PORTAUDIO_LIBRARY} ${CSOUND_WINDOWS_LIBRARIES})
        else()
            target_link_libraries(rtpa ${PORTAUDIO_LIBRARY})
        endif()
    else()
        if(MSVC)
            set_source_files_properties(rtpa.c PROPERTIES LANGUAGE CXX)
            target_link_libraries(rtpa winmm dsound setupapi ${PORTAUDIO_LIBRARY} ${CSOUND_WINDOWS_LIBRARIES})
        else()
            target_link_libraries(rtpa ${PORTAUDIO_LIBRARY})
        endif()
    endif()
else()
  message(STATUS "Not building Portaudio Driver...")
  message(STATUS "Portaudio v19 Found: ${PORTAUDIO_V19}.")
endif()

if(APPLE)
    check_deps(USE_PORTMIDI PORTMIDI_INCLUDE_PATH PORTMIDI_LIBRARY)
elseif(WIN32)
  if(MSVC)
    check_deps(USE_PORTMIDI PORTMIDI_INCLUDE_PATH PORTMIDI_LIBRARY)
  else()
    if(NEED_PORTTIME)
      check_deps(USE_PORTMIDI PORTMIDI_INCLUDE_PATH PORTTIME_INCLUDE_PATH PORTMIDI_LIBRARY)
    else()
      check_deps(USE_PORTMIDI PORTMIDI_INCLUDE_PATH PORTMIDI_LIBRARY)
    endif()
  endif()
elseif(NEED_PORTTIME)
    check_deps(USE_PORTMIDI PORTMIDI_INCLUDE_PATH PORTMIDI_LIBRARY PORTTIME_LIBRARY)
else()
    check_deps(USE_PORTMIDI PORTMIDI_INCLUDE_PATH PORTMIDI_LIBRARY)
endif()

if(USE_PORTMIDI)
    make_plugin(pmidi pmidi.c)
    target_include_directories(pmidi PRIVATE ${PORTMIDI_INCLUDE_PATH})
    target_link_libraries(pmidi ${PORTMIDI_LIBRARY})
    if(LINUX)
      if(NEED_PORTTIME)
        target_include_directories(pmidi PRIVATE ${PORTTIME_INCLUDE_PATH})
        target_link_libraries(pmidi ${PORTTIME_LIBRARY})
      endif()
    elseif(WIN32)
      if(NEED_PORTTIME)
          target_include_directories(pmidi PRIVATE ${PORTTIME_INCLUDE_PATH})
      endif()
      target_link_libraries(pmidi ${CSOUND_WINDOWS_LIBRARIES})
    elseif(LINUX AND ALSA_LIBRARY)
      target_link_libraries(pmidi ${ALSA_LIBRARY})
    endif()

    add_dependency_to_framework(pmidi ${PORTMIDI_LIBRARY})
endif()

#check_deps(USE_IPMIDI PORTMIDI_HEADER PORTMIDI_LIBRARY)
if(USE_IPMIDI)
    if(WIN32)
      set(ipmidi_LIBS ws2_32)
    endif()
    make_plugin(ipmidi ipmidi.c "${ipmidi_LIBS}")
endif()

check_deps(USE_JACK JACK_HEADER JACK_LIBRARY)
if(USE_JACK)
    set(rtjack_LIBS "")
    if(LINUX)
        list(APPEND rtjack_LIBS
            ${JACK_LIBRARY} ${PTHREAD_LIBRARY})
    elseif(WIN32)
        list(APPEND rtjack_LIBS
            ${JACKDMP_LIBRARY} ${PTHREAD_LIBRARY})
    else()
        list(APPEND rtjack_LIBS
            ${JACK_LIBRARY} ${PTHREAD_LIBRARY})
    endif()
    make_plugin(rtjack rtjack.c "${rtjack_LIBS}")
endif()

check_deps(USE_FLTK FLTK_FOUND)
if(USE_FLTK)
    set(widgets_SRCS FL_graph.cpp winFLTK.c widgets.cpp)
    make_plugin(widgets "${widgets_SRCS}" "${FLTK_LIBRARIES}")
    if(NOT MSVC)
        target_link_libraries(widgets ${FLTK_BASE_LIBRARY})
        target_link_libraries(widgets ${FLTK_FORMS_LIBRARY})
        target_link_libraries(widgets ${FLTK_IMAGES_LIBRARY})
    else()
        target_link_libraries(widgets ${FLTK_LIBRARIES})
    endif()
    target_include_directories(widgets PRIVATE ${FLTK_INCLUDE_DIR})
    #add_dependency_to_framework(widgets ${FLTK_BASE_LIBRARY})
    #add_dependency_to_framework(widgets ${FLTK_FORMS_LIBRARY})
    #add_dependency_to_framework(widgets ${FLTK_IMAGES_LIBRARY})
endif()

check_deps(BUILD_VIRTUAL_KEYBOARD FLTK_FOUND)
if(BUILD_VIRTUAL_KEYBOARD)
    set(virtual_SRCS virtual_keyboard/FLTKKeyboard.cpp
        virtual_keyboard/FLTKKeyboardWindow.cpp
        virtual_keyboard/FLTKKeyboardWidget.cpp
        virtual_keyboard/virtual_keyboard.cpp
        virtual_keyboard/Bank.cpp
        virtual_keyboard/KeyboardMapping.cpp
        virtual_keyboard/Program.cpp
        virtual_keyboard/SliderBank.cpp
        virtual_keyboard/SliderData.cpp)
    make_plugin(virtual "${virtual_SRCS}" "${FLTK_LIBRARIES}")
    if (NOT MSVC)
        target_link_libraries(virtual ${FLTK_BASE_LIBRARY})
        target_link_libraries(virtual ${FLTK_FORMS_LIBRARY})
        target_link_libraries(virtual ${FLTK_IMAGES_LIBRARY})
    else()
        target_link_libraries(virtual ${FLTK_LIBRARIES})
    endif()
    #add_dependency_to_framework(virtual ${FLTK_BASE_LIBRARY})
    #add_dependency_to_framework(virtual ${FLTK_FORMS_LIBRARY})
    #add_dependency_to_framework(virtual ${FLTK_IMAGES_LIBRARY})
    target_include_directories(virtual PRIVATE ".")
    target_include_directories(virtual PRIVATE ${FLTK_INCLUDE_DIR})
endif()

message(STATUS "")
