New upstream version 26.1.0+dfsg1
This commit is contained in:
parent
040dcc3fc2
commit
013818c4af
594 changed files with 19576 additions and 4478 deletions
35
plugins/sndio/CMakeLists.txt
Normal file
35
plugins/sndio/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
project(sndio)
|
||||
|
||||
if(DISABLE_SNDIO)
|
||||
message(STATUS "Sndio support disabled")
|
||||
return()
|
||||
endif()
|
||||
|
||||
find_package(Sndio)
|
||||
if(NOT Sndio_FOUND AND ENABLE_SNDIO)
|
||||
message(FATAL_ERROR "Sndio not found but set as enabled")
|
||||
elseif(NOT Sndio_FOUND)
|
||||
message(STATUS "Sndio not found, disabling Sndio plugin")
|
||||
return()
|
||||
endif()
|
||||
|
||||
include_directories(
|
||||
SYSTEM "${CMAKE_SOURCE_DIR}/libobs" SYSTEM "${CMAKE_SOURCE_DIR}/../../libobs"
|
||||
${Sndio_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
set(sndio_SOURCES
|
||||
sndio.c
|
||||
sndio-input.c
|
||||
)
|
||||
|
||||
add_library(sndio MODULE
|
||||
${sndio_SOURCES}
|
||||
)
|
||||
target_link_libraries(sndio
|
||||
libobs
|
||||
${Sndio_LIBRARIES}
|
||||
)
|
||||
set_target_properties(sndio PROPERTIES FOLDER "plugins")
|
||||
|
||||
install_obs_plugin_with_data(sndio data)
|
||||
6
plugins/sndio/data/locale/ar-SA.ini
Normal file
6
plugins/sndio/data/locale/ar-SA.ini
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
Channels="عدد القنوات"
|
||||
Device="جهاز"
|
||||
BitsPerSample="بت لكل عينة"
|
||||
Rate="معدل"
|
||||
|
||||
|
||||
7
plugins/sndio/data/locale/ca-ES.ini
Normal file
7
plugins/sndio/data/locale/ca-ES.ini
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
Channels="Número de canals"
|
||||
Device="Dispositiu"
|
||||
BitsPerSample="Bits per mostra"
|
||||
Rate="Taxa"
|
||||
SndioInput="Client d’entrada Sndio"
|
||||
|
||||
|
||||
7
plugins/sndio/data/locale/cs-CZ.ini
Normal file
7
plugins/sndio/data/locale/cs-CZ.ini
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
Channels="Počet kanálů"
|
||||
Device="Zařízení"
|
||||
BitsPerSample="Bitů na vzorek"
|
||||
Rate="Frekvence"
|
||||
SndioInput="Sndio klient"
|
||||
|
||||
|
||||
7
plugins/sndio/data/locale/da-DK.ini
Normal file
7
plugins/sndio/data/locale/da-DK.ini
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
Channels="Antal kanaler"
|
||||
Device="Enhed"
|
||||
BitsPerSample="Bits pr. sample"
|
||||
Rate="Hastighed"
|
||||
SndioInput="Sndio-inputklient"
|
||||
|
||||
|
||||
7
plugins/sndio/data/locale/de-DE.ini
Normal file
7
plugins/sndio/data/locale/de-DE.ini
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
Channels="Anzahl der Kanäle"
|
||||
Device="Gerät"
|
||||
BitsPerSample="Bits pro Sample"
|
||||
Rate="Rate"
|
||||
SndioInput="Sndio-Eingabeclient"
|
||||
|
||||
|
||||
6
plugins/sndio/data/locale/el-GR.ini
Normal file
6
plugins/sndio/data/locale/el-GR.ini
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
Channels="Αριθμός καναλιών"
|
||||
Device="Συσκευή"
|
||||
BitsPerSample="Bits ανά δείγμα"
|
||||
Rate="Ρυθμός"
|
||||
|
||||
|
||||
7
plugins/sndio/data/locale/en-GB.ini
Normal file
7
plugins/sndio/data/locale/en-GB.ini
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
Channels="Number of channels"
|
||||
Device="Device"
|
||||
BitsPerSample="Bits per sample"
|
||||
Rate="Rate"
|
||||
SndioInput="Sndio input client"
|
||||
|
||||
|
||||
6
plugins/sndio/data/locale/en-US.ini
Normal file
6
plugins/sndio/data/locale/en-US.ini
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
Channels="Number of channels"
|
||||
Device="Device"
|
||||
BitsPerSample="Bits per sample"
|
||||
Rate="Rate"
|
||||
SndioInput="Sndio input client"
|
||||
|
||||
7
plugins/sndio/data/locale/es-ES.ini
Normal file
7
plugins/sndio/data/locale/es-ES.ini
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
Channels="Número de canales"
|
||||
Device="Dispositivo"
|
||||
BitsPerSample="Bits por muestra"
|
||||
Rate="Tasa"
|
||||
SndioInput="Cliente de entrada Sndio"
|
||||
|
||||
|
||||
7
plugins/sndio/data/locale/et-EE.ini
Normal file
7
plugins/sndio/data/locale/et-EE.ini
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
Channels="Kanalite arv"
|
||||
Device="Seade"
|
||||
BitsPerSample="Bitti proovi"
|
||||
Rate="Hinnang"
|
||||
SndioInput="Sndio sisendklient"
|
||||
|
||||
|
||||
7
plugins/sndio/data/locale/fa-IR.ini
Normal file
7
plugins/sndio/data/locale/fa-IR.ini
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
Channels="تعداد کانال ها"
|
||||
Device="دستگاه"
|
||||
BitsPerSample="بیت در هر نمونه"
|
||||
Rate="نرخ"
|
||||
SndioInput="کلاینت ورودی Sndio"
|
||||
|
||||
|
||||
7
plugins/sndio/data/locale/fi-FI.ini
Normal file
7
plugins/sndio/data/locale/fi-FI.ini
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
Channels="Kanavien määrä"
|
||||
Device="Laite"
|
||||
BitsPerSample="Bittiä per näyte"
|
||||
Rate="Näytteenottotaajuus"
|
||||
SndioInput="Sndio sisääntulon asiakas"
|
||||
|
||||
|
||||
7
plugins/sndio/data/locale/fr-FR.ini
Normal file
7
plugins/sndio/data/locale/fr-FR.ini
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
Channels="Nombre de canaux"
|
||||
Device="Appareil"
|
||||
BitsPerSample="Bits par échantillon"
|
||||
Rate="Taux"
|
||||
SndioInput="Entrée client Sndio"
|
||||
|
||||
|
||||
7
plugins/sndio/data/locale/gl-ES.ini
Normal file
7
plugins/sndio/data/locale/gl-ES.ini
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
Channels="Número de canles"
|
||||
Device="Dispositivo"
|
||||
BitsPerSample="Bits por mostra"
|
||||
Rate="Taxa"
|
||||
SndioInput="Cliente de entrada «sndio»"
|
||||
|
||||
|
||||
4
plugins/sndio/data/locale/hu-HU.ini
Normal file
4
plugins/sndio/data/locale/hu-HU.ini
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
Channels="Csatornák száma"
|
||||
Device="Eszköz"
|
||||
|
||||
|
||||
7
plugins/sndio/data/locale/id-ID.ini
Normal file
7
plugins/sndio/data/locale/id-ID.ini
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
Channels="Jumlah saluran"
|
||||
Device="Perangkat"
|
||||
BitsPerSample="Bit per sampel"
|
||||
Rate="Nilai"
|
||||
SndioInput="Input klien Sndio"
|
||||
|
||||
|
||||
7
plugins/sndio/data/locale/it-IT.ini
Normal file
7
plugins/sndio/data/locale/it-IT.ini
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
Channels="Numero di canali"
|
||||
Device="Dispositivo"
|
||||
BitsPerSample="Bit per campione"
|
||||
Rate="Velocità"
|
||||
SndioInput="Client di ingresso sndio"
|
||||
|
||||
|
||||
7
plugins/sndio/data/locale/ja-JP.ini
Normal file
7
plugins/sndio/data/locale/ja-JP.ini
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
Channels="チャネル数"
|
||||
Device="デバイス"
|
||||
BitsPerSample="ビット毎サンプル"
|
||||
Rate="レート"
|
||||
SndioInput="Sndio入力クライアント"
|
||||
|
||||
|
||||
7
plugins/sndio/data/locale/ka-GE.ini
Normal file
7
plugins/sndio/data/locale/ka-GE.ini
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
Channels="არხების რაოდენობა"
|
||||
Device="მოწყობილობა"
|
||||
BitsPerSample="ბიტი დანაყოფში"
|
||||
Rate="სიხშირე"
|
||||
SndioInput="Sndio-შეტანის კლიენტი"
|
||||
|
||||
|
||||
7
plugins/sndio/data/locale/kab-KAB.ini
Normal file
7
plugins/sndio/data/locale/kab-KAB.ini
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
Channels="Amḍan n ibuda"
|
||||
Device="Ibenk"
|
||||
BitsPerSample="Ibiten i tlemmict"
|
||||
Rate="Atug"
|
||||
SndioInput="Anekcum Sndio n umsaɣ"
|
||||
|
||||
|
||||
7
plugins/sndio/data/locale/ko-KR.ini
Normal file
7
plugins/sndio/data/locale/ko-KR.ini
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
Channels="채널 수"
|
||||
Device="장치"
|
||||
BitsPerSample="샘플 당 비트 수"
|
||||
Rate="샘플링 레이트"
|
||||
SndioInput="입력 클라이언트"
|
||||
|
||||
|
||||
7
plugins/sndio/data/locale/nl-NL.ini
Normal file
7
plugins/sndio/data/locale/nl-NL.ini
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
Channels="Aantal kanalen"
|
||||
Device="Apparaat"
|
||||
BitsPerSample="Bits per sample"
|
||||
Rate="Rate"
|
||||
SndioInput="Sndio input client"
|
||||
|
||||
|
||||
7
plugins/sndio/data/locale/pl-PL.ini
Normal file
7
plugins/sndio/data/locale/pl-PL.ini
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
Channels="Liczba kanałów"
|
||||
Device="Urządzenie"
|
||||
BitsPerSample="Bity na próbkę"
|
||||
Rate="Częstotliwość próbkowania"
|
||||
SndioInput="Klient Sndio - wejście"
|
||||
|
||||
|
||||
7
plugins/sndio/data/locale/pt-BR.ini
Normal file
7
plugins/sndio/data/locale/pt-BR.ini
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
Channels="Número de canais"
|
||||
Device="Dispositivo"
|
||||
BitsPerSample="Bits por amostra"
|
||||
Rate="Taxa"
|
||||
SndioInput="Cliente de inserção sndio"
|
||||
|
||||
|
||||
5
plugins/sndio/data/locale/pt-PT.ini
Normal file
5
plugins/sndio/data/locale/pt-PT.ini
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
Channels="Número de canais"
|
||||
Device="Dispositivo"
|
||||
BitsPerSample="Bits por amostra"
|
||||
|
||||
|
||||
7
plugins/sndio/data/locale/ru-RU.ini
Normal file
7
plugins/sndio/data/locale/ru-RU.ini
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
Channels="Количество каналов"
|
||||
Device="Устройство"
|
||||
BitsPerSample="Биты на образец"
|
||||
Rate="Ставка"
|
||||
SndioInput="Клиент ввода Sndio"
|
||||
|
||||
|
||||
7
plugins/sndio/data/locale/sk-SK.ini
Normal file
7
plugins/sndio/data/locale/sk-SK.ini
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
Channels="Počet kanálov"
|
||||
Device="Zariadenie"
|
||||
BitsPerSample="Bitov na vzorku"
|
||||
Rate="Frekvencia"
|
||||
SndioInput="Sndio klient vstupu"
|
||||
|
||||
|
||||
7
plugins/sndio/data/locale/sl-SI.ini
Normal file
7
plugins/sndio/data/locale/sl-SI.ini
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
Channels="Število kanalov"
|
||||
Device="Naprava"
|
||||
BitsPerSample="Bitov na vzorec"
|
||||
Rate="Stopnja"
|
||||
SndioInput="Vhodni zvočni odjemalec"
|
||||
|
||||
|
||||
7
plugins/sndio/data/locale/sv-SE.ini
Normal file
7
plugins/sndio/data/locale/sv-SE.ini
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
Channels="Antal kanaler"
|
||||
Device="Enhet"
|
||||
BitsPerSample="Bitar per sampling"
|
||||
Rate="Hastighet"
|
||||
SndioInput="Sndio-inmatningsklient"
|
||||
|
||||
|
||||
7
plugins/sndio/data/locale/tr-TR.ini
Normal file
7
plugins/sndio/data/locale/tr-TR.ini
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
Channels="Kanal sayısı"
|
||||
Device="Aygıt"
|
||||
BitsPerSample="Örnek başına bit"
|
||||
Rate="Oran"
|
||||
SndioInput="Sndio giriş istemcisi"
|
||||
|
||||
|
||||
7
plugins/sndio/data/locale/uk-UA.ini
Normal file
7
plugins/sndio/data/locale/uk-UA.ini
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
Channels="Кількість каналів"
|
||||
Device="Пристрій"
|
||||
BitsPerSample="Біт на зразок"
|
||||
Rate="Частота"
|
||||
SndioInput="Клієнт введення Sndio"
|
||||
|
||||
|
||||
7
plugins/sndio/data/locale/zh-CN.ini
Normal file
7
plugins/sndio/data/locale/zh-CN.ini
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
Channels="通道数量"
|
||||
Device="设备"
|
||||
BitsPerSample="采样位数"
|
||||
Rate="采样率"
|
||||
SndioInput="Sndio 输入端"
|
||||
|
||||
|
||||
7
plugins/sndio/data/locale/zh-TW.ini
Normal file
7
plugins/sndio/data/locale/zh-TW.ini
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
Channels="聲道數目"
|
||||
Device="裝置"
|
||||
BitsPerSample="每樣本位元"
|
||||
Rate="頻率"
|
||||
SndioInput="Sndio 輸入裝置"
|
||||
|
||||
|
||||
418
plugins/sndio/sndio-input.c
Normal file
418
plugins/sndio/sndio-input.c
Normal file
|
|
@ -0,0 +1,418 @@
|
|||
/*
|
||||
Copyright (C) 2020 by Vadim Zhukov <zhuk@openbsd.org>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <errno.h>
|
||||
#include <poll.h>
|
||||
#include <pthread.h>
|
||||
#include <sndio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <util/bmem.h>
|
||||
#include <util/platform.h>
|
||||
#include <util/threading.h>
|
||||
#include <util/util_uint64.h>
|
||||
#include <obs.h>
|
||||
#include <obs-module.h>
|
||||
|
||||
#include "sndio-input.h"
|
||||
|
||||
#define blog(level, msg, ...) \
|
||||
blog(level, "sndio-input: %s: " msg, __func__, ##__VA_ARGS__);
|
||||
|
||||
#define berr(level, msg, ...) \
|
||||
do { \
|
||||
const char *errstr = strerror(errno); \
|
||||
blog(level, msg ": %s", ##__VA_ARGS__, errstr); \
|
||||
} while (0)
|
||||
|
||||
#define NSEC_PER_SEC 1000000000LL
|
||||
|
||||
/**
|
||||
* Returns the name of the plugin
|
||||
*/
|
||||
static const char *sndio_input_getname(void *unused)
|
||||
{
|
||||
UNUSED_PARAMETER(unused);
|
||||
return obs_module_text("SndioInput");
|
||||
}
|
||||
|
||||
static enum speaker_layout sndio_channels_to_obs_speakers(int channels)
|
||||
{
|
||||
switch (channels) {
|
||||
case 1:
|
||||
return SPEAKERS_MONO;
|
||||
case 2:
|
||||
return SPEAKERS_STEREO;
|
||||
case 3:
|
||||
return SPEAKERS_2POINT1;
|
||||
case 4:
|
||||
return SPEAKERS_4POINT0;
|
||||
case 5:
|
||||
return SPEAKERS_4POINT1;
|
||||
case 6:
|
||||
return SPEAKERS_5POINT1;
|
||||
case 8:
|
||||
return SPEAKERS_7POINT1;
|
||||
}
|
||||
return SPEAKERS_UNKNOWN;
|
||||
}
|
||||
|
||||
static enum audio_format sndio_to_obs_audio_format(const struct sio_par *par)
|
||||
{
|
||||
switch (par->bits) {
|
||||
case 8:
|
||||
return AUDIO_FORMAT_U8BIT;
|
||||
case 16:
|
||||
return AUDIO_FORMAT_16BIT;
|
||||
case 32:
|
||||
return AUDIO_FORMAT_32BIT;
|
||||
}
|
||||
return AUDIO_FORMAT_UNKNOWN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs sndio tasks on a pre-opened audio device.
|
||||
* Whenever user chooses another device, this thread gets signalled to exit,
|
||||
* and another one starts immediately, without waiting for the previous.
|
||||
*/
|
||||
static void *sndio_thread(void *attr)
|
||||
{
|
||||
struct sndio_thr_data *thrdata = attr;
|
||||
size_t msgread = 0; // msg bytes read from socket
|
||||
size_t nsiofds = sio_nfds(thrdata->hdl);
|
||||
struct pollfd pfd[1 + nsiofds];
|
||||
struct sio_par par;
|
||||
uint64_t ts;
|
||||
ssize_t nread;
|
||||
int pollres;
|
||||
uint8_t *buf;
|
||||
size_t bufsz;
|
||||
|
||||
ts = os_gettime_ns();
|
||||
|
||||
bufsz = thrdata->par.appbufsz * thrdata->par.bps * 2;
|
||||
if ((buf = bmalloc(bufsz * 2)) == NULL) {
|
||||
blog(LOG_ERROR, "could not allocate record buffer of %zu bytes",
|
||||
bufsz);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
memset(pfd, 0, sizeof(pfd));
|
||||
pfd[0].fd = thrdata->sock;
|
||||
|
||||
for (;;) {
|
||||
for (size_t i = 0; i <= nsiofds; i++)
|
||||
pfd[i].revents = 0;
|
||||
pfd[0].events = POLLIN;
|
||||
sio_pollfd(thrdata->hdl, pfd + 1, POLLIN);
|
||||
|
||||
if (poll(pfd, 1 + nsiofds, /*INFTIM*/ -1) == -1) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
berr(LOG_ERROR, "exiting due to poll error");
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if ((pfd[0].revents & POLLHUP) == POLLHUP) {
|
||||
blog(LOG_INFO,
|
||||
"exiting upon receiving EOF at IPC socket");
|
||||
goto finish;
|
||||
}
|
||||
if ((pfd[0].revents & POLLIN) == POLLIN) {
|
||||
nread = read(pfd[0].fd, ((uint8_t *)&par) + msgread,
|
||||
sizeof(par) - msgread);
|
||||
switch (nread) {
|
||||
case -1:
|
||||
if (errno == EAGAIN)
|
||||
goto proceed_sio;
|
||||
berr(LOG_ERROR,
|
||||
"reading from IPC socket failed");
|
||||
goto finish;
|
||||
|
||||
case 0:
|
||||
blog(LOG_INFO,
|
||||
"exiting upon receiving EOF at IPC socket");
|
||||
goto finish;
|
||||
|
||||
default:
|
||||
msgread += (size_t)nread;
|
||||
if (msgread == sizeof(struct sio_par)) {
|
||||
size_t tbufsz;
|
||||
uint8_t *tbuf;
|
||||
|
||||
msgread = 0;
|
||||
sio_stop(thrdata->hdl);
|
||||
if (!sio_setpar(thrdata->hdl, &par)) {
|
||||
blog(LOG_WARNING,
|
||||
"sio_setpar failed, keeping old params");
|
||||
}
|
||||
blog(LOG_INFO,
|
||||
"after sio_setpar(): appbufsz=%u bps=%u",
|
||||
par.appbufsz, par.bps);
|
||||
memcpy(&thrdata->par, &par,
|
||||
sizeof(struct sio_par));
|
||||
|
||||
tbufsz = thrdata->par.appbufsz *
|
||||
thrdata->par.bps * 2;
|
||||
if ((tbuf = brealloc(buf, tbufsz)) ==
|
||||
NULL) {
|
||||
blog(LOG_ERROR,
|
||||
"could not reallocate record buffer of %zu bytes",
|
||||
tbufsz);
|
||||
goto finish;
|
||||
}
|
||||
buf = tbuf;
|
||||
bufsz = tbufsz;
|
||||
|
||||
if (!sio_start(thrdata->hdl)) {
|
||||
blog(LOG_ERROR,
|
||||
"sio_start failed, exiting");
|
||||
goto finish;
|
||||
}
|
||||
ts = os_gettime_ns();
|
||||
// Since we restarted recording,
|
||||
// do not try to handle events we lost.
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
proceed_sio:
|
||||
pollres = sio_revents(thrdata->hdl, pfd + 1);
|
||||
if ((pollres & POLLHUP) == POLLHUP) {
|
||||
blog(LOG_ERROR, "sndio device error happened, exiting");
|
||||
goto finish;
|
||||
}
|
||||
if ((pollres & POLLIN) == POLLIN) {
|
||||
struct obs_source_audio out;
|
||||
unsigned int nframes;
|
||||
|
||||
nread = (ssize_t)sio_read(thrdata->hdl, buf, bufsz);
|
||||
if (nread == 0) {
|
||||
if (sio_eof(thrdata->hdl)) {
|
||||
blog(LOG_ERROR,
|
||||
"sndio device EOF happened, exiting");
|
||||
goto finish;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
nframes = (unsigned int)nread / thrdata->par.bps;
|
||||
//blog(LOG_INFO, "sio_read returned %u, nframes = %u", nread, nframes);
|
||||
|
||||
memset(&out, 0, sizeof(struct obs_source_audio));
|
||||
out.data[0] = buf;
|
||||
out.frames = nframes;
|
||||
out.format = sndio_to_obs_audio_format(&thrdata->par);
|
||||
out.speakers = sndio_channels_to_obs_speakers(
|
||||
thrdata->par.rchan);
|
||||
out.samples_per_sec = thrdata->par.rate;
|
||||
out.timestamp = ts;
|
||||
|
||||
ts += util_mul_div64(nframes, NSEC_PER_SEC,
|
||||
thrdata->par.rate);
|
||||
|
||||
obs_source_output_audio(thrdata->source, &out);
|
||||
}
|
||||
}
|
||||
|
||||
finish:
|
||||
sio_close(thrdata->hdl);
|
||||
close(thrdata->sock);
|
||||
bfree(buf);
|
||||
bfree(thrdata);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy the plugin object and free all memory
|
||||
*/
|
||||
static void sndio_destroy(void *vptr)
|
||||
{
|
||||
struct sndio_data *data = vptr;
|
||||
|
||||
if (!data)
|
||||
return;
|
||||
close(data->sock);
|
||||
data->sock = -1;
|
||||
pthread_attr_destroy(&data->attr);
|
||||
bfree(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to apply the input settings.
|
||||
* Must be called on stopped device.
|
||||
*/
|
||||
static void sndio_apply(struct sndio_data *data, obs_data_t *settings)
|
||||
{
|
||||
struct sndio_thr_data *thrdata;
|
||||
pthread_t thread;
|
||||
int ec;
|
||||
int socks[2] = {-1, -1};
|
||||
const char *devname = obs_data_get_string(settings, "device");
|
||||
|
||||
if ((thrdata = bzalloc(sizeof(struct sndio_thr_data))) == NULL) {
|
||||
blog(LOG_ERROR, "malloc");
|
||||
return;
|
||||
}
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0,
|
||||
socks) == -1) {
|
||||
berr(LOG_ERROR, "socketpair");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (data->sock != -1)
|
||||
close(data->sock);
|
||||
data->sock = socks[0];
|
||||
thrdata->sock = socks[1];
|
||||
thrdata->source = data->source;
|
||||
|
||||
thrdata->hdl = sio_open(devname, SIO_REC, 0);
|
||||
if (!thrdata->hdl) {
|
||||
berr(LOG_ERROR, "could not open %s sndio device", devname);
|
||||
goto error;
|
||||
}
|
||||
|
||||
sio_initpar(&thrdata->par);
|
||||
thrdata->par.bits = obs_data_get_int(settings, "bits");
|
||||
thrdata->par.bps = SIO_BPS(thrdata->par.bits);
|
||||
thrdata->par.sig = thrdata->par.bits > 8;
|
||||
thrdata->par.le = 1;
|
||||
thrdata->par.rate = obs_data_get_int(settings, "rate");
|
||||
thrdata->par.rchan = obs_data_get_int(settings, "channels");
|
||||
thrdata->par.xrun = SIO_SYNC; // makes timestamping easy
|
||||
if (!sio_setpar(thrdata->hdl, &thrdata->par)) {
|
||||
berr(LOG_ERROR, "could not set parameters for %s sndio device",
|
||||
devname);
|
||||
goto error;
|
||||
}
|
||||
blog(LOG_INFO, "after initial sio_setpar(): appbufsz=%u bps=%u",
|
||||
thrdata->par.appbufsz, thrdata->par.bps);
|
||||
|
||||
if (!sio_start(thrdata->hdl)) {
|
||||
berr(LOG_ERROR, "could not start recording on %s sndio device",
|
||||
devname);
|
||||
goto error;
|
||||
}
|
||||
|
||||
ec = pthread_create(&thread, &data->attr, sndio_thread, thrdata);
|
||||
if (ec != 0) {
|
||||
blog(LOG_ERROR, "could not start thread");
|
||||
goto error;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
error:
|
||||
if (thrdata->hdl != NULL)
|
||||
sio_close(thrdata->hdl);
|
||||
close(socks[0]);
|
||||
close(socks[1]);
|
||||
bfree(thrdata);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the input settings.
|
||||
*/
|
||||
static void sndio_update(void *vptr, obs_data_t *settings)
|
||||
{
|
||||
struct sndio_data *data = vptr;
|
||||
sndio_apply(data, settings);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the plugin object
|
||||
*/
|
||||
static void *sndio_create(obs_data_t *settings, obs_source_t *source)
|
||||
{
|
||||
struct sndio_data *data = bzalloc(sizeof(struct sndio_data));
|
||||
pthread_attr_init(&data->attr);
|
||||
pthread_attr_setdetachstate(&data->attr, PTHREAD_CREATE_DETACHED);
|
||||
data->source = source;
|
||||
data->sock = -1;
|
||||
sndio_apply(data, settings);
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get plugin defaults
|
||||
*/
|
||||
static void sndio_input_defaults(obs_data_t *settings)
|
||||
{
|
||||
obs_data_set_default_string(settings, "device", SIO_DEVANY);
|
||||
obs_data_set_default_int(settings, "rate", 48000);
|
||||
obs_data_set_default_int(settings, "bits", 16);
|
||||
obs_data_set_default_int(settings, "channels", 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get plugin properties
|
||||
*/
|
||||
static obs_properties_t *sndio_input_properties(void *unused)
|
||||
{
|
||||
obs_property_t *rate, *bits;
|
||||
|
||||
UNUSED_PARAMETER(unused);
|
||||
|
||||
obs_properties_t *props = obs_properties_create();
|
||||
|
||||
obs_properties_add_text(props, "device", obs_module_text("Device"),
|
||||
OBS_TEXT_DEFAULT);
|
||||
|
||||
rate = obs_properties_add_list(props, "rate", obs_module_text("Rate"),
|
||||
OBS_COMBO_TYPE_LIST,
|
||||
OBS_COMBO_FORMAT_INT);
|
||||
obs_property_list_add_int(rate, "11025 Hz", 11025);
|
||||
obs_property_list_add_int(rate, "22050 Hz", 22050);
|
||||
obs_property_list_add_int(rate, "32000 Hz", 32000);
|
||||
obs_property_list_add_int(rate, "44100 Hz", 44100);
|
||||
obs_property_list_add_int(rate, "48000 Hz", 48000);
|
||||
obs_property_list_add_int(rate, "96000 Hz", 96000);
|
||||
obs_property_list_add_int(rate, "192000 Hz", 192000);
|
||||
|
||||
bits = obs_properties_add_list(props, "bits",
|
||||
obs_module_text("BitsPerSample"),
|
||||
OBS_COMBO_TYPE_LIST,
|
||||
OBS_COMBO_FORMAT_INT);
|
||||
obs_property_list_add_int(bits, "8", 8);
|
||||
obs_property_list_add_int(bits, "16", 16);
|
||||
obs_property_list_add_int(bits, "32", 32);
|
||||
|
||||
obs_properties_add_int(props, "channels", obs_module_text("Channels"),
|
||||
1, 8, 1);
|
||||
|
||||
return props;
|
||||
}
|
||||
|
||||
struct obs_source_info sndio_output_capture = {
|
||||
.id = "sndio_output_capture",
|
||||
.type = OBS_SOURCE_TYPE_INPUT,
|
||||
.output_flags = OBS_SOURCE_AUDIO,
|
||||
.get_name = sndio_input_getname,
|
||||
.create = sndio_create,
|
||||
.destroy = sndio_destroy,
|
||||
#if SHUTDOWN_ON_DEACTIVATE
|
||||
.activate = sndio_activate,
|
||||
.deactivate = sndio_deactivate,
|
||||
#endif
|
||||
.update = sndio_update,
|
||||
.get_defaults = sndio_input_defaults,
|
||||
.get_properties = sndio_input_properties,
|
||||
.icon_type = OBS_ICON_TYPE_AUDIO_OUTPUT,
|
||||
};
|
||||
18
plugins/sndio/sndio-input.h
Normal file
18
plugins/sndio/sndio-input.h
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
#ifndef OBS_SNDIO_INPUT_H
|
||||
#define OBS_SNDIO_INPUT_H
|
||||
|
||||
struct sndio_thr_data {
|
||||
obs_source_t *source;
|
||||
struct obs_source_audio out;
|
||||
struct sio_hdl *hdl;
|
||||
struct sio_par par;
|
||||
int sock;
|
||||
};
|
||||
|
||||
struct sndio_data {
|
||||
obs_source_t *source;
|
||||
pthread_attr_t attr;
|
||||
int sock;
|
||||
};
|
||||
|
||||
#endif // OBS_SNDIO_INPUT_H
|
||||
32
plugins/sndio/sndio.c
Normal file
32
plugins/sndio/sndio.c
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
Copyright (C) 2020 by Vadim Zhukov <zhuk@openbsd.org>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <obs-module.h>
|
||||
|
||||
OBS_DECLARE_MODULE()
|
||||
OBS_MODULE_USE_DEFAULT_LOCALE("sndio", "en-US")
|
||||
MODULE_EXPORT const char *obs_module_description(void)
|
||||
{
|
||||
return "sndio output capture";
|
||||
}
|
||||
|
||||
extern struct obs_source_info sndio_output_capture;
|
||||
|
||||
bool obs_module_load(void)
|
||||
{
|
||||
obs_register_source(&sndio_output_capture);
|
||||
return true;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue