void guac_audio_stream_end(guac_audio_stream* audio) { double duration; /* Flush stream and finish encoding */ guac_audio_stream_flush(audio); audio->encoder->end_handler(audio); /* Calculate duration of PCM data */ duration = ((double) (audio->pcm_bytes_written * 1000 * 8)) / audio->rate / audio->channels / audio->bps; /* Send audio */ guac_protocol_send_audio(audio->client->socket, audio->stream, audio->stream->index, audio->encoder->mimetype, duration); guac_protocol_send_blob(audio->client->socket, audio->stream, audio->encoded_data, audio->encoded_data_used); guac_protocol_send_end(audio->client->socket, audio->stream); /* Clear data */ audio->encoded_data_used = 0; }
/** * Guacamole client plugin entry point. This function will be called by guacd * when the protocol associated with this plugin is selected. * * @param client * A newly-allocated guac_client structure representing the client which * connected to guacd. * * @param argc * The number of arguments within the argv array. * * @param argv * All arguments passed during the Guacamole protocol handshake. These * arguments correspond identically in both order and number to the * arguments listed in GUAC_CLIENT_ARGS. */ int guac_client_init(guac_client* client, int argc, char** argv) { /* Validate argument count */ if (argc != STREAMTEST_ARGS_COUNT) { guac_client_log(client, GUAC_LOG_ERROR, "Wrong number of arguments."); return 1; } /* Allocate stream for media */ streamtest_playback_mode mode; guac_stream* stream = guac_client_alloc_stream(client); /* Determine playback mode from mimetype */ if (strncmp(argv[IDX_MIMETYPE], "audio/", 6) == 0) { mode = STREAMTEST_AUDIO; guac_client_log(client, GUAC_LOG_DEBUG, "Recognized type \"%s\" as audio", argv[IDX_MIMETYPE]); } else if (strncmp(argv[IDX_MIMETYPE], "video/", 6) == 0) { mode = STREAMTEST_VIDEO; guac_client_log(client, GUAC_LOG_DEBUG, "Recognized type \"%s\" as video", argv[IDX_MIMETYPE]); } /* Abort if type cannot be recognized */ else { guac_client_log(client, GUAC_LOG_ERROR, "Invalid media type \"%s\" (not audio nor video)", argv[IDX_MIMETYPE]); return 1; } /* Initialize streaming depending on playback mode */ switch (mode) { /* Set up progress bar for audio streams */ case STREAMTEST_AUDIO: /* Begin audio stream */ guac_protocol_send_audio(client->socket, stream, argv[IDX_MIMETYPE]); /* Init display */ guac_protocol_send_size(client->socket, GUAC_DEFAULT_LAYER, STREAMTEST_PROGRESS_WIDTH, STREAMTEST_PROGRESS_HEIGHT); break; /* Set up generic video area for video streams */ case STREAMTEST_VIDEO: /* Begin video stream */ guac_protocol_send_video(client->socket, stream, GUAC_DEFAULT_LAYER, argv[IDX_MIMETYPE]); /* Init display */ guac_protocol_send_size(client->socket, GUAC_DEFAULT_LAYER, client->info.optimal_width, client->info.optimal_height); break; /* There are no other playback modes */ default: assert(false); } /* Attempt to open specified file, abort on error */ int fd = open(argv[IDX_FILENAME], O_RDONLY); if (fd == -1) { guac_client_log(client, GUAC_LOG_ERROR, "Unable to open \"%s\": %s", argv[IDX_FILENAME], strerror(errno)); return 1; } int file_size = streamtest_get_file_size(fd); if (file_size == -1) { guac_client_log(client, GUAC_LOG_ERROR, "Unable to determine size of file \"%s\": %s", argv[IDX_FILENAME], strerror(errno)); return 1; } guac_client_log(client, GUAC_LOG_DEBUG, "Successfully opened file \"%s\" (%i bytes)", argv[IDX_FILENAME], file_size); /* Allocate state structure */ streamtest_state* state = malloc(sizeof(streamtest_state)); /* Set frame duration/size */ state->frame_duration = atoi(argv[IDX_FRAME_USECS]); state->frame_bytes = atoi(argv[IDX_BYTES_PER_FRAME]); state->frame_buffer = malloc(state->frame_bytes); guac_client_log(client, GUAC_LOG_DEBUG, "Frames will last %i microseconds and contain %i bytes", state->frame_duration, state->frame_bytes); /* Start with the file closed, playback not paused */ state->mode = mode; state->stream = stream; state->fd = fd; state->paused = false; state->file_size = file_size; /* Set client handlers and data */ client->handle_messages = streamtest_client_message_handler; client->key_handler = streamtest_client_key_handler; client->free_handler = streamtest_client_free_handler; client->data = state; /* Render initial progress bar */ streamtest_render_progress(client); guac_socket_flush(client->socket); /* Initialization complete */ return 0; }