/* tools/sigcheck.c — per-port SDI signal scanner, run on host with SDK installed */
#include <stdio.h>
#include <unistd.h>
#include <time.h>
#include "videomaster/VideoMasterHD_Core.h"
#include "videomaster/VideoMasterHD_Sdi.h"

static ULONG rx_types[8] = {
    VHD_ST_RX0,VHD_ST_RX1,VHD_ST_RX2,VHD_ST_RX3,
    VHD_ST_RX4,VHD_ST_RX5,VHD_ST_RX6,VHD_ST_RX7
};

int main(void) {
    ULONG dll, nb;
    if (VHD_GetApiInfo(&dll,&nb)!=VHDERR_NOERROR||nb==0) { fprintf(stderr,"no boards\n"); return 1; }
    HANDLE board;
    if (VHD_OpenBoardHandle(0,&board,NULL,0)!=VHDERR_NOERROR) { fprintf(stderr,"board open fail\n"); return 1; }

    printf("Port | Result\n");
    printf("-----|-------\n");

    for (int p = 0; p < 8; p++) {
        HANDLE stream = NULL;
        ULONG r = VHD_OpenStreamHandle(board, rx_types[p],
                                       VHD_SDI_STPROC_DISJOINED_VIDEO,
                                       NULL, &stream, NULL);
        if (r != VHDERR_NOERROR) {
            printf("  %d  | OPEN_FAIL rc=%lu\n", p, r);
            fflush(stdout);
            continue;
        }
        VHD_SetStreamProperty(stream, VHD_CORE_SP_TRANSFER_SCHEME, VHD_TRANSFER_SLAVED);
        VHD_SetStreamProperty(stream, VHD_CORE_SP_BUFFERQUEUE_DEPTH, 4);
        if (VHD_StartStream(stream) != VHDERR_NOERROR) {
            VHD_CloseStreamHandle(stream);
            printf("  %d  | START_FAIL\n", p);
            fflush(stdout);
            continue;
        }

        ULONG std = (ULONG)NB_VHD_VIDEOSTANDARDS;
        ULONG clk = VHD_CLOCKDIV_1;
        struct timespec deadline, now;
        clock_gettime(CLOCK_MONOTONIC, &deadline);
        deadline.tv_sec += 4;
        while (1) {
            clock_gettime(CLOCK_MONOTONIC, &now);
            if (now.tv_sec>deadline.tv_sec || (now.tv_sec==deadline.tv_sec && now.tv_nsec>=deadline.tv_nsec)) break;
            VHD_GetStreamProperty(stream, VHD_SDI_SP_VIDEO_STANDARD, &std);
            if (std != (ULONG)NB_VHD_VIDEOSTANDARDS) break;
            struct timespec ts = {0, 100000000L};
            nanosleep(&ts, NULL);
        }
        VHD_GetStreamProperty(stream, VHD_SDI_SP_CLOCK_DIVISOR, &clk);
        VHD_StopStream(stream);
        VHD_CloseStreamHandle(stream);

        if (std == (ULONG)NB_VHD_VIDEOSTANDARDS) {
            printf("  %d  | NO SIGNAL\n", p);
        } else {
            int ntsc = (clk == VHD_CLOCKDIV_1001);
            int w=1920,h=1080,fn=30,fd=1;
            switch(std) {
                case VHD_VIDEOSTD_S274M_1080p_60Hz: fn=ntsc?60000:60;fd=ntsc?1001:1; break;
                case VHD_VIDEOSTD_S274M_1080p_50Hz: fn=50;fd=1; break;
                case VHD_VIDEOSTD_S274M_1080p_30Hz: fn=ntsc?30000:30;fd=ntsc?1001:1; break;
                case VHD_VIDEOSTD_S274M_1080p_25Hz: fn=25;fd=1; break;
                case VHD_VIDEOSTD_S274M_1080p_24Hz: fn=ntsc?24000:24;fd=ntsc?1001:1; break;
                case VHD_VIDEOSTD_S274M_1080i_60Hz: fn=ntsc?30000:30;fd=ntsc?1001:1; break;
                case VHD_VIDEOSTD_S274M_1080i_50Hz: fn=25;fd=1; break;
                case VHD_VIDEOSTD_S296M_720p_60Hz: w=1280;h=720;fn=ntsc?60000:60;fd=ntsc?1001:1; break;
                case VHD_VIDEOSTD_S296M_720p_50Hz: w=1280;h=720;fn=50;fd=1; break;
                default: break;
            }
            printf("  %d  | SIGNAL  std=%lu  %dx%d  %d/%d\n", p, std, w, h, fn, fd);
        }
        fflush(stdout);
        usleep(200000);
    }
    VHD_CloseBoardHandle(board);
    return 0;
}
