Added video profiles, shared object save, camera preview, change audio and video connection parameters.
This commit is contained in:
parent
e0c14b8483
commit
78ec0aa4b4
@ -0,0 +1,34 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
|
||||||
|
xmlns:s="library://ns.adobe.com/flex/spark"
|
||||||
|
xmlns:mx="library://ns.adobe.com/flex/mx"
|
||||||
|
styleName="cameraProfileItemStyle">
|
||||||
|
|
||||||
|
<fx:Script>
|
||||||
|
<![CDATA[
|
||||||
|
private var guestID:String;
|
||||||
|
|
||||||
|
override public function set data(obj:Object):void {
|
||||||
|
super.data = obj;
|
||||||
|
if (obj) {
|
||||||
|
quality.text = obj.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]]>
|
||||||
|
</fx:Script>
|
||||||
|
<s:Group width="100%"
|
||||||
|
height="{getStyle('itemHeight')}">
|
||||||
|
<s:Label id="quality"
|
||||||
|
styleName="contentFontSize"
|
||||||
|
width="100%"
|
||||||
|
height="100%" />
|
||||||
|
</s:Group>
|
||||||
|
|
||||||
|
<s:Line width="100%">
|
||||||
|
<s:stroke>
|
||||||
|
<s:SolidColorStroke color="{getStyle('lineColor')}"
|
||||||
|
weight="{getStyle('lineWeight')}" />
|
||||||
|
</s:stroke>
|
||||||
|
</s:Line>
|
||||||
|
|
||||||
|
</s:ItemRenderer>
|
@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<s:List xmlns:fx="http://ns.adobe.com/mxml/2009"
|
||||||
|
xmlns:s="library://ns.adobe.com/flex/spark"
|
||||||
|
itemRenderer="org.bigbluebutton.air.settings.views.cameraprofiles.CameraProfileItemRenderer"
|
||||||
|
styleName="cameraProfilesListStyle">
|
||||||
|
<s:layout>
|
||||||
|
<s:VerticalLayout horizontalAlign="contentJustify"
|
||||||
|
gap="0"
|
||||||
|
verticalAlign="middle"
|
||||||
|
variableRowHeight="false" />
|
||||||
|
</s:layout>
|
||||||
|
<fx:Declarations>
|
||||||
|
</fx:Declarations>
|
||||||
|
</s:List>
|
@ -0,0 +1,7 @@
|
|||||||
|
package org.bigbluebutton.lib.common.models {
|
||||||
|
|
||||||
|
public interface ISaveData {
|
||||||
|
function save(name:String, obj:Object):void
|
||||||
|
function read(name:String):Object
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
package org.bigbluebutton.lib.common.models {
|
||||||
|
|
||||||
|
import flash.net.SharedObject;
|
||||||
|
|
||||||
|
public class SaveData implements ISaveData {
|
||||||
|
private var sharedObject:SharedObject;
|
||||||
|
|
||||||
|
public function SaveData() {
|
||||||
|
sharedObject = SharedObject.getLocal("bbb");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function save(name:String, obj:Object):void {
|
||||||
|
sharedObject.data[name] = obj;
|
||||||
|
sharedObject.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function read(name:String):Object {
|
||||||
|
return sharedObject.data[name];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,90 @@
|
|||||||
|
package org.bigbluebutton.lib.main.models {
|
||||||
|
import org.osflash.signals.Signal;
|
||||||
|
|
||||||
|
public class LockSettings {
|
||||||
|
private var _disableCamSignal:Signal = new Signal();
|
||||||
|
|
||||||
|
private var _disableMicSignal:Signal = new Signal();
|
||||||
|
|
||||||
|
private var _disablePrivateChatSignal:Signal = new Signal();
|
||||||
|
|
||||||
|
private var _disablePublicChatSignal:Signal = new Signal();
|
||||||
|
|
||||||
|
private var _disableCam:Boolean;
|
||||||
|
|
||||||
|
private var _disableMic:Boolean;
|
||||||
|
|
||||||
|
private var _disablePrivateChat:Boolean;
|
||||||
|
|
||||||
|
private var _disablePublicChat:Boolean;
|
||||||
|
|
||||||
|
private var _lockedLayout:Boolean;
|
||||||
|
|
||||||
|
public function LockSettings() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get disableCamSignal():Signal {
|
||||||
|
return _disableCamSignal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get disableMicSignal():Signal {
|
||||||
|
return _disableMicSignal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get disablePrivateChatSignal():Signal {
|
||||||
|
return _disablePrivateChatSignal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get disablePublicChatSignal():Signal {
|
||||||
|
return _disablePublicChatSignal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get disableCam():Boolean {
|
||||||
|
return _disableCam;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get lockedLayout():Boolean {
|
||||||
|
return _lockedLayout;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function set disableCam(disable:Boolean):void {
|
||||||
|
if (_disableCam != disable) {
|
||||||
|
_disableCam = disable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get disableMic():Boolean {
|
||||||
|
return _disableMic;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function set disableMic(disable:Boolean):void {
|
||||||
|
if (_disableMic != disable) {
|
||||||
|
_disableMic = disable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get disablePrivateChat():Boolean {
|
||||||
|
return _disablePrivateChat;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function set disablePrivateChat(disable:Boolean):void {
|
||||||
|
if (_disablePrivateChat != disable) {
|
||||||
|
_disablePrivateChat = disable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get disablePublicChat():Boolean {
|
||||||
|
return _disablePublicChat;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function set disablePublicChat(disable:Boolean):void {
|
||||||
|
if (_disablePublicChat != disable) {
|
||||||
|
_disablePublicChat = disable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function set lockedLayout(disable:Boolean):void {
|
||||||
|
_lockedLayout = disable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
package org.bigbluebutton.lib.video.models {
|
||||||
|
import org.bigbluebutton.lib.user.models.User;
|
||||||
|
|
||||||
|
public class UserStreamName {
|
||||||
|
public var streamName:String;
|
||||||
|
|
||||||
|
public var user:org.bigbluebutton.lib.user.models.User;
|
||||||
|
|
||||||
|
public function UserStreamName(streamName:String, user:User) {
|
||||||
|
this.streamName = streamName;
|
||||||
|
this.user = user;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,144 @@
|
|||||||
|
package org.bigbluebutton.lib.video.models {
|
||||||
|
import flash.utils.Dictionary;
|
||||||
|
import mx.resources.ResourceManager;
|
||||||
|
|
||||||
|
public class VideoProfile {
|
||||||
|
private var _fallbackLanguage:String;
|
||||||
|
|
||||||
|
private static var _nextId:int = -1;
|
||||||
|
|
||||||
|
private var _id:String;
|
||||||
|
|
||||||
|
private var _default:Boolean = false;
|
||||||
|
|
||||||
|
private var _name:Dictionary = new Dictionary();
|
||||||
|
|
||||||
|
private var _width:int = 320;
|
||||||
|
|
||||||
|
private var _height:int = 240;
|
||||||
|
|
||||||
|
private var _keyFrameInterval:int = 30;
|
||||||
|
|
||||||
|
private var _modeFps:int = 10;
|
||||||
|
|
||||||
|
private var _qualityBandwidth:int = 0;
|
||||||
|
|
||||||
|
private var _qualityPicture:int = 90;
|
||||||
|
|
||||||
|
private var _enableH264:Boolean = true;
|
||||||
|
|
||||||
|
private var _h264Level:String = "2.1";
|
||||||
|
|
||||||
|
private var _h264Profile:String = "main";
|
||||||
|
|
||||||
|
public function VideoProfile(vxml:XML, fallbackLanguage:String) {
|
||||||
|
_fallbackLanguage = fallbackLanguage;
|
||||||
|
if (vxml.@id != undefined) {
|
||||||
|
_id = vxml.@id.toString();
|
||||||
|
} else {
|
||||||
|
_id = String(nextId());
|
||||||
|
}
|
||||||
|
if (vxml.@default != undefined) {
|
||||||
|
_default = ((vxml.@default).toString().toUpperCase() == "TRUE") ? true : false;
|
||||||
|
}
|
||||||
|
if (vxml.locale != undefined) {
|
||||||
|
for each (var locale:XML in vxml.locale.children()) {
|
||||||
|
_name[locale.localName()] = locale.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (vxml.width != undefined) {
|
||||||
|
_width = vxml.width;
|
||||||
|
}
|
||||||
|
if (vxml.height != undefined) {
|
||||||
|
_height = vxml.height;
|
||||||
|
}
|
||||||
|
if (vxml.keyFrameInterval != undefined) {
|
||||||
|
_keyFrameInterval = vxml.keyFrameInterval;
|
||||||
|
}
|
||||||
|
if (vxml.modeFps != undefined) {
|
||||||
|
_modeFps = vxml.modeFps;
|
||||||
|
}
|
||||||
|
if (vxml.qualityBandwidth != undefined) {
|
||||||
|
_qualityBandwidth = vxml.qualityBandwidth;
|
||||||
|
}
|
||||||
|
if (vxml.qualityPicture != undefined) {
|
||||||
|
_qualityPicture = vxml.qualityPicture;
|
||||||
|
}
|
||||||
|
if (vxml.enableH264 != undefined) {
|
||||||
|
_enableH264 = (vxml.enableH264.toString().toUpperCase() == "TRUE") ? true : false;
|
||||||
|
}
|
||||||
|
if (vxml.h264Level != undefined) {
|
||||||
|
_h264Level = vxml.h264Level.toString();
|
||||||
|
}
|
||||||
|
if (vxml.h264Profile != undefined) {
|
||||||
|
_h264Profile = vxml.h264Profile.toString();
|
||||||
|
}
|
||||||
|
trace("This is a new video profile");
|
||||||
|
trace(this.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function toString():String {
|
||||||
|
return "VideoProfile [ " + "id: " + this.id + ", " + "default: " + this.defaultProfile + ", " + "name: " + this.name + ", " + "width: " + this.width + ", " + "height: " + this.height + ", " + "keyFrameInterval: " + this.keyFrameInterval + ", " + "modeFps: " + this.modeFps + ", " + "qualityBandwidth: " + this.qualityBandwidth + ", " + "qualityPicture: " + this.qualityPicture + ", " + "enableH264: " + this.enableH264 + ", " + "h264Level: " + this.h264Level + ", " + "h264Profile: " + this.h264Profile + " ]";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function nextId():int {
|
||||||
|
_nextId++;
|
||||||
|
return _nextId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get id():String {
|
||||||
|
return _id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get defaultProfile():Boolean {
|
||||||
|
return _default;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get name():String {
|
||||||
|
var locale:String = ResourceManager.getInstance().localeChain[0]; //"en_US";//ResourceUtil.getInstance().getCurrentLanguageCode();
|
||||||
|
if (_name.hasOwnProperty(locale)) {
|
||||||
|
return _name[locale];
|
||||||
|
} else if (_name.hasOwnProperty(_fallbackLanguage)) {
|
||||||
|
return _name[_fallbackLanguage];
|
||||||
|
} else {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get width():int {
|
||||||
|
return _width;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get height():int {
|
||||||
|
return _height;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get keyFrameInterval():int {
|
||||||
|
return _keyFrameInterval;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get modeFps():int {
|
||||||
|
return _modeFps;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get qualityBandwidth():int {
|
||||||
|
return _qualityBandwidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get qualityPicture():int {
|
||||||
|
return _qualityPicture;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get enableH264():Boolean {
|
||||||
|
return _enableH264;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get h264Level():String {
|
||||||
|
return _h264Level;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get h264Profile():String {
|
||||||
|
return _h264Profile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,117 @@
|
|||||||
|
package org.bigbluebutton.lib.video.models {
|
||||||
|
import flash.events.EventDispatcher;
|
||||||
|
|
||||||
|
public class VideoProfileManager extends EventDispatcher {
|
||||||
|
public static const PROFILES_XML:String = "client/conf/profiles.xml";
|
||||||
|
|
||||||
|
public static const DEFAULT_FALLBACK_LOCALE:String = "en_US";
|
||||||
|
|
||||||
|
private var _profiles:Array = new Array();
|
||||||
|
|
||||||
|
public function parseProfilesXml(profileXML:XML):void {
|
||||||
|
// first clear the array
|
||||||
|
_profiles.splice(0);
|
||||||
|
var fallbackLocale:String = profileXML.@fallbackLocale != undefined ? profileXML.@fallbackLocale.toString() : DEFAULT_FALLBACK_LOCALE;
|
||||||
|
for each (var profile:XML in profileXML.children()) {
|
||||||
|
_profiles.push(new VideoProfile(profile, fallbackLocale));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function parseConfigXml(configXML:XML):void {
|
||||||
|
var resolutionsString:String = configXML.@resolutions;
|
||||||
|
var resolutions:Array = resolutionsString.split(",");
|
||||||
|
for (var resolution in resolutions) {
|
||||||
|
var profileXml:XML = <profile></profile>
|
||||||
|
profileXml.@['id'] = resolutions[resolution];
|
||||||
|
profileXml.locale.en_US = resolutions[resolution];
|
||||||
|
profileXml.width = resolutions[resolution].split("x")[0];
|
||||||
|
profileXml.height = resolutions[resolution].split("x")[1];
|
||||||
|
profileXml.keyFrameInterval = configXML.@camKeyFrameInterval;
|
||||||
|
profileXml.modeFps = configXML.@camModeFps;
|
||||||
|
profileXml.qualityBandwidth = configXML.@camQualityBandwidth;
|
||||||
|
profileXml.qualityPicture = configXML.@camQualityPicture;
|
||||||
|
profileXml.enableH264 = configXML.@enableH264;
|
||||||
|
profileXml.h264Level = configXML.@h264Level;
|
||||||
|
profileXml.h264Profile = configXML.@h264Profile;
|
||||||
|
var profile:VideoProfile = new VideoProfile(profileXml, DEFAULT_FALLBACK_LOCALE);
|
||||||
|
_profiles.push(profile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get profiles():Array {
|
||||||
|
if (_profiles.length > 0) {
|
||||||
|
return _profiles;
|
||||||
|
} else {
|
||||||
|
return [fallbackVideoProfile];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getVideoProfileById(id:String):VideoProfile {
|
||||||
|
for each (var profile:VideoProfile in profiles) {
|
||||||
|
if (profile.id == id) {
|
||||||
|
return profile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getVideoProfileByStreamName(streamName:String):VideoProfile {
|
||||||
|
trace("stream name: " + streamName);
|
||||||
|
var pattern:RegExp = new RegExp("([a-z0-9]+)-([A-Za-z0-9_]+)-\\d+", "");
|
||||||
|
if (pattern.test(streamName)) {
|
||||||
|
var profileID:String = pattern.exec(streamName)[1]
|
||||||
|
for each (var profile:VideoProfile in _profiles) {
|
||||||
|
if (profile.id == profileID) {
|
||||||
|
return profile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get defaultVideoProfile():VideoProfile {
|
||||||
|
for each (var profile:VideoProfile in _profiles) {
|
||||||
|
if (profile.defaultProfile) {
|
||||||
|
return profile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (_profiles.length > 0) {
|
||||||
|
return _profiles[0];
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get fallbackVideoProfile():VideoProfile {
|
||||||
|
return new VideoProfile(<profile id="160x120" default="true">
|
||||||
|
<locale>
|
||||||
|
<en_US>Fallback profile</en_US>
|
||||||
|
</locale>
|
||||||
|
<width>160</width>
|
||||||
|
<height>120</height>
|
||||||
|
<keyFrameInterval>5</keyFrameInterval>
|
||||||
|
<modeFps>10</modeFps>
|
||||||
|
<qualityBandwidth>0</qualityBandwidth>
|
||||||
|
<qualityPicture>90</qualityPicture>
|
||||||
|
<enableH264>true</enableH264>
|
||||||
|
<h264Level>2.1</h264Level>
|
||||||
|
<h264Profile>main</h264Profile>
|
||||||
|
</profile>, DEFAULT_FALLBACK_LOCALE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getProfileWithLowerResolution():VideoProfile {
|
||||||
|
if (_profiles.lenth <= 0) {
|
||||||
|
return fallbackVideoProfile;
|
||||||
|
}
|
||||||
|
var lower:VideoProfile = _profiles[0];
|
||||||
|
for each (var profile:VideoProfile in _profiles) {
|
||||||
|
if (((profile.width) * (profile.height)) < ((lower.width) * (lower.height))) {
|
||||||
|
lower = profile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return lower;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
package org.bigbluebutton.lib.video.services {
|
||||||
|
import flash.net.URLRequest;
|
||||||
|
|
||||||
|
import org.bigbluebutton.lib.common.utils.URLFetcher;
|
||||||
|
import org.osflash.signals.ISignal;
|
||||||
|
import org.osflash.signals.Signal;
|
||||||
|
|
||||||
|
public class ProfilesService {
|
||||||
|
protected var _successSignal:Signal = new Signal();
|
||||||
|
|
||||||
|
protected var _unsuccessSignal:Signal = new Signal();
|
||||||
|
|
||||||
|
public function get successSignal():ISignal {
|
||||||
|
return _successSignal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get unsuccessSignal():ISignal {
|
||||||
|
return _unsuccessSignal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getProfiles(serverUrl:String, urlRequest:URLRequest):void {
|
||||||
|
var ProfileUrl:String = serverUrl + "/client/conf/profiles.xml?a=" + new Date().time;
|
||||||
|
var fetcher:URLFetcher = new URLFetcher;
|
||||||
|
fetcher.successSignal.add(onSuccess);
|
||||||
|
fetcher.failureSignal.add(onUnsuccess);
|
||||||
|
fetcher.fetch(ProfileUrl, urlRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function onSuccess(data:Object, responseUrl:String, urlRequest:URLRequest):void {
|
||||||
|
try {
|
||||||
|
successSignal.dispatch(new XML(data));
|
||||||
|
} catch (e:Error) {
|
||||||
|
onUnsuccess("invalidXml");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function onUnsuccess(reason:String):void {
|
||||||
|
unsuccessSignal.dispatch(reason);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user