/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

#include "config.h"

#include "pulse/pulse.h"

#include <guacamole/audio.h>
#include <guacamole/client.h>
#include <guacamole/user.h>
#include <pulse/pulseaudio.h>

/**
 * Returns whether the given buffer contains only silence (only null bytes).
 *
 * @param buffer
 *     The audio buffer to check.
 *
 * @param length
 *     The length of the buffer to check.
 *
 * @return
 *     Non-zero if the audio buffer contains silence, zero otherwise.
 */
static int guac_pa_is_silence(const void* buffer, size_t length) {

    int i;

    const unsigned char* current = (const unsigned char*) buffer;

    /* For each byte in buffer */
    for (i = 0; i < length; i++) {

        /* If current value non-zero, then not silence */
        if (*(current++))
            return 0;

    }

    /* Otherwise, the buffer contains 100% silence */
    return 1;

}

/**
 * Callback invoked by PulseAudio when PCM data is available for reading
 * from the given stream. The PCM data can be read using pa_stream_peek().
 *
 * @param stream
 *     The PulseAudio stream which has PCM data available.
 *
 * @param length
 *     The number of bytes of PCM data available on the given stream.
 *
 * @param data
 *     A pointer to the guac_pa_stream structure associated with the Guacamole
 *     stream receiving audio data from PulseAudio.
 */
static void __stream_read_callback(pa_stream* stream, size_t length,
        void* data) {

    guac_pa_stream* guac_stream = (guac_pa_stream*) data;
    guac_audio_stream* audio = guac_stream->audio;

    const void* buffer;

    /* Read data */
    pa_stream_peek(stream, &buffer, &length);

    /* Continuously write received PCM data */
    if (!guac_pa_is_silence(buffer, length))
        guac_audio_stream_write_pcm(audio, buffer, length);

    /* Flush upon silence */
    else
        guac_audio_stream_flush(audio);

    /* Advance buffer */
    pa_stream_drop(stream);

}

/**
 * Callback invoked by PulseAudio when the audio stream has changed state. The
 * new state can be retrieved using pa_stream_get_state().
 *
 * @param stream
 *     The PulseAudio stream which has changed state.
 *
 * @param data
 *     A pointer to the guac_pa_stream structure associated with the Guacamole
 *     stream receiving audio data from PulseAudio.
 */
static void __stream_state_callback(pa_stream* stream, void* data) {

    guac_pa_stream* guac_stream = (guac_pa_stream*) data;
    guac_client* client = guac_stream->client;

    switch (pa_stream_get_state(stream)) {

        case PA_STREAM_UNCONNECTED:
            guac_client_log(client, GUAC_LOG_INFO,
                    "PulseAudio stream currently unconnected");
            break;

        case PA_STREAM_CREATING:
            guac_client_log(client, GUAC_LOG_INFO, "PulseAudio stream being created...");
            break;

        case PA_STREAM_READY:
            guac_client_log(client, GUAC_LOG_INFO, "PulseAudio stream now ready");
            break;

        case PA_STREAM_FAILED:
            guac_client_log(client, GUAC_LOG_INFO, "PulseAudio stream connection failed");
            break;

        case PA_STREAM_TERMINATED:
            guac_client_log(client, GUAC_LOG_INFO, "PulseAudio stream terminated");
            break;

        default:
            guac_client_log(client, GUAC_LOG_INFO,
                    "Unknown PulseAudio stream state: 0x%x",
                    pa_stream_get_state(stream));

    }

}

/**
 * Callback invoked by PulseAudio when the audio sink information has been
 * retrieved. The callback is invoked repeatedly, once for each available
 * sink, followed by one final invocation with the is_last flag set. The final
 * invocation (with is_last set) does not describe a sink; it serves as a
 * terminator only.
 *
 * @param context 
 *     The PulseAudio context which is providing the sink information.
 *
 * @param info
 *     Information describing an available audio sink.
 *
 * @param is_last
 *     Non-zero if this invocation is the final invocation of this callback for
 *     all currently-available sinks (and this invocation does not describe a
 *     sink), zero otherwise.
 *
 * @param data
 *     A pointer to the guac_pa_stream structure associated with the Guacamole
 *     stream receiving audio data from PulseAudio.
 */
static void __context_get_sink_info_callback(pa_context* context,
        const pa_sink_info* info, int is_last, void* data) {

    guac_pa_stream* guac_stream = (guac_pa_stream*) data;
    guac_client* client = guac_stream->client;

    pa_stream* stream;
    pa_sample_spec spec;
    pa_buffer_attr attr;

    /* Stop if end of list reached */
    if (is_last)
        return;

    guac_client_log(client, GUAC_LOG_INFO, "Starting streaming from \"%s\"",
            info->description);

    /* Set format */
    spec.format   = PA_SAMPLE_S16LE;
    spec.rate     = GUAC_PULSE_AUDIO_RATE;
    spec.channels = GUAC_PULSE_AUDIO_CHANNELS;

    attr.maxlength = -1;
    attr.fragsize  = GUAC_PULSE_AUDIO_FRAGMENT_SIZE;

    /* Create stream */
    stream = pa_stream_new(context, "Guacamole Audio", &spec, NULL);

    /* Set stream callbacks */
    pa_stream_set_state_callback(stream, __stream_state_callback, guac_stream);
    pa_stream_set_read_callback(stream, __stream_read_callback, guac_stream);

    /* Start stream */
    pa_stream_connect_record(stream, info->monitor_source_name, &attr,
                PA_STREAM_DONT_INHIBIT_AUTO_SUSPEND
              | PA_STREAM_ADJUST_LATENCY);

}

