webrtc-ruby 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,152 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # WebRTC Connection Example
5
+ # This example demonstrates a WebRTC connection between two peers
6
+ # with data channel and DTMF support simulation.
7
+
8
+ require_relative '../lib/webrtc'
9
+
10
+ puts '=== WebRTC Ruby Connection Example ==='
11
+ puts
12
+
13
+ # Initialize WebRTC
14
+ WebRTC.init
15
+
16
+ # Create two peer connections (simulating caller and callee)
17
+ caller_config = {
18
+ ice_servers: [
19
+ { urls: 'stun:stun.l.google.com:19302' }
20
+ ]
21
+ }
22
+
23
+ caller_pc = WebRTC::RTCPeerConnection.new(caller_config)
24
+ callee_pc = WebRTC::RTCPeerConnection.new(caller_config)
25
+
26
+ puts 'Created peer connections'
27
+
28
+ # Set up ICE candidate exchange
29
+ caller_ice_candidates = []
30
+ callee_ice_candidates = []
31
+
32
+ caller_pc.on_ice_candidate do |candidate|
33
+ caller_ice_candidates << candidate if candidate
34
+ end
35
+
36
+ callee_pc.on_ice_candidate do |candidate|
37
+ callee_ice_candidates << candidate if candidate
38
+ end
39
+
40
+ # Monitor connection states
41
+ caller_pc.on_connection_state_change do |state|
42
+ puts "Caller connection state: #{state}"
43
+ end
44
+
45
+ callee_pc.on_connection_state_change do |state|
46
+ puts "Callee connection state: #{state}"
47
+ end
48
+
49
+ # Create data channel for signaling/messaging
50
+ puts "\nCreating data channel..."
51
+ data_channel = caller_pc.create_data_channel('messaging', ordered: true)
52
+ puts " Data channel created: #{data_channel.label}"
53
+
54
+ data_channel.on_open do
55
+ puts ' Data channel opened!'
56
+ end
57
+
58
+ data_channel.on_message do |event|
59
+ puts " Received message: #{event.data}"
60
+ end
61
+
62
+ # Set up callee to receive data channels
63
+ callee_pc.on_data_channel do |dc|
64
+ puts "Callee received data channel: #{dc.label}"
65
+ dc.on_message do |event|
66
+ puts "Callee received: #{event.data}"
67
+ end
68
+ end
69
+
70
+ # Perform signaling
71
+ puts "\n=== Signaling Exchange ==="
72
+
73
+ # 1. Caller creates offer
74
+ puts "\n1. Caller creates offer..."
75
+ offer = caller_pc.create_offer.await
76
+ puts " Offer type: #{offer.type}"
77
+ puts " SDP length: #{offer.sdp.length} bytes"
78
+
79
+ # 2. Caller sets local description
80
+ puts "\n2. Caller sets local description..."
81
+ caller_pc.set_local_description(offer).await
82
+ puts ' Local description set'
83
+
84
+ # 3. Callee receives and sets remote description
85
+ puts "\n3. Callee sets remote description..."
86
+ callee_pc.set_remote_description(offer).await
87
+ puts ' Remote description set'
88
+
89
+ # 4. Exchange ICE candidates
90
+ puts "\n4. Exchanging ICE candidates..."
91
+ caller_ice_candidates.each do |candidate|
92
+ callee_pc.add_ice_candidate(candidate).await
93
+ rescue StandardError
94
+ nil
95
+ end
96
+ puts " Sent #{caller_ice_candidates.size} candidates from caller to callee"
97
+
98
+ callee_ice_candidates.each do |candidate|
99
+ caller_pc.add_ice_candidate(candidate).await
100
+ rescue StandardError
101
+ nil
102
+ end
103
+ puts " Sent #{callee_ice_candidates.size} candidates from callee to caller"
104
+
105
+ # Check status
106
+ puts "\n=== Connection Status ==="
107
+ puts "Caller signaling state: #{caller_pc.signaling_state}"
108
+ puts "Callee signaling state: #{callee_pc.signaling_state}"
109
+ puts "Data channel state: #{data_channel.ready_state}"
110
+
111
+ # Simulate DTMF (audio track simulation)
112
+ puts "\n=== DTMF Simulation ==="
113
+ audio_track = WebRTC::MediaStreamTrack.new(kind: :audio, label: 'virtual-audio')
114
+ sender = WebRTC::RTCRtpSender.new(track: audio_track)
115
+
116
+ if sender.dtmf
117
+ dtmf = sender.dtmf
118
+ puts "DTMF available: #{dtmf.can_insert_dtmf?}"
119
+
120
+ if dtmf.can_insert_dtmf?
121
+ dtmf.on_tone_change do |event|
122
+ puts " Playing tone: #{event.tone}"
123
+ end
124
+
125
+ puts 'Sending DTMF tones: 123#'
126
+ dtmf.insert_dtmf('123#', duration: 100, inter_tone_gap: 70)
127
+ end
128
+ end
129
+
130
+ # Get statistics
131
+ puts "\n=== Connection Statistics ==="
132
+ stats = caller_pc.get_stats.await
133
+ puts "Stats entries: #{stats.size}"
134
+ stats.each do |id, stat|
135
+ case stat
136
+ when WebRTC::RTCPeerConnectionStats
137
+ puts ' PeerConnection Stats:'
138
+ puts " Data channels opened: #{stat.data_channels_opened}"
139
+ when WebRTC::RTCTransportStats
140
+ puts ' Transport Stats:'
141
+ puts " Bytes sent: #{stat.bytes_sent}"
142
+ end
143
+ end
144
+
145
+ # Cleanup
146
+ puts "\n=== Cleanup ==="
147
+ data_channel.destroy
148
+ caller_pc.close
149
+ callee_pc.close
150
+ WebRTC.cleanup
151
+
152
+ puts "\nExample completed!"
@@ -0,0 +1,84 @@
1
+ cmake_minimum_required(VERSION 3.14)
2
+ project(webrtc_ruby C)
3
+
4
+ set(CMAKE_C_STANDARD 11)
5
+ set(CMAKE_C_STANDARD_REQUIRED ON)
6
+
7
+ if(NOT CMAKE_BUILD_TYPE)
8
+ set(CMAKE_BUILD_TYPE Release)
9
+ endif()
10
+
11
+ set(CMAKE_C_FLAGS_DEBUG "-g -O0")
12
+ set(CMAKE_C_FLAGS_RELEASE "-O3")
13
+
14
+ add_compile_definitions(WEBRTC_RUBY_BUILDING)
15
+
16
+ if(APPLE)
17
+ set(CMAKE_C_VISIBILITY_PRESET hidden)
18
+ endif()
19
+
20
+ # Find libdatachannel
21
+ set(LIBDATACHANNEL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../vendor/libdatachannel")
22
+
23
+ if(EXISTS "${LIBDATACHANNEL_DIR}/build/libdatachannel.dylib" OR
24
+ EXISTS "${LIBDATACHANNEL_DIR}/build/libdatachannel.so")
25
+ message(STATUS "Found libdatachannel in vendor directory")
26
+ set(DATACHANNEL_INCLUDE_DIR "${LIBDATACHANNEL_DIR}/include")
27
+ set(DATACHANNEL_LIBRARY_DIR "${LIBDATACHANNEL_DIR}/build")
28
+
29
+ if(APPLE)
30
+ set(DATACHANNEL_LIBRARY "${DATACHANNEL_LIBRARY_DIR}/libdatachannel.dylib")
31
+ else()
32
+ set(DATACHANNEL_LIBRARY "${DATACHANNEL_LIBRARY_DIR}/libdatachannel.so")
33
+ endif()
34
+ else()
35
+ # Try pkg-config
36
+ find_package(PkgConfig QUIET)
37
+ if(PkgConfig_FOUND)
38
+ pkg_check_modules(DATACHANNEL libdatachannel)
39
+ endif()
40
+
41
+ if(NOT DATACHANNEL_FOUND)
42
+ message(FATAL_ERROR "libdatachannel not found. Build it first.")
43
+ endif()
44
+ endif()
45
+
46
+ add_library(webrtc_ruby SHARED
47
+ webrtc_ruby.c
48
+ )
49
+
50
+ target_include_directories(webrtc_ruby PUBLIC
51
+ ${CMAKE_CURRENT_SOURCE_DIR}
52
+ ${DATACHANNEL_INCLUDE_DIR}
53
+ )
54
+
55
+ target_link_directories(webrtc_ruby PRIVATE
56
+ ${DATACHANNEL_LIBRARY_DIR}
57
+ )
58
+
59
+ target_link_libraries(webrtc_ruby PRIVATE
60
+ ${DATACHANNEL_LIBRARY}
61
+ )
62
+
63
+ if(APPLE)
64
+ set_target_properties(webrtc_ruby PROPERTIES
65
+ SUFFIX ".dylib"
66
+ INSTALL_RPATH "@loader_path"
67
+ BUILD_WITH_INSTALL_RPATH TRUE
68
+ )
69
+ elseif(WIN32)
70
+ set_target_properties(webrtc_ruby PROPERTIES
71
+ SUFFIX ".dll"
72
+ )
73
+ else()
74
+ set_target_properties(webrtc_ruby PROPERTIES
75
+ SUFFIX ".so"
76
+ INSTALL_RPATH "$ORIGIN"
77
+ BUILD_WITH_INSTALL_RPATH TRUE
78
+ )
79
+ endif()
80
+
81
+ install(TARGETS webrtc_ruby
82
+ LIBRARY DESTINATION lib
83
+ RUNTIME DESTINATION bin
84
+ )
@@ -0,0 +1,31 @@
1
+ CC = cc
2
+ CFLAGS = -Wall -Wextra -fPIC -O2 -DWEBRTC_RUBY_BUILDING
3
+ LDFLAGS = -shared
4
+
5
+ UNAME_S := $(shell uname -s)
6
+ ifeq ($(UNAME_S),Darwin)
7
+ TARGET = libwebrtc_ruby.dylib
8
+ LDFLAGS += -dynamiclib -install_name @rpath/$(TARGET)
9
+ else ifeq ($(OS),Windows_NT)
10
+ TARGET = webrtc_ruby.dll
11
+ else
12
+ TARGET = libwebrtc_ruby.so
13
+ endif
14
+
15
+ SOURCES = webrtc_ruby.c
16
+ OBJECTS = $(SOURCES:.c=.o)
17
+
18
+ BUILD_DIR = build
19
+
20
+ all: $(BUILD_DIR)/$(TARGET)
21
+
22
+ $(BUILD_DIR):
23
+ mkdir -p $(BUILD_DIR)
24
+
25
+ $(BUILD_DIR)/$(TARGET): $(SOURCES) | $(BUILD_DIR)
26
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(SOURCES)
27
+
28
+ clean:
29
+ rm -rf $(BUILD_DIR)
30
+
31
+ .PHONY: all clean