Fuck undocumented GStreamer
This commit is contained in:
parent
4330c8f52e
commit
203164f422
|
@ -43,7 +43,6 @@
|
|||
|
||||
# Rake-compiled extension files:
|
||||
/lib/tox/tox.so
|
||||
/lib/gst-plugins-tox.so
|
||||
|
||||
# Vendored dependencies:
|
||||
/vendor/*
|
||||
|
|
|
@ -8,7 +8,7 @@ rvm:
|
|||
|
||||
before_install:
|
||||
- sudo apt-get update
|
||||
- sudo apt-get install -y yasm libconfig-dev libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev
|
||||
- sudo apt-get install -y yasm libconfig-dev
|
||||
|
||||
install: bundle install --jobs 3 --retry 3 --without examples
|
||||
|
||||
|
|
4
Gemfile
4
Gemfile
|
@ -7,10 +7,6 @@ gemspec
|
|||
|
||||
gem 'coveralls', group: :test, require: false
|
||||
|
||||
group :development, :test do
|
||||
gem 'gstreamer', '~> 3.2'
|
||||
end
|
||||
|
||||
group :examples do
|
||||
gem 'gtk3', '~> 3.2'
|
||||
end
|
||||
|
|
5
Rakefile
5
Rakefile
|
@ -54,11 +54,6 @@ begin
|
|||
ext.lib_dir = File.expand_path('lib/tox', __dir__).freeze
|
||||
ext.config_options << "--with-opt-dir=#{VENDOR_PREFIX.shellescape}"
|
||||
end
|
||||
|
||||
Rake::ExtensionTask.new 'gst-plugins-tox' do |ext|
|
||||
ext.lib_dir = File.expand_path('lib', __dir__).freeze
|
||||
ext.config_options << "--with-opt-dir=#{VENDOR_PREFIX.shellescape}"
|
||||
end
|
||||
rescue LoadError
|
||||
nil
|
||||
end
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
require 'bundler/setup'
|
||||
|
||||
require 'tox'
|
||||
require 'gst/plugins/tox'
|
||||
|
||||
# You can add fixtures and/or initialization code here to make experimenting
|
||||
# with your gem easier. You can also use a different console, if you like.
|
||||
|
|
|
@ -1,160 +0,0 @@
|
|||
#!/usr/bin/env ruby
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'bundler/setup'
|
||||
|
||||
require 'tox'
|
||||
require 'gst/plugins/tox'
|
||||
|
||||
class StreamingThread
|
||||
FILENAME = File.expand_path('test.mp3', __dir__).freeze
|
||||
|
||||
attr_reader :tox_audio_video, :friend_number
|
||||
|
||||
def initialize(tox_audio_video, friend_number)
|
||||
@tox_audio_video = tox_audio_video
|
||||
@friend_number = friend_number
|
||||
|
||||
raise unless elements.all?
|
||||
|
||||
Thread.start(&method(:call))
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def call
|
||||
bus # add loop event handler
|
||||
|
||||
pipeline.play
|
||||
main_loop.run
|
||||
ensure
|
||||
pipeline.stop
|
||||
end
|
||||
|
||||
def main_loop
|
||||
@main_loop ||= GLib::MainLoop.new
|
||||
end
|
||||
|
||||
def pipeline
|
||||
@pipeline ||= Gst::Pipeline.new.tap do |pipeline|
|
||||
elements.inject(pipeline, &:<<)
|
||||
elements.inject(&:>>)
|
||||
end
|
||||
end
|
||||
|
||||
def bus
|
||||
@bus ||= pipeline.bus.tap do |bus|
|
||||
bus.add_watch do |_bus, message|
|
||||
case message.type
|
||||
when Gst::MessageType::EOS, Gst::MessageType::ERROR
|
||||
main_loop.quit
|
||||
end
|
||||
true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def elements
|
||||
@elements ||= [
|
||||
filesrc,
|
||||
mpegaudioparse,
|
||||
mpg123audiodec,
|
||||
audioresample,
|
||||
toxaudiosink,
|
||||
].freeze
|
||||
end
|
||||
|
||||
def filesrc
|
||||
@filesrc ||= Gst::ElementFactory.make('filesrc')&.tap do |elem|
|
||||
elem.location = FILENAME
|
||||
end
|
||||
end
|
||||
|
||||
def mpegaudioparse
|
||||
@mpegaudioparse ||= Gst::ElementFactory.make 'mpegaudioparse'
|
||||
end
|
||||
|
||||
def mpg123audiodec
|
||||
@mpg123audiodec ||= Gst::ElementFactory.make 'mpg123audiodec'
|
||||
end
|
||||
|
||||
def audioresample
|
||||
@audioresample ||= Gst::ElementFactory.make 'audioresample'
|
||||
end
|
||||
|
||||
def toxaudiosink
|
||||
@toxaudiosink ||= Gst::ElementFactory.make('toxaudiosink')&.tap do |elem|
|
||||
elem.tox_av = tox_audio_video.pointer
|
||||
elem.friend_number = friend_number
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
NAME = 'GStreamerAudioSendBot'
|
||||
STATUS_MESSAGE = 'Call me'
|
||||
|
||||
AUDIO_BIT_RATE = 48
|
||||
|
||||
tox_client = Tox::Client.new
|
||||
|
||||
tox_client.name = NAME
|
||||
tox_client.status = Tox::UserStatus::NONE
|
||||
tox_client.status_message = STATUS_MESSAGE
|
||||
|
||||
puts "Address: #{tox_client.address}"
|
||||
|
||||
puts 'Connecting to the nodes from official list...'
|
||||
tox_client.bootstrap_official
|
||||
|
||||
tox_client.on_friend_request do |public_key, text|
|
||||
puts 'Friend request. Adding to contacts...'
|
||||
puts "Public key: #{public_key}"
|
||||
puts "Text: #{text.inspect}"
|
||||
puts
|
||||
|
||||
tox_client.friend_add_norequest public_key
|
||||
end
|
||||
|
||||
tox_client.audio_video.on_call do |friend_call_request|
|
||||
puts 'Friend call.'
|
||||
puts "Friend number: #{friend_call_request.friend_number}"
|
||||
puts "Audio enabled: #{friend_call_request.audio_enabled?}"
|
||||
puts "Video enabled: #{friend_call_request.video_enabled?}"
|
||||
puts
|
||||
|
||||
unless friend_call_request.audio_enabled?
|
||||
puts 'Audio disabled. Rejecting...'
|
||||
puts
|
||||
|
||||
friend_call_request.reject
|
||||
next
|
||||
end
|
||||
|
||||
friend_call_request.answer AUDIO_BIT_RATE, nil
|
||||
|
||||
StreamingThread.new(
|
||||
friend_call_request.audio_video,
|
||||
friend_call_request.friend_number,
|
||||
)
|
||||
end
|
||||
|
||||
puts 'Running. Send me friend request, I\'ll accept it immediately. ' \
|
||||
'Then call me.'
|
||||
|
||||
puts
|
||||
|
||||
Thread.start do
|
||||
loop do
|
||||
sleep tox_client.audio_video.iteration_interval
|
||||
tox_client.audio_video.iterate
|
||||
end
|
||||
end
|
||||
|
||||
begin
|
||||
loop do
|
||||
sleep tox_client.iteration_interval
|
||||
tox_client.iterate
|
||||
end
|
||||
rescue Interrupt
|
||||
nil
|
||||
end
|
|
@ -1,179 +0,0 @@
|
|||
#!/usr/bin/env ruby
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'mkmf'
|
||||
|
||||
ENV['PKG_CONFIG_PATH'] =
|
||||
File.expand_path(
|
||||
File.join('..', '..', 'vendor', 'lib', 'pkgconfig'),
|
||||
__dir__,
|
||||
).freeze
|
||||
|
||||
def cflags(*args)
|
||||
args.each do |str|
|
||||
$CFLAGS += " #{str.shellescape} "
|
||||
end
|
||||
end
|
||||
|
||||
def pkg_config!(*args)
|
||||
exit 1 unless pkg_config(*args)
|
||||
end
|
||||
|
||||
def have_library!(*args)
|
||||
exit 1 unless have_library(*args)
|
||||
end
|
||||
|
||||
def have_header!(*args)
|
||||
exit 1 unless have_header(*args)
|
||||
end
|
||||
|
||||
def have_struct_member!(header, *args)
|
||||
exit 1 unless have_struct_member(*args, header)
|
||||
end
|
||||
|
||||
def have_func!(header, *args)
|
||||
exit 1 unless have_func(*args, header)
|
||||
end
|
||||
|
||||
def have_macro!(header, *args)
|
||||
exit 1 unless have_macro(*args, header)
|
||||
end
|
||||
|
||||
def have_type!(header, *args)
|
||||
exit 1 unless have_type(*args, header)
|
||||
end
|
||||
|
||||
def have_const!(header, *args)
|
||||
exit 1 unless have_const(*args, header)
|
||||
end
|
||||
|
||||
##########
|
||||
# Common #
|
||||
##########
|
||||
|
||||
cflags '-std=c11'
|
||||
cflags '-Wall'
|
||||
cflags '-Wextra'
|
||||
cflags '-Wno-declaration-after-statement'
|
||||
|
||||
pkg_config! 'libtoxav'
|
||||
pkg_config! 'gstreamer-1.0'
|
||||
pkg_config! 'gstreamer-audio-1.0'
|
||||
|
||||
have_library! 'toxav'
|
||||
have_library! 'gstreamer-1.0'
|
||||
have_library! 'gstaudio-1.0'
|
||||
|
||||
have_header! 'tox/tox.h'
|
||||
have_header! 'gst/gst.h'
|
||||
have_header! 'gst/base/gstbasesink.h'
|
||||
have_header! 'gst/audio/gstaudiosink.h'
|
||||
|
||||
#########
|
||||
# ToxAV #
|
||||
#########
|
||||
|
||||
have_type! 'tox/toxav.h', 'TOXAV_ERR_SEND_FRAME'
|
||||
|
||||
have_func! 'tox/toxav.h', 'toxav_audio_send_frame'
|
||||
|
||||
########
|
||||
# GLib #
|
||||
########
|
||||
|
||||
have_type! 'gst/gst.h', 'gpointer'
|
||||
have_type! 'gst/gst.h', 'gboolean'
|
||||
have_type! 'gst/gst.h', 'guint'
|
||||
have_type! 'gst/gst.h', 'guint64'
|
||||
have_type! 'gst/gst.h', 'GValue'
|
||||
have_type! 'gst/gst.h', 'GObject'
|
||||
have_type! 'gst/gst.h', 'GType'
|
||||
have_type! 'gst/gst.h', 'GParamSpec'
|
||||
have_type! 'gst/gst.h', 'GObjectClass'
|
||||
|
||||
have_macro! 'gst/gst.h', 'G_TYPE_CHECK_INSTANCE_CAST'
|
||||
have_macro! 'gst/gst.h', 'G_TYPE_CHECK_CLASS_CAST'
|
||||
have_macro! 'gst/gst.h', 'G_TYPE_CHECK_INSTANCE_TYPE'
|
||||
have_macro! 'gst/gst.h', 'G_TYPE_CHECK_CLASS_TYPE'
|
||||
have_macro! 'gst/gst.h', 'G_DEFINE_TYPE'
|
||||
have_macro! 'gst/gst.h', 'G_OBJECT_WARN_INVALID_PROPERTY_ID'
|
||||
have_macro! 'gst/gst.h', 'G_OBJECT_CLASS'
|
||||
|
||||
have_const! 'gst/gst.h', 'G_PARAM_READWRITE'
|
||||
|
||||
have_struct_member! 'gst/gst.h', 'GObjectClass', 'finalize'
|
||||
have_struct_member! 'gst/gst.h', 'GObjectClass', 'get_property'
|
||||
have_struct_member! 'gst/gst.h', 'GObjectClass', 'set_property'
|
||||
|
||||
have_func! 'gst/gst.h', 'g_type_class_peek_parent'
|
||||
# have_func!' gst/gst.h', 'g_object_class_install_property'
|
||||
have_func! 'gst/gst.h', 'g_param_spec_uint'
|
||||
have_func! 'gst/gst.h', 'g_param_spec_uint64'
|
||||
have_func! 'gst/gst.h', 'g_value_get_uint'
|
||||
have_func! 'gst/gst.h', 'g_value_set_uint'
|
||||
have_func! 'gst/gst.h', 'g_value_get_uint64'
|
||||
have_func! 'gst/gst.h', 'g_value_set_uint64'
|
||||
|
||||
#############
|
||||
# GStreamer #
|
||||
#############
|
||||
|
||||
# have_type! 'gst/gst.h', 'GstPlugin'
|
||||
have_type! 'gst/gst.h', 'GstElementClass'
|
||||
have_type! 'gst/gst.h', 'GstStaticPadTemplate'
|
||||
have_type! 'gst/gst.h', 'GstPad'
|
||||
have_type! 'gst/gst.h', 'GstCaps'
|
||||
have_type! 'gst/gst.h', 'GstQuery'
|
||||
|
||||
have_type! 'gst/base/gstbasesink.h', 'GstBaseSink'
|
||||
have_type! 'gst/base/gstbasesink.h', 'GstBaseSinkClass'
|
||||
|
||||
have_struct_member! 'gst/base/gstbasesink.h', 'GstBaseSinkClass', 'get_caps'
|
||||
have_struct_member! 'gst/base/gstbasesink.h', 'GstBaseSinkClass', 'query'
|
||||
|
||||
have_macro! 'gst/gst.h', 'GST_VERSION_MAJOR'
|
||||
have_macro! 'gst/gst.h', 'GST_VERSION_MINOR'
|
||||
have_macro! 'gst/gst.h', 'GST_PLUGIN_DEFINE'
|
||||
have_macro! 'gst/gst.h', 'GST_DEBUG_CATEGORY_STATIC'
|
||||
have_macro! 'gst/gst.h', 'GST_DEBUG_CATEGORY_INIT'
|
||||
have_macro! 'gst/gst.h', 'GST_STATIC_CAPS'
|
||||
have_macro! 'gst/gst.h', 'GST_DEBUG_FUNCPTR'
|
||||
have_macro! 'gst/gst.h', 'GST_STATIC_PAD_TEMPLATE'
|
||||
have_macro! 'gst/gst.h', 'GST_QUERY_TYPE'
|
||||
|
||||
have_macro! 'gst/base/gstbasesink.h', 'GST_BASE_SINK_CLASS'
|
||||
have_macro! 'gst/base/gstbasesink.h', 'GST_BASE_SINK_PAD'
|
||||
|
||||
have_const! 'gst/gst.h', 'GST_PAD_SINK'
|
||||
have_const! 'gst/gst.h', 'GST_PAD_ALWAYS'
|
||||
have_const! 'gst/gst.h', 'GST_RANK_NONE'
|
||||
have_const! 'gst/gst.h', 'GST_QUERY_ACCEPT_CAPS'
|
||||
|
||||
have_func! 'gst/gst.h', 'gst_element_class_set_details_simple'
|
||||
have_func! 'gst/gst.h', 'gst_element_register'
|
||||
have_func! 'gst/gst.h', 'gst_element_class_add_pad_template'
|
||||
have_func! 'gst/gst.h', 'gst_static_pad_template_get'
|
||||
have_func! 'gst/gst.h', 'gst_pad_get_pad_template_caps'
|
||||
|
||||
###################
|
||||
# GStreamer Audio #
|
||||
###################
|
||||
|
||||
have_macro! 'gst/audio/gstaudiosink.h', 'GST_TYPE_AUDIO_SINK'
|
||||
|
||||
have_type! 'gst/audio/gstaudiosink.h', 'GstAudioSink'
|
||||
have_type! 'gst/audio/gstaudiosink.h', 'GstAudioSinkClass'
|
||||
|
||||
have_struct_member! 'gst/audio/gstaudiosink.h', 'GstAudioSinkClass', 'open'
|
||||
have_struct_member! 'gst/audio/gstaudiosink.h', 'GstAudioSinkClass', 'prepare'
|
||||
have_struct_member! 'gst/audio/gstaudiosink.h', 'GstAudioSinkClass', 'unprepare'
|
||||
have_struct_member! 'gst/audio/gstaudiosink.h', 'GstAudioSinkClass', 'close'
|
||||
have_struct_member! 'gst/audio/gstaudiosink.h', 'GstAudioSinkClass', 'write'
|
||||
have_struct_member! 'gst/audio/gstaudiosink.h', 'GstAudioSinkClass', 'reset'
|
||||
have_struct_member! 'gst/audio/gstaudiosink.h', 'GstAudioSinkClass', 'delay'
|
||||
|
||||
##########
|
||||
# Common #
|
||||
##########
|
||||
|
||||
create_makefile 'gst-plugins-tox' or exit 1
|
|
@ -1,325 +0,0 @@
|
|||
#include "gsttoxaudiosink.h"
|
||||
|
||||
GST_DEBUG_CATEGORY_STATIC(gst_tox_audio_sink_debug);
|
||||
#define GST_CAT_DEFAULT gst_tox_audio_sink_debug
|
||||
|
||||
#define gst_tox_audio_sink_parent_class parent_class
|
||||
G_DEFINE_TYPE(GstToxAudioSink, gst_tox_audio_sink, GST_TYPE_AUDIO_SINK);
|
||||
|
||||
/******************************************************************************
|
||||
* Types and constants
|
||||
******************************************************************************/
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_TOX_AV,
|
||||
PROP_FRIEND_NUMBER
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
* Function declarations
|
||||
******************************************************************************/
|
||||
|
||||
static void gst_tox_audio_sink_class_init(GstToxAudioSinkClass *klass);
|
||||
|
||||
static void gst_tox_audio_sink_init(GstToxAudioSink *self);
|
||||
|
||||
static void gst_tox_audio_sink_finalize(GObject *object);
|
||||
|
||||
static void gst_tox_audio_sink_get_property(
|
||||
GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec
|
||||
);
|
||||
|
||||
static void gst_tox_audio_sink_set_property(
|
||||
GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec
|
||||
);
|
||||
|
||||
static GstCaps *gst_tox_audio_sink_get_caps(
|
||||
GstBaseSink *gst_base_sink,
|
||||
GstCaps *filter
|
||||
);
|
||||
|
||||
static gboolean gst_tox_audio_sink_query(
|
||||
GstBaseSink *gst_base_sink,
|
||||
GstQuery *gst_query
|
||||
);
|
||||
|
||||
static gboolean gst_tox_audio_sink_query_accept_caps(
|
||||
GstBaseSink *gst_base_sink,
|
||||
GstQuery *gst_query
|
||||
);
|
||||
|
||||
static gboolean gst_tox_audio_sink_open(GstAudioSink *gst_audio_sink);
|
||||
|
||||
static gboolean gst_tox_audio_sink_close(GstAudioSink *gst_audio_sink);
|
||||
|
||||
static gboolean gst_tox_audio_sink_prepare(
|
||||
GstAudioSink *gst_audio_sink,
|
||||
GstAudioRingBufferSpec *gst_audio_ring_buffer_spec
|
||||
);
|
||||
|
||||
static gboolean gst_tox_audio_sink_unprepare(GstAudioSink *gst_audio_sink);
|
||||
|
||||
static void gst_tox_audio_sink_reset(GstAudioSink *gst_audio_sink);
|
||||
|
||||
static guint gst_tox_audio_sink_delay(GstAudioSink *gst_audio_sink);
|
||||
|
||||
static gint gst_tox_audio_sink_write(
|
||||
GstAudioSink *gst_audio_sink,
|
||||
gpointer data,
|
||||
guint length
|
||||
);
|
||||
|
||||
/******************************************************************************
|
||||
* Variables
|
||||
******************************************************************************/
|
||||
|
||||
static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE(
|
||||
"sink",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS(
|
||||
"audio/x-raw, "
|
||||
"format = (string) S16LE, "
|
||||
"rate = (int) 48000, "
|
||||
"channels = (int) 1, "
|
||||
"channel-mapping-family = (int) 0, "
|
||||
"stream-count = (int) 1, "
|
||||
"coupled-count = (int) 0"
|
||||
)
|
||||
);
|
||||
|
||||
/******************************************************************************
|
||||
* Function implementations
|
||||
******************************************************************************/
|
||||
|
||||
void gst_tox_audio_sink_class_init(GstToxAudioSinkClass *const klass)
|
||||
{
|
||||
GST_DEBUG_CATEGORY_INIT(
|
||||
gst_tox_audio_sink_debug,
|
||||
"toxaudiosink",
|
||||
0,
|
||||
"toxaudiosink element"
|
||||
);
|
||||
|
||||
parent_class = g_type_class_peek_parent(klass);
|
||||
|
||||
// Class inheritance hierarchy
|
||||
|
||||
GObjectClass *const gobject_class = (GObjectClass*)klass;
|
||||
GstElementClass *const gst_element_class = (GstElementClass*)klass;
|
||||
GstBaseSinkClass *const gst_base_sink_class = (GstBaseSinkClass*)klass;
|
||||
GstAudioSinkClass *const gst_audio_sink_class = (GstAudioSinkClass*)klass;
|
||||
|
||||
// GObjectClass
|
||||
|
||||
gobject_class->finalize = gst_tox_audio_sink_finalize;
|
||||
gobject_class->get_property = gst_tox_audio_sink_get_property;
|
||||
gobject_class->set_property = gst_tox_audio_sink_set_property;
|
||||
|
||||
g_object_class_install_property(
|
||||
gobject_class,
|
||||
PROP_TOX_AV,
|
||||
g_param_spec_uint64(
|
||||
"tox-av",
|
||||
"ToxAV",
|
||||
"ToxAV instance",
|
||||
0,
|
||||
UINT64_MAX,
|
||||
0,
|
||||
G_PARAM_READWRITE
|
||||
)
|
||||
);
|
||||
|
||||
g_object_class_install_property(
|
||||
gobject_class,
|
||||
PROP_FRIEND_NUMBER,
|
||||
g_param_spec_uint(
|
||||
"friend-number",
|
||||
"Friend number",
|
||||
"Friend number",
|
||||
0,
|
||||
UINT32_MAX,
|
||||
0,
|
||||
G_PARAM_READWRITE
|
||||
)
|
||||
);
|
||||
|
||||
// GstElementClass
|
||||
|
||||
gst_element_class_set_details_simple(
|
||||
gst_element_class,
|
||||
"ToxAudioSink",
|
||||
"Sink/Audio",
|
||||
"Sends audio to Tox",
|
||||
"Braiden Vasco <braiden-vasco@users.noreply.github.com>"
|
||||
);
|
||||
|
||||
gst_element_class_add_pad_template(
|
||||
gst_element_class,
|
||||
gst_static_pad_template_get(&sink_template)
|
||||
);
|
||||
|
||||
// GstBaseSinkClass
|
||||
|
||||
gst_base_sink_class->get_caps = GST_DEBUG_FUNCPTR(gst_tox_audio_sink_get_caps);
|
||||
gst_base_sink_class->query = GST_DEBUG_FUNCPTR(gst_tox_audio_sink_query);
|
||||
|
||||
// GstAudioSinkClass
|
||||
|
||||
gst_audio_sink_class->open = GST_DEBUG_FUNCPTR(gst_tox_audio_sink_open);
|
||||
gst_audio_sink_class->close = GST_DEBUG_FUNCPTR(gst_tox_audio_sink_close);
|
||||
gst_audio_sink_class->prepare = GST_DEBUG_FUNCPTR(gst_tox_audio_sink_prepare);
|
||||
gst_audio_sink_class->unprepare = GST_DEBUG_FUNCPTR(gst_tox_audio_sink_unprepare);
|
||||
gst_audio_sink_class->reset = GST_DEBUG_FUNCPTR(gst_tox_audio_sink_reset);
|
||||
gst_audio_sink_class->delay = GST_DEBUG_FUNCPTR(gst_tox_audio_sink_delay);
|
||||
gst_audio_sink_class->write = GST_DEBUG_FUNCPTR(gst_tox_audio_sink_write);
|
||||
}
|
||||
|
||||
void gst_tox_audio_sink_init(GstToxAudioSink *const self)
|
||||
{
|
||||
self->tox_av = NULL;
|
||||
self->friend_number = 0;
|
||||
}
|
||||
|
||||
void gst_tox_audio_sink_finalize(GObject *const object)
|
||||
{
|
||||
G_OBJECT_CLASS(parent_class)->finalize(object);
|
||||
}
|
||||
|
||||
void gst_tox_audio_sink_get_property(
|
||||
GObject *const object,
|
||||
const guint prop_id,
|
||||
GValue *const value,
|
||||
GParamSpec *const pspec
|
||||
)
|
||||
{
|
||||
switch (prop_id) {
|
||||
case PROP_TOX_AV:
|
||||
g_value_set_uint64(value, (guint64)GST_TOX_AUDIO_SINK(object)->tox_av);
|
||||
break;
|
||||
case PROP_FRIEND_NUMBER:
|
||||
g_value_set_uint(value, GST_TOX_AUDIO_SINK(object)->friend_number);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
void gst_tox_audio_sink_set_property(
|
||||
GObject *const object,
|
||||
const guint prop_id,
|
||||
const GValue *const value,
|
||||
GParamSpec *const pspec
|
||||
)
|
||||
{
|
||||
switch (prop_id) {
|
||||
case PROP_TOX_AV:
|
||||
GST_TOX_AUDIO_SINK(object)->tox_av = (gpointer)g_value_get_uint64(value);
|
||||
break;
|
||||
case PROP_FRIEND_NUMBER:
|
||||
GST_TOX_AUDIO_SINK(object)->friend_number = g_value_get_uint(value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
GstCaps *gst_tox_audio_sink_get_caps(
|
||||
GstBaseSink *gst_base_sink,
|
||||
GstCaps *filter
|
||||
)
|
||||
{
|
||||
GstPad *pad = GST_BASE_SINK_PAD(gst_base_sink);
|
||||
return gst_pad_get_pad_template_caps(pad);
|
||||
}
|
||||
|
||||
gboolean gst_tox_audio_sink_query(
|
||||
GstBaseSink *gst_base_sink,
|
||||
GstQuery *gst_query
|
||||
)
|
||||
{
|
||||
switch (GST_QUERY_TYPE(gst_query)) {
|
||||
case GST_QUERY_ACCEPT_CAPS:
|
||||
return gst_tox_audio_sink_query_accept_caps(gst_base_sink, gst_query);
|
||||
default:
|
||||
return GST_BASE_SINK_CLASS(parent_class)->
|
||||
query(gst_base_sink, gst_query);
|
||||
}
|
||||
}
|
||||
|
||||
gboolean gst_tox_audio_sink_query_accept_caps(
|
||||
GstBaseSink *gst_base_sink,
|
||||
GstQuery *gst_query
|
||||
)
|
||||
{
|
||||
return GST_BASE_SINK_CLASS(parent_class)->query(gst_base_sink, gst_query);
|
||||
}
|
||||
|
||||
gboolean gst_tox_audio_sink_open(GstAudioSink *gst_audio_sink)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean gst_tox_audio_sink_close(GstAudioSink *gst_audio_sink)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean gst_tox_audio_sink_prepare(
|
||||
GstAudioSink *gst_audio_sink,
|
||||
GstAudioRingBufferSpec *gst_audio_ring_buffer_spec
|
||||
)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean gst_tox_audio_sink_unprepare(GstAudioSink *gst_audio_sink)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void gst_tox_audio_sink_reset(GstAudioSink *gst_audio_sink)
|
||||
{
|
||||
}
|
||||
|
||||
guint gst_tox_audio_sink_delay(GstAudioSink *gst_audio_sink)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
gint gst_tox_audio_sink_write(
|
||||
GstAudioSink *const gst_audio_sink,
|
||||
const gpointer data,
|
||||
const guint length
|
||||
)
|
||||
{
|
||||
const GstToxAudioSink *const gst_tox_audio_sink =
|
||||
GST_TOX_AUDIO_SINK(gst_audio_sink);
|
||||
|
||||
if (!gst_tox_audio_sink->tox_av) {
|
||||
return length;
|
||||
}
|
||||
|
||||
const size_t sample_count = length / sizeof(int16_t);
|
||||
|
||||
TOXAV_ERR_SEND_FRAME toxav_audio_send_frame_error;
|
||||
|
||||
toxav_audio_send_frame(
|
||||
gst_tox_audio_sink->tox_av,
|
||||
gst_tox_audio_sink->friend_number,
|
||||
data,
|
||||
sample_count,
|
||||
1, // channels
|
||||
48000, // sampling_rate
|
||||
&toxav_audio_send_frame_error
|
||||
);
|
||||
|
||||
return length;
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
#ifndef __GSTTOXAUDIOSINK_H__
|
||||
#define __GSTTOXAUDIOSINK_H__
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/audio/gstaudiosink.h>
|
||||
#include <tox/toxav.h>
|
||||
|
||||
#define GST_TYPE_TOX_AUDIO_SINK \
|
||||
(gst_tox_audio_sink_get_type())
|
||||
|
||||
#define GST_TOX_AUDIO_SINK(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_TOX_AUDIO_SINK,GstToxAudioSink))
|
||||
|
||||
#define GST_TOX_AUDIO_SINK_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_TOX_AUDIO_SINK,GetToxAudioSinkClass))
|
||||
|
||||
#define GST_IS_TOX_AUDIO_SINK(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_TOX_AUDIO_SINK))
|
||||
|
||||
#define GST_IS_TOX_AUDIO_SINK_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_TOX_AUDIO_SINK))
|
||||
|
||||
typedef struct _GstToxAudioSink GstToxAudioSink;
|
||||
typedef struct _GstToxAudioSinkClass GstToxAudioSinkClass;
|
||||
|
||||
struct _GstToxAudioSink {
|
||||
GstAudioSink parent;
|
||||
|
||||
ToxAV *tox_av;
|
||||
uint32_t friend_number;
|
||||
};
|
||||
|
||||
struct _GstToxAudioSinkClass {
|
||||
GstAudioSinkClass parent_class;
|
||||
};
|
||||
|
||||
GType gst_tox_audio_sink_get_type();
|
||||
|
||||
#endif // __GSTTOXAUDIOSINK_H__
|
|
@ -1,31 +0,0 @@
|
|||
#include "gsttoxaudiosink.h"
|
||||
|
||||
#ifndef PACKAGE
|
||||
#define PACKAGE "tox"
|
||||
#endif
|
||||
|
||||
static gboolean tox_init(GstPlugin *plugin);
|
||||
|
||||
GST_PLUGIN_DEFINE(
|
||||
GST_VERSION_MAJOR,
|
||||
GST_VERSION_MINOR,
|
||||
tox,
|
||||
"Tox audio/video sink/src",
|
||||
tox_init,
|
||||
"0.0.0",
|
||||
"GPL",
|
||||
"gst-plugins-tox",
|
||||
"https://github.com/toxon/tox.rb"
|
||||
)
|
||||
|
||||
gboolean tox_init(GstPlugin *const plugin)
|
||||
{
|
||||
gst_element_register(
|
||||
plugin,
|
||||
"toxaudiosink",
|
||||
GST_RANK_NONE,
|
||||
GST_TYPE_TOX_AUDIO_SINK
|
||||
);
|
||||
|
||||
return TRUE;
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'gst'
|
||||
|
||||
Gst::Registry.get.scan_path File.expand_path '../..', __dir__
|
|
@ -1,53 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
RSpec.describe 'lib/gst-plugins-tox.so' do
|
||||
subject { Gst::Registry.get.find_plugin 'tox' }
|
||||
|
||||
describe '#description' do
|
||||
specify do
|
||||
expect(subject.description).to eq 'Tox audio/video sink/src'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#license' do
|
||||
specify do
|
||||
expect(subject.license).to eq 'GPL'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#name' do
|
||||
specify do
|
||||
expect(subject.name).to eq 'tox'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#origin' do
|
||||
specify do
|
||||
expect(subject.origin).to eq 'https://github.com/toxon/tox.rb'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#package' do
|
||||
specify do
|
||||
expect(subject.package).to eq 'gst-plugins-tox'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#source' do
|
||||
specify do
|
||||
expect(subject.source).to eq 'tox'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#version' do
|
||||
specify do
|
||||
expect(subject.version).to eq '0.0.0'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#load' do
|
||||
specify do
|
||||
expect { subject.load }.not_to raise_error
|
||||
end
|
||||
end
|
||||
end
|
|
@ -26,7 +26,6 @@ require 'openssl'
|
|||
require 'faker'
|
||||
|
||||
require 'tox'
|
||||
require 'gst/plugins/tox'
|
||||
|
||||
require 'support/random_port'
|
||||
|
||||
|
|
|
@ -38,7 +38,6 @@ Gem::Specification.new do |spec|
|
|||
spec.executables = spec.files.grep %r{^exe/}, &File.method(:basename)
|
||||
|
||||
spec.extensions << 'ext/tox/extconf.rb'
|
||||
spec.extensions << 'ext/gst-plugins-tox/extconf.rb'
|
||||
|
||||
spec.add_development_dependency 'bundler', '~> 1.13'
|
||||
spec.add_development_dependency 'celluloid', '~> 0.17'
|
||||
|
|
Reference in New Issue