media/audioipc/client/src/lib.rs
author Dorel Luca <dluca@mozilla.com>
Wed, 06 Mar 2019 23:28:37 +0200
changeset 462707 873b90887e3af682383dea7a7e1fb52d6ec02960
parent 462696 0a78b7e72e1bf620cd70608abb7f31f389f87fcc
child 462806 25eb307eb4edf93cd6ec84f97d51aa5547cb2991
permissions -rw-r--r--
Backed out 3 changesets (bug 1512445) Build bustage Backed out changeset b954e5d0324a (bug 1512445) Backed out changeset 04c1982c1a7e (bug 1512445) Backed out changeset 0a78b7e72e1b (bug 1512445)

// Copyright © 2017 Mozilla Foundation
//
// This program is made available under an ISC-style license.  See the
// accompanying file LICENSE for details.

extern crate audioipc;
#[macro_use]
extern crate cubeb_backend;
extern crate foreign_types;
extern crate futures;
extern crate futures_cpupool;
extern crate libc;
#[macro_use]
extern crate log;
extern crate tokio_core;
extern crate tokio_uds;

#[macro_use]
mod send_recv;
mod context;
mod stream;

use audioipc::PlatformHandleType;
use context::ClientContext;
use cubeb_backend::{capi, ffi};
use std::os::raw::{c_char, c_int};
use std::os::unix::io::RawFd;
use stream::ClientStream;

type InitParamsTls = std::cell::RefCell<Option<CpuPoolInitParams>>;

thread_local!(static IN_CALLBACK: std::cell::RefCell<bool> = std::cell::RefCell::new(false));
thread_local!(static CPUPOOL_INIT_PARAMS: InitParamsTls = std::cell::RefCell::new(None));

// This must match the definition of AudioIpcInitParams in
// dom/media/CubebUtils.cpp in Gecko.
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct AudioIpcInitParams {
    // Fields only need to be public for ipctest.
    pub server_connection: PlatformHandleType,
    pub pool_size: usize,
    pub stack_size: usize,
    pub thread_create_callback: Option<extern "C" fn(*const ::std::os::raw::c_char)>,
}

#[derive(Clone, Copy, Debug)]
struct CpuPoolInitParams {
    pool_size: usize,
    stack_size: usize,
    thread_create_callback: Option<extern "C" fn(*const ::std::os::raw::c_char)>,
}

impl CpuPoolInitParams {
    fn init_with(params: &AudioIpcInitParams) -> Self {
        CpuPoolInitParams {
            pool_size: params.pool_size,
            stack_size: params.stack_size,
            thread_create_callback: params.thread_create_callback,
        }
    }
}

fn set_in_callback(in_callback: bool) {
    IN_CALLBACK.with(|b| {
        assert_eq!(*b.borrow(), !in_callback);
        *b.borrow_mut() = in_callback;
    });
}

fn assert_not_in_callback() {
    IN_CALLBACK.with(|b| {
        assert_eq!(*b.borrow(), false);
    });
}

fn set_cpupool_init_params<P>(params: P)
where
    P: Into<Option<CpuPoolInitParams>>,
{
    CPUPOOL_INIT_PARAMS.with(|p| {
        *p.borrow_mut() = params.into();
    });
}

static mut G_SERVER_FD: Option<RawFd> = None;

#[no_mangle]
/// Entry point from C code.
pub unsafe extern "C" fn audioipc_client_init(
    c: *mut *mut ffi::cubeb,
    context_name: *const c_char,
    init_params: *const AudioIpcInitParams,
) -> c_int {
    if init_params.is_null() {
        return cubeb_backend::ffi::CUBEB_ERROR;
    }

    let init_params = &*init_params;

    // TODO: Windows portability (for fd).
    // TODO: Better way to pass extra parameters to Context impl.
    if G_SERVER_FD.is_some() {
        panic!("audioipc client's server connection already initialized.");
    }
    if init_params.server_connection >= 0 {
        G_SERVER_FD = Some(init_params.server_connection);
    }

    let cpupool_init_params = CpuPoolInitParams::init_with(&init_params);
    set_cpupool_init_params(cpupool_init_params);
    capi::capi_init::<ClientContext>(c, context_name)
}