@@ -1167,17 +1167,20 @@ def self.screenshare_has_audio?(events, deskshare_dir)
11671167 return false
11681168 end
11691169
1170- # Get a list of times when the "screenshare as content" flag is changed
1170+ # Generic function to get a list of times when a specific state changes
11711171 #
11721172 # The returned times account for recording start/stop events, and have timestamps relative to the start of the
11731173 # recording.
11741174 #
11751175 # @param events [Nokogiri::XML::Document] The parsed events.xml document
11761176 # @param start_time [Integer] The recording segment start timestamp (ms)
11771177 # @param end_time [Integer] The recording segment end timestamp (ms)
1178- # @return [Array<Hash>] An array of events, each with a timestamp and the screenshareAsContent flag
1179- def self . get_screenshare_as_content_events ( events , start_time , end_time )
1180- BigBlueButton . logger . info ( 'Getting Screenshare as Content Events' )
1178+ # @param target_module [String] The module name of the event to track
1179+ # @param target_eventname [String] The event name to track
1180+ # @param compare_keys [Array<Symbol>] Optional list of keys to compare for state changes. If nil, all keys are compared.
1181+ # @return [Array<Hash>] An array of events, each with a timestamp and the extracted state
1182+ def self . get_events ( events , start_time , end_time , target_module , target_eventname , compare_keys = nil )
1183+ BigBlueButton . logger . info ( "Getting #{ target_eventname } Events" )
11811184
11821185 initial_timestamp = first_event_timestamp ( events )
11831186 start_time -= initial_timestamp
@@ -1188,25 +1191,32 @@ def self.get_screenshare_as_content_events(events, start_time, end_time)
11881191 # Recordings without status events are assumed to have been recorded from the beginning
11891192 record = events . at_xpath ( '/recording/event[@eventname="RecordStatusEvent"]' ) . nil?
11901193
1191- screenshare_content_events = [ ]
1194+ extracted_events = [ ]
1195+ current_state = nil
11921196
11931197 events . xpath ( '/recording/event' ) . each do |event |
11941198 timestamp = event [ :timestamp ] . to_i - initial_timestamp
11951199 break if timestamp >= end_time
11961200
11971201 case [ event [ :module ] , event [ :eventname ] ]
1198- when %w[ PARTICIPANT SetScreenshareAsContentEvent ]
1199- screenshare_as_content = event . at_xpath ( 'screenshareAsContent' ) &. content == 'true'
1202+ when [ target_module , target_eventname ]
1203+ current_state = yield ( event )
12001204
12011205 # Don't emit events during unrecorded sections of the meeting. An event will be emitted when recording resumes
12021206 next unless timestamp >= start_time && record
1207+
12031208 # Don't emit an event if the previous event has the same state
1204- next if screenshare_content_events . dig ( -1 , :screenshareAsContent ) == screenshare_as_content
1209+ if extracted_events . last
1210+ last_event = extracted_events . last . reject { |k | k == :timestamp }
1211+ if compare_keys
1212+ next if last_event . select { |k , _ | compare_keys . include? ( k ) } == current_state . select { |k , _ | compare_keys . include? ( k ) }
1213+ else
1214+ next if last_event == current_state
1215+ end
1216+ end
1217+
1218+ extracted_events << current_state . merge ( timestamp : timestamp - offset )
12051219
1206- screenshare_content_events << {
1207- timestamp : timestamp - offset ,
1208- screenshareAsContent : screenshare_as_content ,
1209- }
12101220 when %w[ PARTICIPANT RecordStatusEvent ]
12111221 record = event . at_xpath ( 'status' ) . content == 'true'
12121222 # Don't update timestamps until we're past the segment start time
@@ -1217,12 +1227,17 @@ def self.get_screenshare_as_content_events(events, start_time, end_time)
12171227 offset += timestamp - last_stop_timestamp
12181228
12191229 # Don't emit an event if the previous event has the same state
1220- next if screenshare_content_events . dig ( -1 , :screenshareAsContent ) == screenshare_as_content
1230+ next if current_state . nil?
1231+ if extracted_events . last
1232+ last_event = extracted_events . last . reject { |k | k == :timestamp }
1233+ if compare_keys
1234+ next if last_event . select { |k , _ | compare_keys . include? ( k ) } == current_state . select { |k , _ | compare_keys . include? ( k ) }
1235+ else
1236+ next if last_event == current_state
1237+ end
1238+ end
12211239
1222- screenshare_content_events << {
1223- timestamp : timestamp - offset ,
1224- screenshareAsContent : screenshare_as_content ,
1225- }
1240+ extracted_events << current_state . merge ( timestamp : timestamp - offset )
12261241 else
12271242 # Recording paused
12281243 last_stop_timestamp = timestamp
@@ -1232,18 +1247,36 @@ def self.get_screenshare_as_content_events(events, start_time, end_time)
12321247 # whatever the state happened to be when start_time was reached
12331248
12341249 # Don't emit an event during unrecorded sections of the meeting, or if one has already been emitted.
1235- next unless timestamp >= start_time && record && screenshare_content_events . empty?
1250+ next unless timestamp >= start_time && record && extracted_events . empty?
12361251
1237- # Don't emit an event if we haven't seen a SetScreenshareAsContentEvent yet
1238- next if screenshare_as_content . nil?
1252+ # Don't emit an event if we haven't seen the target event yet
1253+ next if current_state . nil?
12391254
1240- screenshare_content_events << {
1241- timestamp : 0 ,
1242- screenshareAsContent : screenshare_as_content ,
1243- }
1255+ extracted_events << current_state . merge ( timestamp : 0 )
12441256 end
12451257 end
1246- screenshare_content_events
1258+ extracted_events
1259+ end
1260+
1261+ def self . get_screenshare_as_content_events ( events , start_time , end_time )
1262+ get_events ( events , start_time , end_time , 'PARTICIPANT' , 'SetScreenshareAsContentEvent' , [ :screenshareAsContent ] ) do |event |
1263+ {
1264+ screenshareAsContent : event . at_xpath ( 'screenshareAsContent' ) &.content == "true"
1265+ }
1266+ end
1267+ end
1268+
1269+ def self . get_layout_broadcasted_events ( events , start_time , end_time )
1270+ get_events ( events , start_time , end_time , 'PARTICIPANT' , 'LayoutBroadcastedEvent' , [ :presentationIsOpen ] ) do |event |
1271+ {
1272+ focusedCamera : event . at_xpath ( 'focusedCamera' ) &.content ,
1273+ presentationVideoRate : event . at_xpath ( 'presentationVideoRate' ) &.content . to_f ,
1274+ cameraPosition : event . at_xpath ( 'cameraPosition' ) &.content ,
1275+ layout : event . at_xpath ( 'layout' ) &.content ,
1276+ presentationIsOpen : event . at_xpath ( 'presentationIsOpen' ) &.content == "true" ,
1277+ isResizing : event . at_xpath ( 'isResizing' ) &.content == "true"
1278+ }
1279+ end
12471280 end
12481281 end
12491282end
0 commit comments