/**
 * Callback invoked by PulseAudio when server information has been retrieved.
 *
 * @param context 
 *     The PulseAudio context which is providing the sink information.
 *
 * @param info
 *     Information describing the PulseAudio server.
 *
 * @param data
 *     A pointer to the guac_pa_stream structure associated with the Guacamole
 *     stream receiving audio data from PulseAudio.
 */
static void __context_get_server_info_callback(pa_context* context,
        const pa_server_info* info, void* data) {

    guac_pa_stream* guac_stream = (guac_pa_stream*) data;
    guac_client* client = guac_stream->client;

    /* If no default sink, cannot continue */
    if (info->default_sink_name == NULL) {
        guac_client_log(client, GUAC_LOG_ERROR, "No default sink. Cannot stream audio.");
        return;
    }

    guac_client_log(client, GUAC_LOG_INFO, "Will use default sink: \"%s\"",
            info->default_sink_name);

    /* Wait for default sink information */
    pa_operation_unref(
            pa_context_get_sink_info_by_name(context,
                info->default_sink_name, __context_get_sink_info_callback,
                guac_stream));

}

/**
 * Callback invoked by PulseAudio when the overall audio context has changed
 * state. The new state can be retrieved using pa_context_get_state().
 *
 * @param context 
 *     The PulseAudio context which has changed state.
 *
 * @param data
 *     A pointer to the guac_pa_stream structure associated with the Guacamole
 *     stream receiving audio data from PulseAudio.
 */
static void __context_state_callback(pa_context* context, void* data) {

    guac_pa_stream* guac_stream = (guac_pa_stream*) data;
    guac_client* client = guac_stream->client;

    switch (pa_context_get_state(context)) {

        case PA_CONTEXT_UNCONNECTED:
            guac_client_log(client, GUAC_LOG_INFO,
                    "PulseAudio reports it is unconnected");
            break;

        case PA_CONTEXT_CONNECTING:
            guac_client_log(client, GUAC_LOG_INFO, "Connecting to PulseAudio...");
            break;

        case PA_CONTEXT_AUTHORIZING:
            guac_client_log(client, GUAC_LOG_INFO,
                    "Authorizing PulseAudio connection...");
            break;

        case PA_CONTEXT_SETTING_NAME:
            guac_client_log(client, GUAC_LOG_INFO, "Sending client name...");
            break;

        case PA_CONTEXT_READY:
            guac_client_log(client, GUAC_LOG_INFO, "PulseAudio now ready");
            pa_operation_unref(pa_context_get_server_info(context,
                        __context_get_server_info_callback, guac_stream));
            break;

        case PA_CONTEXT_FAILED:
            guac_client_log(client, GUAC_LOG_INFO, "PulseAudio connection failed");
            break;

        case PA_CONTEXT_TERMINATED:
            guac_client_log(client, GUAC_LOG_INFO, "PulseAudio connection terminated");
            break;

        default:
            guac_client_log(client, GUAC_LOG_INFO,
                    "Unknown PulseAudio context state: 0x%x",
                    pa_context_get_state(context));

    }

}

guac_pa_stream* guac_pa_stream_alloc(guac_client* client,
        const char* server_name) {

    guac_audio_stream* audio = guac_audio_stream_alloc(client, NULL,
            GUAC_PULSE_AUDIO_RATE, GUAC_PULSE_AUDIO_CHANNELS,
            GUAC_PULSE_AUDIO_BPS);

    /* Abort if audio stream cannot be created */
    if (audio == NULL)
        return NULL;

    /* Init main loop */
    guac_pa_stream* stream = malloc(sizeof(guac_pa_stream));
    stream->client = client;
    stream->audio = audio;
    stream->pa_mainloop = pa_threaded_mainloop_new();

    /* Create context */
    pa_context* context = pa_context_new(
            pa_threaded_mainloop_get_api(stream->pa_mainloop),
            "Guacamole Audio");

    /* Set up context */
    pa_context_set_state_callback(context, __context_state_callback, stream);
    pa_context_connect(context, server_name, PA_CONTEXT_NOAUTOSPAWN, NULL);

    /* Start loop */
    pa_threaded_mainloop_start(stream->pa_mainloop);

    return stream;

}

void guac_pa_stream_add_user(guac_pa_stream* stream, guac_user* user) {
    guac_audio_stream_add_user(stream->audio, user);
}

void guac_pa_stream_free(guac_pa_stream* stream) {

    /* Stop loop */
    pa_threaded_mainloop_stop(stream->pa_mainloop);

    /* Free underlying audio stream */
    guac_audio_stream_free(stream->audio);

    /* Stream now ended */
    guac_client_log(stream->client, GUAC_LOG_INFO, "Audio stream finished");
    free(stream);

}

