# encoding: utf-8
#
# WAF build scripts for XMMS2
# Copyright (C) 2006-2023 XMMS2 Team
#

import os
from waflib import Options, Logs, Errors, Utils

source = """
    config.c
    mediainfo.c
    medialib.c
    medialib_query.c
    medialib_query_result.c
    medialib_session.c
    metadata.c
    fetchspec.c
    fetchinfo.c
    object.c
    error.c
    output.c
    playlist.c
    playlist_updater.c
    collection.c
    collsync.c
    ipc.c
    log.c
    plugin.c
    magic.c
    ringbuf.c
    xform.c
    xform_object.c
    xform_plugin.c
    streamtype.c
    converter_plugin.c
    cutter_plugins.c
    ringbuf_xform.c
    outputplugin.c
    bindata.c
    sample.c
    converter.genpy
    utils.c
    courier.c
    visualization/format.c
    visualization/object.c
    visualization/udp.c
    visualization/xform.c
""".split()

ipc_object_files = """
    bindata
    collection
    collsync
    config
    main
    mediainfo
    medialib
    output
    playlist
    visualization/object
    xform
    courier
    ipc_manager
""".split()

def build(bld):
    for ipc_object_file in ipc_object_files:
        python_script = ipc_object_file + '_ipc.py'
        c_file = ipc_object_file + '_ipc.c'

        bld(source=['../ipc.xml', python_script],
            target=c_file,
            rule='${PYTHON} ${SRC[1].abspath()} > ${TGT}',
            before='c'
        )

    compat = [
        "compat/localtime_%s.c" % bld.env.localtime_impl,
        "compat/statfs_%s.c" % bld.env.statfs_impl,
        "compat/signal_%s.c" % bld.env.compat_impl,
        "compat/symlink_%s.c" % bld.env.compat_impl,
        "compat/checkroot_%s.c" % bld.env.compat_impl,
        "visualization/%s.c" % bld.env.visualization_impl
    ]

    builtin_env = bld.env.derive()
    builtin_env.GENPY_ARGS = ' '.join(bld.env.XMMS_PLUGINS_BUILTIN)
    bld(features = 'c',
        target = 'xmms_builtin_plugins',
        source = 'builtin_plugins.genpy',
        includes = '. ../.. ../include ../includepriv',
        uselib = 'glib2',
        use = ' '.join(['xmms_' + x for x in bld.env.XMMS_PLUGINS_BUILTIN]),
        env = builtin_env
    )

    bld(features='c visibilityhidden ' + (bld.env.xmms_shared_library and 'cshlib' or ''),
        target = 'xmms2core',
        source = source + compat,
        includes = '. ../.. ../include ../includepriv',
        uselib = 'glib2 gmodule2 math s4 shm socket statfs valgrind',
        use = 'xmmsipc xmmssocket xmmsutils xmmstypes xmmsvisualization s4 xmmsc-glib xmms_builtin_plugins',
        defines = 'G_LOG_DOMAIN="core"'
    )

    objects = []
    if bld.env.xmms_icon:
        objects += ['xmms_icon']

    bld(features = 'c cprogram visibilityhidden',
        target = 'xmms2d',
        source = 'main.c',
        includes = '. ../.. ../include ../includepriv',
        use = ['xmms2core'] + objects,
        defines = 'G_LOG_DOMAIN=""'
    )

    bld(features = 'man',
        source = 'xmms2d.1'
    )


## Code fragments for configuration
statfs_fragment = """
#include <sys/param.h>
#include <sys/mount.h>
int main() {
    struct statfs foo;
    return 0;
}
"""
prctl_fragment = """
#include <sys/prctl.h>
int main() {
  return prctl(PR_SET_NAME, (unsigned long) "test", 0, 0, 0);
}
"""
semun_fragment = """
#include <time.h>
#include <sys/sem.h>
int main() {
  union semun foo;
  return 0;
}
"""

def get_statfs_impl(conf):
    # Detect the type of stat call used
    if Utils.unversioned_sys_platform() == 'win32':
        return 'dummy'
    else:
        try:
            conf.check(header_name='sys/vfs.h')
        except Errors.ConfigurationError:
            try:
                conf.check(header_name='sys/param.h')
            except Errors.ConfigurationError:
                return 'dummy'
            else:
                try:
                    conf.check_cc(fragment=statfs_fragment,
                                  uselib_store="statfs",
                                  msg="Checking for struct statfs")
                except Errors.ConfigurationError:
                    return 'netbsd'
                else:
                    return 'bsd'
        else:
            if Utils.unversioned_sys_platform() == 'sunos':
                return 'solaris'
            else:
                return 'linux'

# Get the implementation variant for the localtime_r function.
def get_localtime_impl(conf):
    try:
        localtime_r_fragment = """
        #include <time.h>
        int main(void) {
            return localtime_r(0, 0) != 0;
        }
        """
        conf.check_cc(fragment=localtime_r_fragment, header_name='time.h')
    except Errors.ConfigurationError:
        return 'dummy'
    else:
        return 'unix'

# Get the implementation variant for signals, symlinks and uid check.
def get_compat_impl(conf):
    if Utils.unversioned_sys_platform() == 'win32':
        return 'dummy'
    else:
        return 'unix'

def get_visualization_impl(conf):
    if conf.options.without_unixshmserver:
        return 'dummy'

    try:
        semctl_fragment = """
        #include <sys/sem.h>
        int main(void) {
            return semctl(0,0,0,0);
        }
        """
        conf.check_cc(fragment=semctl_fragment,
                      header_name=['sys/types.h','sys/ipc.h','sys/sem.h'])
    except:
        have_semctl = False
    else:
        have_semctl = True

    try:
        conf.check_cc(fragment=semun_fragment, uselib_store="semun",
                      msg = "Checking for union semun")
    except Errors.ConfigurationError:
        conf.env.append_value('DEFINES_shm', "_SEM_SEMUN_UNDEFINED")

    if have_semctl:
        return 'unixshm'
    else:
        return 'dummy'

def configure(conf):
    conf.check_cfg(package='gmodule-2.0', atleast_version='2.32.0',
            uselib_store='gmodule2', args='--cflags --libs')

    # Check for the sin function in the math lib
    sin_fragment = """
    #include <math.h>
    int main(void) {
        return sin(0.5);
    }
    """
    conf.check_cc(lib='m', fragment=sin_fragment, header_name='math.h',
                  uselib_store="math")

    conf.env.compat_impl = get_compat_impl(conf)
    conf.env.statfs_impl = get_statfs_impl(conf)
    conf.env.localtime_impl = get_localtime_impl(conf)
    conf.env.visualization_impl = get_visualization_impl(conf)

    if conf.env.visualization_impl == 'dummy':
        Logs.warn("Compiling visualization without shm support")

    # Add Darwin stuff
    if Utils.unversioned_sys_platform() == 'darwin':
        conf.env.append_value('LINKFLAGS', ['-framework', 'CoreFoundation'])
        conf.env.append_value('DEFINES', 'USE_BUNDLES')

    conf.env.xmms_shared_library = (Utils.unversioned_sys_platform() == 'win32')

    conf.env.XMMS_PKGCONF_FILES.append(('xmms2-plugin', ''))

    return True


def options(opt):
    opt.add_option('--disable-shmvis-server', action='store_true',
                   dest='without_unixshmserver', default=False,
                   help="Disable shared memory support for visualization")
