<commit_before>/*
 * Copyright (C) 2010 Nokia Corporation.
 *
 * Contact: <NAME> <<EMAIL>>
 *          or <NAME> <<EMAIL>>
 *
 * These PulseAudio Modules are free software; you can redistribute
 * it and/or modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation
 * version 2.1 of the License.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
 * USA.
 */
#include "cmtspeech-connection.h"

#include <meego/module-voice-api.h>
#include "cmtspeech-mainloop-handler.h"
#include "cmtspeech-sink-input.h"
#include <pulsecore/rtpoll.h>
#include <pulsecore/core-rtclock.h>
#include <pulse/rtclock.h>
#include <pulse/timeval.h>
#include <poll.h>
#include <errno.h>

#include <cmtspeech.h>

/* TODO: Get rid of this and use asyncmsgq instead. */
enum cmt_speech_thread_state {
    CMT_UNINITIALIZED = 0,
    CMT_STARTING,
    CMT_RUNNING,
    CMT_ASK_QUIT,
    CMT_QUIT
};

/* This should be only used for memblock free cb - cmtspeech_free_cb - below
   and it is initialized in cmtspeech_connection_init(). */
static struct userdata *userdata = NULL;

static uint ul_frame_count = 0;

#define CMTSPEECH_CLEANUP_TIMER_TIMEOUT ((pa_usec_t)(5 * PA_USEC_PER_SEC))

enum cmtspeech_cleanup_state_name {
    CMTSPEECH_CLEANUP_TIMER_INACTIVE = 0,
    CMTSPEECH_CLEANUP_TIMER_ACTIVE,
    CMTSPEECH_CLEANUP_IN_PROGRESS
};

enum {
    CMTSPEECH_HANDLER_CLOSE_CONNECTION,
};

typedef struct cmtspeech_handler {
    pa_msgobject parent;
    struct userdata *u;
} cmtspeech_handler;

PA_DEFINE_PRIVATE_CLASS(cmtspeech_handler, pa_msgobject);
#define CMTSPEECH_HANDLER(o) cmtspeech_handler_cast(o)

static void cmtspeech_handler_free(pa_object *o) {
    cmtspeech_handler *h = CMTSPEECH_HANDLER(o);

    pa_log_info("Free called");
    pa_xfree(h);
}

static void close_cmtspeech_on_error(struct userdata *u);

static int cmtspeech_handler_process_msg(pa_msgobject *o, int code, void *ud, int64_t offset, pa_memchunk *chunk) {
    cmtspeech_handler *h = CMTSPEECH_HANDLER(o);
    struct userdata *u;

    cmtspeech_handler_assert_ref(h);
    pa_assert_se(u = h->u);

    switch (code) {
        case CMTSPEECH_HANDLER_CLOSE_CONNECTION:
            pa_log_debug("CMTSPEECH_HANDLER_CLOSE_CONNECTION");
            close_cmtspeech_on_error(u);
            return 0;
        default:
            pa_log_error("Unknown message code %d", code);
            return -1;
    }
}

static pa_msgobject *cmtspeech_handler_new(struct userdata *u) {
    cmtspeech_handler *h;

    pa_assert(u);
    pa_assert(u->core);
    pa_assert_se(h = pa_msgobject_new(cmtspeech_handler));

    h->parent.parent.free = cmtspeech_handler_free;
    h->parent.process_msg = cmtspeech_handler_process_msg;
    h->u = u;

    return (pa_msgobject *)h;
}

/* This is usually called from sink IO-thread */
static void cmtspeech_free_cb(void *p) {
    cmtspeech_t *cmtspeech;

    if (!p)
        return;

    if (!userdata) {
        pa_log_error("userdata not set, cmtspeech buffer %p was not freed!", p);
        return;
    }

    pa_mutex_lock(userdata->cmt_connection.cmtspeech_mutex);
    cmtspeech = userdata->cmt_connection.cmtspeech;
    if (!cmtspeech) {
        pa_log_error("cmtspeech not open, cmtspeech buffer %p was not freed!", p);
    } else {
        int ret;
        cmtspeech_buffer_t *buf = cmtspeech_dl_buffer_find_with_data(cmtspeech, (uint8_t*)p);
        if (buf != NULL) {
            if ((ret = cmtspeech_dl_buffer_release(cmtspeech, buf))) {
                pa_log_error("cmtspeech_dl_buffer_release(%p) failed return value %d.", (void *)buf, ret);
            }
        } else {
            pa_log_error("cmtspeech_dl_buffer_find_with_data() returned NULL, releasing buffer failed.");
        }
    }
    pa_mutex_unlock(userdata->cmt_connection.cmtspeech_mutex);
}

