Пример #1
0
int kqt_Handle_set_position(kqt_Handle handle, int track, long long nanoseconds)
{
    check_handle(handle, 0);

    Handle* h = get_handle(handle);
    check_data_is_valid(h, 0);
    check_data_is_validated(h, 0);

    if (track < -1 || track >= KQT_TRACKS_MAX)
    {
        Handle_set_error(h, ERROR_ARGUMENT, "Invalid track number: %d", track);
        return 0;
    }
    if (nanoseconds < 0)
    {
        Handle_set_error(h, ERROR_ARGUMENT, "nanoseconds must be non-negative");
        return 0;
    }

    int64_t skip_frames = (int64_t)(((double)nanoseconds / 1000000000L) *
        Player_get_audio_rate(h->player));

    Device_states_reset(Player_get_device_states(h->player));

    Player_reset(h->player, track);
    Player_skip(h->player, skip_frames);

    return 1;
}
Пример #2
0
int kqt_Handle_set_audio_rate(kqt_Handle handle, long rate)
{
    check_handle(handle, 0);

    Handle* h = get_handle(handle);
    check_data_is_valid(h, 0);
    check_data_is_validated(h, 0);

    if (rate <= 0)
    {
        Handle_set_error(h, ERROR_ARGUMENT, "Audio rate must be positive");
        return 0;
    }
#if LONG_MAX > INT32_MAX
    else if ((int64_t)rate > INT32_MAX)
    {
        Handle_set_error(h, ERROR_ARGUMENT, "Audio rate must be <= %" PRId32, INT32_MAX);
        return 0;
    }
#endif

    if (!Player_set_audio_rate(h->player, (int32_t)rate))
    {
        Handle_set_error(
                h, ERROR_MEMORY, "Couldn't allocate memory after change of audio rate.");
        return 0;
    }

    return 1;
}
Пример #3
0
int kqt_Handle_set_thread_count(kqt_Handle handle, int count)
{
    check_handle(handle, 0);

    Handle* h = get_handle(handle);
    check_data_is_valid(h, 0);
    check_data_is_validated(h, 0);

    if (count < 1)
    {
        Handle_set_error(h, ERROR_ARGUMENT, "Thread count must be positive");
        return 0;
    }
    if (count > KQT_THREADS_MAX)
    {
        Handle_set_error(
                h, ERROR_ARGUMENT, "Thread count must not exceed %d", KQT_THREADS_MAX);
        return 0;
    }

    Error* error = ERROR_AUTO;

    if (!Player_set_thread_count(h->player, count, error))
    {
        Handle_set_error_from_Error(h, error);
        return 0;
    }

    return 1;
}
Пример #4
0
int kqt_Handle_set_audio_buffer_size(kqt_Handle handle, long size)
{
    check_handle(handle, 0);

    Handle* h = get_handle(handle);
    check_data_is_valid(h, 0);
    check_data_is_validated(h, 0);

    if (size <= 0)
    {
        Handle_set_error(h, ERROR_ARGUMENT, "Buffer size must be positive");
        return 0;
    }
    if (size > KQT_AUDIO_BUFFER_SIZE_MAX)
    {
        Handle_set_error(
                h,
                ERROR_ARGUMENT,
                "Buffer size must not be greater than %ld frames",
                KQT_AUDIO_BUFFER_SIZE_MAX);
        return 0;
    }

    if (!Player_set_audio_buffer_size(h->player, (int32_t)size))
    {
        Handle_set_error(h, ERROR_MEMORY, "Couldn't allocate memory for new buffers");
        return 0;
    }

    return 1;
}
Пример #5
0
kqt_Handle kqt_new_Handle(void)
{
    Handle* handle = memory_alloc_item(Handle);
    if (handle == NULL)
    {
        Handle_set_error(0, ERROR_MEMORY, "Couldn't allocate memory");
        return 0;
    }

    if (!Handle_init(handle))
    {
        memory_free(handle);
        return 0;
    }

    kqt_Handle id = add_handle(handle);
    if (id == 0)
    {
        Handle_deinit(handle);
        memory_free(handle);
        return 0;
    }

    return id;
}
Пример #6
0
bool Handle_init(Handle* handle)
{
    assert(handle != NULL);

    handle->data_is_valid = true;
    handle->data_is_validated = true;
    handle->module = NULL;
    handle->error = *ERROR_AUTO;
    handle->validation_error = *ERROR_AUTO;
    memset(handle->position, '\0', POSITION_LENGTH);
    handle->player = NULL;
    handle->length_counter = NULL;

//    int buffer_count = SONG_DEFAULT_BUF_COUNT;
//    int voice_count = 256;

    handle->module = new_Module();
    if (handle->module == NULL)
    {
        Handle_set_error(NULL, ERROR_MEMORY, "Couldn't allocate memory");
        Handle_deinit(handle);
        return false;
    }

    // Create players
    handle->player = new_Player(
            handle->module,
            DEFAULT_AUDIO_RATE,
            2048,
            16384,
            256);
    handle->length_counter = new_Player(handle->module, 1000000000L, 0, 0, 0);
    if (handle->player == NULL || handle->length_counter == NULL)
    {
        Handle_set_error(NULL, ERROR_MEMORY, "Couldn't allocate memory");
        Handle_deinit(handle);
        return false;
    }

    Handle_stop(handle);
    //kqt_Handle_set_position(handle, 0, 0);
    return true;
}
Пример #7
0
int kqt_Handle_set_data(
        kqt_Handle handle,
        const char* key,
        const void* data,
        long length)
{
    check_handle(handle, 0);

    Handle* h = get_handle(handle);
    check_data_is_valid(h, 0);
    check_key(h, key, 0);

    // Short-circuit if we have already got invalid data
    // TODO: Remove this if we decide to collect more error info
    if (Error_is_set(&h->validation_error))
        return 1;

    if (length < 0)
    {
        Handle_set_error(
                h, ERROR_ARGUMENT, "Data length must be non-negative");
        return 0;
    }

    if (data == NULL && length > 0)
    {
        Handle_set_error(
                h,
                ERROR_ARGUMENT,
                "Data must not be null if given length (%ld) is positive",
                length);
        return 0;
    }

    if (!parse_data(h, key, data, length))
        return 0;

    h->data_is_validated = false;

    return 1;
}
Пример #8
0
int kqt_Handle_fire_event(kqt_Handle handle, int channel, const char* event)
{
    check_handle(handle, 0);

    Handle* h = get_handle(handle);
    check_data_is_valid(h, 0);
    check_data_is_validated(h, 0);

    if (channel < 0 || channel >= KQT_COLUMNS_MAX)
    {
        Handle_set_error(h, ERROR_ARGUMENT, "Invalid channel number: %d", channel);
        return 0;
    }
    if (event == NULL)
    {
        Handle_set_error(h, ERROR_ARGUMENT, "No event description given");
        return 0;
    }

    const size_t length = strlen(event);
    if (length > 4096)
    {
        Handle_set_error(h, ERROR_ARGUMENT, "Event description is too long");
        return 0;
    }

    Streader* sr = Streader_init(STREADER_AUTO, event, (int64_t)length);
    if (!Player_fire(h->player, channel, sr))
    {
        rassert(Streader_is_error_set(sr));
        Handle_set_error(
                h,
                ERROR_ARGUMENT,
                "Invalid event description `%s`: %s",
                event, Streader_get_error_desc(sr));
        return 0;
    }

    return 1;
}
Пример #9
0
static kqt_Handle add_handle(Handle* handle)
{
    rassert(handle != NULL);

#ifndef NDEBUG
    for (int i = 0; i < KQT_HANDLES_MAX; ++i)
        rassert(handles[i] != handle);
#endif

    static int next_try = 0;

    for (int i = 0; i < KQT_HANDLES_MAX; ++i)
    {
        const int try = (i + next_try) % KQT_HANDLES_MAX;
        if (handles[try] == NULL)
        {
            handles[try] = handle;
            next_try = try + 1;
            return try + 1; // shift kqt_Handle range to [1, KQT_HANDLES_MAX]
        }
    }

    Handle_set_error(NULL, ERROR_MEMORY,
            "Maximum number of Kunquat Handles reached");
    return 0;
}


