#-*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:ft=tcl:et:sw=4:ts=4:sts=4

PortSystem          1.0
PortGroup           github 1.0
PortGroup           cmake 1.1
PortGroup           legacysupport 1.1
PortGroup           active_variants 1.1

# whisper-server uses <filesystem>, missing from the system libc++ until 10.15
legacysupport.use_mp_libcxx yes

name                whisper
categories          audio
github.setup        ggerganov whisper.cpp 1.9.4 v
github.tarball_from archive
revision            0
license             MIT
maintainers         {ijams.me:nate @exprez135} \
                    openmaintainer
description         Port of OpenAI's Whisper model in C/C++
long_description    High-performance inference of OpenAI's Whisper automatic speech recognition \
                    (ASR) model
notes               "
Install this port's variants to include models, or download
your own and use the built-in `-m` feature.

Remember that whisper.cpp only functions on 16-bit WAV
files. You can use `ffmpeg -i input.mp3 -ar 16000
output.wav` to convert the file first.
"

compiler.cxx_standard   2017

checksums           whisper.cpp-${version}.tar.gz \
                    rmd160  f45c60a0491e0619401713d54fd963ebc1e9ead5 \
                    sha256  57e280cee375ab02425b806ad5146b99f6eb9357e3c2b31357c8a6af2e2e44ae \
                    size    9353438

depends_lib-append  port:ggml

patchfiles          whisper-add-models.diff \
                    include-missing-headers.diff

post-patch {
    reinplace "s|__PREFIX__|${prefix}|" src/whisper.cpp
}

configure.args-append   -DWHISPER_BUILD_EXAMPLES=ON \
                        -DWHISPER_BUILD_TESTS=OFF \
                        -DWHISPER_BUILD_IS_DEV=OFF \
                        -DWHISPER_USE_SYSTEM_GGML=ON

if {[string match *gcc* ${configure.compiler}] \
    && ${configure.build_arch} in [list arm i386 ppc]} {
    # ___atomic_load_8 and ___atomic_compare_exchange_8, from the bundled
    # miniaudio in examples/common-whisper.cpp
    configure.ldflags-append \
                        -latomic
}

post-destroot {
    # This port has always called the CLI `whisper`; upstream names it
    # whisper-cli and installs it alongside the other tools.
    ln -s whisper-cli ${destroot}${prefix}/bin/whisper
}

# Define model variants

variant tiny description {Install tiny model} {
    distfiles-append        ggml-tiny.bin:tiny
    master_sites-append     https://huggingface.co/ggerganov/whisper.cpp/resolve/main/:tiny
    checksums-append        ggml-tiny.bin \
                            sha256  be07e048e1e599ad46341c8d2a135645097a538221678b7acdd1b1919c6e1b21 \
                            size    77691713
    post-destroot {
        xinstall -d ${destroot}${prefix}/share/whisper/models
        xinstall ${distpath}/ggml-tiny.bin ${destroot}${prefix}/share/whisper/models/tiny.bin
    }
}

variant base description {Install base model} {
    distfiles-append        ggml-base.bin:base
    master_sites-append     https://huggingface.co/ggerganov/whisper.cpp/resolve/main/:base
    checksums-append        ggml-base.bin \
                            sha256  60ed5bc3dd14eea856493d334349b405782ddcaf0028d4b5df4088345fba2efe \
                            size    147951465
    post-destroot {
        xinstall -d ${destroot}${prefix}/share/whisper/models
        xinstall ${distpath}/ggml-base.bin ${destroot}${prefix}/share/whisper/models/base.bin
    }
}

variant small description {Install small model} {
    distfiles-append        ggml-small.bin:small
    master_sites-append     https://huggingface.co/ggerganov/whisper.cpp/resolve/main/:small
    checksums-append        ggml-small.bin \
                            sha256  1be3a9b2063867b937e64e2ec7483364a79917e157fa98c5d94b5c1fffea987b \
                            size    487601967
    post-destroot {
        xinstall -d ${destroot}${prefix}/share/whisper/models
        xinstall ${distpath}/ggml-small.bin ${destroot}${prefix}/share/whisper/models/small.bin
    }
}

variant medium description {Install medium model} {
    distfiles-append        ggml-medium.bin:medium
    master_sites-append     https://huggingface.co/ggerganov/whisper.cpp/resolve/main/:medium
    checksums-append        ggml-medium.bin \
                            sha256  6c14d5adee5f86394037b4e4e8b59f1673b6cee10e3cf0b11bbdbee79c156208 \
                            size    1533763059
    post-destroot {
        xinstall -d ${destroot}${prefix}/share/whisper/models
        xinstall ${distpath}/ggml-medium.bin ${destroot}${prefix}/share/whisper/models/medium.bin
    }
}

variant large description {Install large model} {
    distfiles-append        ggml-large-v3.bin:large
    master_sites-append     https://huggingface.co/ggerganov/whisper.cpp/resolve/main/:large
    checksums-append        ggml-large-v3.bin \
                            sha256  64d182b440b98d5203c4f9bd541544d84c605196c4f7b845dfa11fb23594d1e2 \
                            size    3095033483
    post-destroot {
        xinstall -d ${destroot}${prefix}/share/whisper/models
        xinstall ${distpath}/ggml-large-v3.bin ${destroot}${prefix}/share/whisper/models/large.bin
    }
}

# Mirror a ggml variant here when it adds a backend to GGML_AVAILABLE_BACKENDS
# in ${prefix}/lib/cmake/ggml/ggml-config.cmake. Each of those builds a
# libggml-*.dylib that whisper's binaries link directly, so a ggml rebuilt
# without one leaves whisper failing at load time. ggml's other variants only
# retune code inside libggml and leave whisper's link line unchanged.
variant blas description {Use ggml with BLAS support} {
    require_active_variants ggml blas
}

variant opencl description {Use ggml with OpenCL support} {
    require_active_variants ggml opencl
}

variant metal conflicts vulkan description {Use ggml with Metal support} {
    require_active_variants ggml metal
}

variant vulkan conflicts metal description {Use ggml with Vulkan support} {
    require_active_variants ggml vulkan
}

default_variants    +blas

# Keep this in step with ggml's own +metal default: ggml builds the backend and
# carries the reason for the threshold.
if {${os.platform} eq "darwin" && ${os.major} >= 20 && \
    ${configure.sdk_version} >= 11} {
    default_variants    +metal
}