/* Called from sink IO-thread */
/* NOTE: If you ever see a seqfault when accessing these libcmtspeechdata owned
 * memblocks, then just free the cmtframes here after coping them to regular
 * pa_memblocks. The performance penalty should not be too severe. */
int cmtspeech_buffer_to_memchunk(struct userdata *u, cmtspeech_buffer_t *buf, pa_memchunk *chunk) {
    pa_assert_fp(u);
    pa_assert_fp(chunk);
    pa_assert_fp(buf);

    if (!buf->data) {
        pa_log_warn("No data in cmtspeech_buffer");
        if (cmtspeech_dl_buffer_release(u->cmt_connection.cmtspeech, buf))
            pa_log_warn("cmtspeech_dl_buffer_release() failed");
        return -1;
    }

    chunk->memblock = pa_memblock_new_user(u->core->mempool, buf->data, (size_t) buf->size, cmtspeech_free_cb, true);
    chunk->index = CMTSPEECH_DATA_HEADER_LEN;
    chunk->length = buf->count - CMTSPEECH_DATA_HEADER_LEN;

    return 0;
}

/* cmtspeech thread */
static inline
int push_cmtspeech_buffer_to_dl_queue(struct userdata *u, cmtspeech_dl_buf_t *buf) {
    pa_assert_fp(u);
    pa_assert_fp(buf);

    if (pa_asyncq_push(u->cmt_connection.dl_frame_queue, (void *)buf, false)) {
        int ret;
        struct cmtspeech_connection *c = &u->cmt_connection;

        pa_log_error("Failed to push dl frame to asyncq");
        pa_mutex_lock(c->cmtspeech_mutex);
        if ((ret = cmtspeech_dl_buffer_release(u->cmt_connection.cmtspeech, buf)))<commit_msg>[cmtspeech] Pass user data to new pa_memblock_new_user. MER#1466<commit_after>/*
 * Copyright (C) 2010 Nokia Corporation.
 *
 * Contact: <NAME> <<EMAIL>>
 *          or <NAME> <<EMAIL>>
 *
 * These PulseAudio Modules are free software; you can redistribute
 * it and/or modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation
 * version 2.1 of the License.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
 * USA.
 */
#include "cmtspeech-connection.h"

#include <meego/module-voice-api.h>
#include "cmtspeech-mainloop-handler.h"
#include "cmtspeech-sink-input.h"
#include <pulsecore/rtpoll.h>
#include <pulsecore/core-rtclock.h>
#include <pulse/rtclock.h>
#include <pulse/timeval.h>
#include <poll.h>
#include <errno.h>

#include <cmtspeech.h>

/* TODO: Get rid of this and use asyncmsgq instead. */
enum cmt_speech_thread_state {
    CMT_UNINITIALIZED = 0,
    CMT_STARTING,
    CMT_RUNNING,
    CMT_ASK_QUIT,
    CMT_QUIT
};

/* This should be only used for memblock free cb - cmtspeech_free_cb - below
   and it is initialized in cmtspeech_connection_init(). */
static struct userdata *userdata = NULL;

static uint ul_frame_count = 0;

#define CMTSPEECH_CLEANUP_TIMER_TIMEOUT ((pa_usec_t)(5 * PA_USEC_PER_SEC))

enum cmtspeech_cleanup_state_name {
    CMTSPEECH_CLEANUP_TIMER_INACTIVE = 0,
    CMTSPEECH_CLEANUP_TIMER_ACTIVE,
    CMTSPEECH_CLEANUP_IN_PROGRESS
};

enum {
    CMTSPEECH_HANDLER_CLOSE_CONNECTION,
};

typedef struct cmtspeech_handler {
    pa_msgobject parent;
    struct userdata *u;
} cmtspeech_handler;

PA_DEFINE_PRIVATE_CLASS(cmtspeech_handler, pa_msgobject);
#define CMTSPEECH_HANDLER(o) cmtspeech_handler_cast(o)

static void cmtspeech_handler_free(pa_object *o) {
    cmtspeech_handler *h = CMTSPEECH_HANDLER(o);

    pa_log_info("Free called");
    pa_xfree(h);
}

static void close_cmtspeech_on_error(struct userdata *u);

static int cmtspeech_handler_process_msg(pa_msgobject *o, int code, void *ud, int64_t offset, pa_memchunk *chunk) {
    cmtspeech_handler *h = CMTSPEECH_HANDLER(o);
    struct userdata *u;

    cmtspeech_handler_assert_ref(h);
    pa_assert_se(u = h->u);

    switch (code) {
        case CMTSPEECH_HANDLER_CLOSE_CONNECTION:
            pa_log_debug("CMTSPEECH_HANDLER_CLOSE_CONNECTION");
            close_cmtspeech_on_error(u);
            return 0;
        default:
            pa_log_error("Unknown message code %d", code);
            return -1;
    }
}

static pa_msgobject *cmtspeech_handler_new(struct userdata *u) {
    cmtspeech_handler *h;

    pa_assert(u);
    pa_assert(u->core);
    pa_assert_se(h = pa_msgobject_new(cmtspeech_handler));

    h->parent.parent.free = cmtspeech_handler_free;
    h->parent.process_msg = cmtspeech_handler_process_msg;
    h->u = u;

    return (pa_msgobject *)h;
}

/* This is usually called from sink IO-thread */
static void cmtspeech_free_cb(void *p) {
    cmtspeech_t *cmtspeech;

    if (!p)
        return;

    if (!userdata) {
        pa_log_error("userdata not set, cmtspeech buffer %p was not freed!", p);
        return;
    }

    pa_mutex_lock(userdata->cmt_connection.cmtspeech_mutex);
    cmtspeech = userdata->cmt_connection.cmtspeech;
    if (!cmtspeech) {
        pa_log_error("cmtspeech not open, cmtspeech buffer %p was not freed!", p);
    } else {
        int ret;
        cmtspeech_buffer_t *buf = cmtspeech_dl_buffer_find_with_data(cmtspeech, (uint8_t*)p);
        if (buf != NULL) {
            if ((ret = cmtspeech_dl_buffer_release(cmtspeech, buf))) {
                pa_log_error("cmtspeech_dl_buffer_release(%p) failed return value %d.", (void *)buf, ret);
            }
        } else {
            pa_log_error("cmtspeech_dl_buffer_find_with_data() returned NULL, releasing buffer failed.");
        }
    }
    pa_mutex_unlock(userdata->cmt_connection.cmtspeech_mutex);
}

/* Called from sink IO-thread */
/* NOTE: If you ever see a seqfault when accessing these libcmtspeechdata owned
 * memblocks, then just free the cmtframes here after coping them to regular
 * pa_memblocks. The performance penalty should not be too severe. */
int cmtspeech_buffer_to_memchunk(struct userdata *u, cmtspeech_buffer_t *buf, pa_memchunk *chunk) {
    pa_assert_fp(u);
    pa_assert_fp(chunk);
    pa_assert_fp(buf);

    if (!buf->data) {
        pa_log_warn("No data in cmtspeech_buffer");
        if (cmtspeech_dl_buffer_release(u->cmt_connection.cmtspeech, buf))
            pa_log_warn("cmtspeech_dl_buffer_release() failed");
        return -1;
    }

    chunk->memblock = pa_memblock_new_user(u->core->mempool, buf->data, (size_t) buf->size, cmtspeech_free_cb, buf->data, true);
    chunk->index = CMTSPEECH_DATA_HEADER_LEN;
    chunk->length = buf->count - CMTSPEECH_DATA_HEADER_LEN;

    return 0;
}

/* cmtspeech thread */
static inline
int push_cmtspeech_buffer_to_dl_queue(struct userdata *u, cmtspeech_dl_buf_t *buf) {
    pa_assert_fp(u);
    pa_assert_fp(buf);

    if (pa_asyncq_push(u->cmt_connection.dl_frame_queue, (void *)buf, false)) {
        int ret;
        struct cmtspeech_connection *c = &u->cmt_connection;

        pa_log_error("Failed to push dl frame to asyncq");
        pa_mutex_lock(c->cmtspeech_mutex);
        if ((ret = cmtspeech_dl_buffer_release(u->cmt_connection.cmtspeech, buf)))
{'fraction_non_alphanumeric': 0.09889240506329114, 'fraction_numerical': 0.005274261603375527, 'mean_word_length': 3.7463496036712556, 'pattern_counts': {'":': 0, '<': 31, '<?xml version=': 0, '>': 76, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1541817', 'n_tokens_mistral': 4131, 'n_tokens_neox': 4044, 'n_words': 943}