Handle* get_handle(kqt_Handle id)
{
    rassert(kqt_Handle_is_valid(id));

    Handle* handle = handles[id - 1];
    rassert(handle != NULL);

    return handle;
}


static bool remove_handle(kqt_Handle id)
{
    rassert(kqt_Handle_is_valid(id));

    const bool was_null = (handles[id - 1] == NULL);
    handles[id - 1] = NULL;

    return !was_null;
}
Пример #10
0
const float* kqt_Handle_get_audio(kqt_Handle handle, int index)
{
    check_handle(handle, NULL);

    Handle* h = get_handle(handle);
    check_data_is_valid(h, NULL);
    check_data_is_validated(h, NULL);

    if (index < 0 || index >= KQT_BUFFERS_MAX)
    {
        Handle_set_error(h, ERROR_ARGUMENT, "Buffer #%d does not exist", index);
        return NULL;
    }

    return Player_get_audio(h->player, index);
}
Пример #11
0
void kqt_del_Handle(kqt_Handle handle)
{
    check_handle_void(handle);
    Handle* h = get_handle(handle);

    if (!remove_handle(handle))
    {
        Handle_set_error(NULL, ERROR_ARGUMENT,
                "Invalid Kunquat Handle: %d", handle);
        return;
    }

    Handle_deinit(h);
    memory_free(h);

    return;
}
Пример #12
0
int kqt_Handle_play(kqt_Handle handle, long nframes)
{
    check_handle(handle, 0);

    Handle* h = get_handle(handle);
    check_data_is_valid(h, 0);
    check_data_is_validated(h, 0);

    if (nframes <= 0)
    {
        Handle_set_error(h, ERROR_ARGUMENT, "Number of frames must be positive.");
        return 0;
    }

    Player_play(h->player, (int32_t)min(nframes, KQT_AUDIO_BUFFER_SIZE_MAX));

    return 1;
}
Пример #13
0
long long kqt_Handle_get_duration(kqt_Handle handle, int track)
{
    check_handle(handle, -1);

    Handle* h = get_handle(handle);
    check_data_is_valid(h, -1);
    check_data_is_validated(h, -1);

    if (track < -1 || track >= KQT_TRACKS_MAX)
    {
        Handle_set_error(h, ERROR_ARGUMENT, "Invalid track number: %d", track);
        return -1;
    }

    Player_reset(h->length_counter, track);
    Player_skip(h->length_counter, KQT_CALC_DURATION_MAX);

    return Player_get_nanoseconds(h->length_counter);
}
Пример #14
0
static bool Handle_update_connections(Handle* handle)
{
    rassert(handle != NULL);

    Module* module = Handle_get_module(handle);
    const Connections* conns = Module_get_connections(module);

    if (conns == NULL)
        return true;

    Device_states* dstates = Player_get_device_states(handle->player);

    if (!Device_states_prepare(dstates, conns))
    {
        Handle_set_error(handle, ERROR_MEMORY,
                "Couldn't allocate memory for connections");
        return false;
    }

    return true;
}
Пример #15
0
bool key_is_valid(Handle* handle, const char* key)
{
    rassert(handle != NULL);

    if (key == NULL)
    {
        Handle_set_error(handle, ERROR_ARGUMENT, "No key given");
        return false;
    }

    if (strlen(key) > KQT_KEY_LENGTH_MAX)
    {
        char key_repr[KQT_KEY_LENGTH_MAX + 3] = { '\0' };
        strncpy(key_repr, key, KQT_KEY_LENGTH_MAX - 1);
        strcat(key_repr, "...");
        Handle_set_error(handle, ERROR_ARGUMENT, "Key %s is too long"
                " (over %d characters)", key_repr, KQT_KEY_LENGTH_MAX);
        return false;
    }

    bool valid_element = false;
    bool element_has_period = false;
    const char* key_iter = key;

    while (*key_iter != '\0')
    {
        if (!(*key_iter >= '0' && *key_iter <= '9') &&
                strchr("abcdefghijklmnopqrstuvwxyz_./X", *key_iter) == NULL)
        {
            Handle_set_error(handle, ERROR_ARGUMENT, "Key %s contains an"
                    " illegal character \'%c\'", key, *key_iter);
            return false;
        }

        if (*key_iter != '.' && *key_iter != '/')
        {
            valid_element = true;
        }
        else if (*key_iter == '.')
        {
            element_has_period = true;
        }
        else if (*key_iter == '/')
        {
            if (!valid_element)
            {
                Handle_set_error(handle, ERROR_ARGUMENT, "Key %s contains"
                        " an invalid component", key);
                return false;
            }
            else if (element_has_period)
            {
                Handle_set_error(handle, ERROR_ARGUMENT, "Key %s contains"
                        " an intermediate component with a period", key);
                return false;
            }
            valid_element = false;
            element_has_period = false;
        }

        ++key_iter;
    }

    if (!element_has_period)
    {
        Handle_set_error(handle, ERROR_ARGUMENT, "The final element of"
                " key %s does not have a period", key);
        return false;
    }

    return true;
}