guacamole-spice-protocol/src/protocols/rdp/audio_input.h

314 lines
9.7 KiB
C

/*
* 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.
*/
#ifndef GUAC_RDP_AUDIO_INPUT_H
#define GUAC_RDP_AUDIO_INPUT_H
#include "config.h"
#include "dvc.h"
#include <freerdp/freerdp.h>
#include <guacamole/stream.h>
#include <guacamole/user.h>
#include <pthread.h>
/**
* Handler which is invoked when a guac_rdp_audio_buffer's internal packet
* buffer has reached capacity and must be flushed.
*
* @param buffer
* The buffer which needs to be flushed as an audio packet.
*
* @param length
* The number of bytes stored within the buffer. This is guaranteed to be
* identical to the packet_size value specified when the audio buffer was
* initialized.
*
* @param data
* The arbitrary data pointer provided when the audio buffer was
* initialized.
*/
typedef void guac_rdp_audio_buffer_flush_handler(char* buffer, int length,
void* data);
/**
* A description of an arbitrary PCM audio format.
*/
typedef struct guac_rdp_audio_format {
/**
* The rate of the audio data in samples per second.
*/
int rate;
/**
* The number of channels included in the audio data. This will be 1 for
* monaural audio and 2 for stereo.
*/
int channels;
/**
* The size of each sample within the audio data, in bytes.
*/
int bps;
} guac_rdp_audio_format;
/**
* A buffer of arbitrary audio data. Received audio data can be written to this
* buffer, and will automatically be flushed via a given handler once the
* internal buffer reaches capacity.
*/
typedef struct guac_rdp_audio_buffer {
/**
* Lock which is acquired/released to ensure accesses to the audio buffer
* are atomic.
*/
pthread_mutex_t lock;
/**
* The user from which this audio buffer will receive data. If no user has
* yet opened an associated audio stream, this will be NULL.
*/
guac_user* user;
/**
* The stream from which this audio buffer will receive data. If no user
* has yet opened an associated audio stream, this will be NULL.
*/
guac_stream* stream;
/**
* The PCM format of the audio stream being received from the user, if any.
* If no stream is yet associated, the values stored within this format are
* undefined.
*/
guac_rdp_audio_format in_format;
/**
* The PCM format of the audio stream expected by RDP, if any. If no audio
* stream has yet been requested by the RDP server, the values stored
* within this format are undefined.
*/
guac_rdp_audio_format out_format;
/**
* The size that each audio packet must be, in bytes. The packet buffer
* within this structure will be at least this size.
*/
int packet_size;
/**
* The number of bytes currently stored within the packet buffer.
*/
int bytes_written;
/**
* The total number of bytes having ever been received by the Guacamole
* server for the current audio stream.
*/
int total_bytes_received;
/**
* The total number of bytes having ever been sent to the RDP server for
* the current audio stream.
*/
int total_bytes_sent;
/**
* All audio data being prepared for sending to the AUDIO_INPUT channel.
*/
char* packet;
/**
* Handler function which will be invoked when a full audio packet is
* ready to be flushed to the AUDIO_INPUT channel, if defined. If NULL,
* audio packets will simply be ignored.
*/
guac_rdp_audio_buffer_flush_handler* flush_handler;
/**
* Arbitrary data assigned by the AUDIO_INPUT plugin implementation.
*/
void* data;
} guac_rdp_audio_buffer;
/**
* Allocates a new audio buffer. The new audio buffer will ignore any received
* data until guac_rdp_audio_buffer_begin() is invoked, and will resume
* ignoring received data once guac_rdp_audio_buffer_end() is invoked.
*
* @return
* A newly-allocated audio buffer.
*/
guac_rdp_audio_buffer* guac_rdp_audio_buffer_alloc();
/**
* Associates the given audio buffer with the underlying audio stream which
* has been received from the given Guacamole user. Once both the Guacamole
* audio stream and the RDP audio stream are ready, an appropriate "ack"
* message will be sent.
*
* @param audio_buffer
* The audio buffer associated with the audio stream just received.
*
* @param user
* The Guacamole user that created the audio stream.
*
* @param stream
* The guac_stream object representing the audio stream.
*
* @param rate
* The rate of the audio stream being received from the user, if any, in
* samples per second.
*
* @param channels
* The number of channels included in the audio stream being received from
* the user, if any.
*
* @param bps
* The size of each sample within the audio stream being received from the
* user, if any, in bytes.
*/
void guac_rdp_audio_buffer_set_stream(guac_rdp_audio_buffer* audio_buffer,
guac_user* user, guac_stream* stream, int rate, int channels, int bps);
/**
* Defines the output format that should be used by the audio buffer when
* flushing packets of audio data received via guac_rdp_audio_buffer_write().
* As this format determines how the underlying packet buffer will be
* allocated, this function MUST be called prior to the call to
* guac_rdp_audio_buffer_begin().
*
* @param audio_buffer
* The audio buffer to set the output format of.
*
* @param rate
* The rate of the audio stream expected by RDP, in samples per second.
*
* @param channels
* The number of channels included in the audio stream expected by RDP.
*
* @param bps
* The size of each sample within the audio stream expected by RDP, in
* bytes.
*/
void guac_rdp_audio_buffer_set_output(guac_rdp_audio_buffer* audio_buffer,
int rate, int channels, int bps);
/**
* Begins handling of audio data received via guac_rdp_audio_buffer_write() and
* allocates the necessary underlying packet buffer. Audio packets having
* exactly packet_frames frames will be flushed as available using the provided
* flush_handler. An audio frame is a set of single samples, one sample per
* channel. The guac_rdp_audio_buffer_set_output() function MUST have
* been invoked first.
*
* @param audio_buffer
* The audio buffer to begin.
*
* @param packet_frames
* The exact number of frames (a set of samples, one for each channel)
* which MUST be included in all audio packets provided to the
* given flush_handler.
*
* @param flush_handler
* The function to invoke when an audio packet must be flushed.
*
* @param data
* Arbitrary data to provide to the flush_handler when an audio packet
* needs to be flushed.
*/
void guac_rdp_audio_buffer_begin(guac_rdp_audio_buffer* audio_buffer,
int packet_frames, guac_rdp_audio_buffer_flush_handler* flush_handler,
void* data);
/**
* Writes the given buffer of audio data to the given audio buffer. A new
* packet will be flushed using the associated flush handler once sufficient
* bytes have been accumulated.
*
* @param audio_buffer
* The audio buffer to which the given audio data should be written.
*
* @param buffer
* The buffer of audio data to write to the given audio buffer.
*
* @param length
* The number of bytes to write.
*/
void guac_rdp_audio_buffer_write(guac_rdp_audio_buffer* audio_buffer,
char* buffer, int length);
/**
* Stops handling of audio data received via guac_rdp_audio_buffer_write() and
* frees the underlying packet buffer. Further audio data will be ignored until
* guac_rdp_audio_buffer_begin() is invoked again.
*
* @param audio_buffer
* The audio buffer to end.
*/
void guac_rdp_audio_buffer_end(guac_rdp_audio_buffer* audio_buffer);
/**
* Frees the given audio buffer. If guac_rdp_audio_buffer_end() has not yet
* been called, its associated packet buffer will also be freed.
*
* @param audio_buffer
* The audio buffer to free.
*/
void guac_rdp_audio_buffer_free(guac_rdp_audio_buffer* audio_buffer);
/**
* Handler for inbound audio data (audio input).
*/
guac_user_audio_handler guac_rdp_audio_handler;
/**
* Handler for stream data related to audio input.
*/
guac_user_blob_handler guac_rdp_audio_blob_handler;
/**
* Handler for end-of-stream related to audio input.
*/
guac_user_end_handler guac_rdp_audio_end_handler;
/**
* Adds Guacamole's "guacai" plugin to the list of dynamic virtual channel
* plugins to be loaded by FreeRDP's "drdynvc" plugin. The plugin will only
* be loaded once guac_rdp_load_drdynvc() is invoked with the guac_rdp_dvc_list
* passed to this function. The "guacai" plugin ultimately adds support for the
* "AUDIO_INPUT" dynamic virtual channel.
*
* @param context
* The rdpContext associated with the active RDP session.
*
* @param list
* The guac_rdp_dvc_list to which the "guacai" plugin should be added, such
* that it may later be loaded by guac_rdp_load_drdynvc().
*/
void guac_rdp_audio_load_plugin(rdpContext* context, guac_rdp_dvc_list* list);
#endif