This commit is contained in:
Markos Calderon 2013-03-07 15:20:55 -05:00
commit 058c9fda8f
21 changed files with 175 additions and 49 deletions

View File

@ -44,7 +44,7 @@ Configure the properties
sudo vi /var/lib/tomcat6/webapps/lti/WEB-INF/classes/lti.properties
Edit the URL and Salt of the BigBlueButton server you are going to connect to
Edit the URL and Salt of the BigBlueButton server you are going to connect to (NOTE: Remove any trailing slashes from the URL!)
bigbluebuttonURL=http://yourbigbluebuttonserver.com/bigbluebutton

View File

@ -74,6 +74,18 @@ class ToolController {
String welcome = message(code: "bigbluebutton.welcome", args: ["\"{0}\"", "\"{1}\""])
log.debug "Localized default welcome message: [" + welcome + "]"
// Check for [custom_]welcome parameter being passed from the LTI
if (params.get(Parameter.CUSTOM_WELCOME) != null) {
log.debug "A custom welcome message has been provided"
welcome = params.get(Parameter.CUSTOM_WELCOME)
log.debug "Overriding default welcome message with: [" + welcome + "]"
}
// Detect if the LTI has requested recording
if (params.get(Parameter.CUSTOM_RECORD) == "true") {
log.debug "This session will be recorded!"
}
//String destinationURL = "http://www.bigbluebutton.org/"
String destinationURL = bigbluebuttonService.getJoinURL(params, welcome)

View File

@ -86,13 +86,14 @@ class BigbluebuttonService {
String userFullName = getValidatedUserFullName(params, isModerator)
String courseTitle = getValidatedCourseTitle(params.get(Parameter.COURSE_TITLE))
String userID = getValidatedUserId(params.get(Parameter.USER_ID))
String record = getValidatedRecord(params.get(Parameter.CUSTOM_RECORD))
String[] values = [meetingName, courseTitle]
String welcomeMsg = MessageFormat.format(welcome, values)
String meta = getMonitoringMetaData(params)
String createURL = getCreateURL( meetingName, meetingID, attendeePW, moderatorPW, welcomeMsg, logoutURL, meta )
String createURL = getCreateURL( meetingName, meetingID, attendeePW, moderatorPW, welcomeMsg, logoutURL, record, meta )
//log.debug "createURL: " + createURL
Map<String, Object> createResponse = doAPICall(createURL)
//log.debug "createResponse: " + createResponse
@ -110,10 +111,10 @@ class BigbluebuttonService {
}
private String getCreateURL(String name, String meetingID, String attendeePW, String moderatorPW, String welcome, String logoutURL, String meta ) {
private String getCreateURL(String name, String meetingID, String attendeePW, String moderatorPW, String welcome, String logoutURL, String record, String meta ) {
Integer voiceBridge = 70000 + new Random(System.currentTimeMillis()).nextInt(10000);
String url = bbbProxy.getCreateURL(name, meetingID, attendeePW, moderatorPW, welcome, "", voiceBridge.toString(), "", logoutURL, "", "", "", meta );
String url = bbbProxy.getCreateURL(name, meetingID, attendeePW, moderatorPW, welcome, "", voiceBridge.toString(), "", logoutURL, "", record, "", meta );
return url;
}
@ -157,6 +158,10 @@ class BigbluebuttonService {
return (userId == null)? "": userId
}
private String getValidatedRecord(String record){
return (record != "true")? "": record
}
private String getMonitoringMetaData(params){
String meta

View File

@ -47,6 +47,8 @@ public class Parameter {
public static final String TOOL_CONSUMER_INSTANCE_URL = "tool_consumer_instance_url";
public static final String CUSTOM_USER_ID = "custom_lis_person_sourcedid";
public static final String CUSTOM_WELCOME = "custom_welcome";
public static final String CUSTOM_RECORD = "custom_record";
}

View File

@ -46,11 +46,15 @@ public class Role {
for( int i=0; i < roles.length; i++){
if( roles[i].equals(FACULTY) ||
roles[i].equals(URN_INSTITUTION_ROLE + FACULTY) ||
roles[i].equals(URN_CONTEXT_ROLE + FACULTY) ||
roles[i].equals(INSTRUCTOR) ||
roles[i].equals(URN_INSTITUTION_ROLE + INSTRUCTOR) ||
roles[i].equals(URN_CONTEXT_ROLE + INSTRUCTOR) ||
roles[i].equals(MENTOR) ||
roles[i].equals(URN_INSTITUTION_ROLE + MENTOR) ||
roles[i].equals(URN_INSTITUTION_ROLE + ADMINISTRATOR)
roles[i].equals(URN_CONTEXT_ROLE + MENTOR) ||
roles[i].equals(URN_INSTITUTION_ROLE + ADMINISTRATOR) ||
roles[i].equals(URN_CONTEXT_ROLE + ADMINISTRATOR)
){
response = true;
break;

View File

@ -48,6 +48,7 @@ public class ConferenceService implements ConferenceEventListener {
}
public void destroyConference(String room) {
confProvider.ejectAll(room);
roomMgr.destroyRoom(room);
}

View File

@ -26,6 +26,7 @@ public interface ConferenceServiceProvider {
public void populateRoom(String room);
public void mute(String room, Integer participant, Boolean mute);
public void eject(String room, Integer participant);
public void ejectAll(String room);
public void record(String room, String meetingid);
public void broadcast(String room, String meetingid);
public void setConferenceEventListener(ConferenceEventListener l);

View File

@ -19,8 +19,6 @@
package org.bigbluebutton.webconference.voice.freeswitch;
import java.io.File;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Observable;
@ -33,6 +31,7 @@ import org.bigbluebutton.webconference.voice.events.ParticipantMutedEvent;
import org.bigbluebutton.webconference.voice.events.ParticipantTalkingEvent;
import org.bigbluebutton.webconference.voice.events.StartRecordingEvent;
import org.bigbluebutton.webconference.voice.freeswitch.actions.BroadcastConferenceCommand;
import org.bigbluebutton.webconference.voice.freeswitch.actions.EjectAllUsersCommand;
import org.bigbluebutton.webconference.voice.freeswitch.actions.EjectParticipantCommand;
import org.bigbluebutton.webconference.voice.freeswitch.actions.PopulateRoomCommand;
import org.bigbluebutton.webconference.voice.freeswitch.actions.MuteParticipantCommand;
@ -150,6 +149,20 @@ public class FreeswitchApplication extends Observable implements ConferenceServi
}
}
@Override
public void ejectAll(String room) {
Client c = manager.getESLClient();
if (c.canSend()) {
EjectAllUsersCommand mpc = new EjectAllUsersCommand(room, USER);
String jobId = c.sendAsyncApiCommand( mpc.getCommand(), mpc.getCommandArgs());
log.debug("eject all user from room [{}], jobid [{}]", room, jobId);
}else {
log.warn("Can't send eject request to FreeSWITCH as we are not connected.");
// Let's see if we can recover the connection.
startHeartbeatMonitor();
}
}
@Override
public void record(String room, String meetingid){
String RECORD_DIR = "/var/freeswitch/meetings";

View File

@ -50,6 +50,11 @@ public class FreeswitchServiceProvider implements ConferenceServiceProvider {
appDelegate.eject(room, participant);
}
@Override
public void ejectAll(String room) {
appDelegate.ejectAll(room);
}
@Override
public void mute(String room, Integer participant, Boolean mute) {
appDelegate.mute(room, participant, mute);
@ -111,4 +116,6 @@ public class FreeswitchServiceProvider implements ConferenceServiceProvider {
conferenceEventListener = l;
appDelegate.setConferenceEventListener(conferenceEventListener);
}
}

View File

@ -0,0 +1,31 @@
/**
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
*
* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation; either version 3.0 of the License, or (at your option) any later
* version.
*
* BigBlueButton 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along
* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
*
*/
package org.bigbluebutton.webconference.voice.freeswitch.actions;
public class EjectAllUsersCommand extends FreeswitchCommand {
public EjectAllUsersCommand(String room, Integer requesterId) {
super(room, requesterId);
}
@Override
public String getCommandArgs() {
return room + " kick all";
}
}

View File

@ -16,6 +16,7 @@
<window name="PresentationWindow" width="0.5137481910274964" height="0.9946808510638298" x="0.18017366136034732" y="0" />
<window name="VideoDock" width="0.1772793053545586" height="0.30851063829787234" x="0" y="0.6875" />
<window name="ChatWindow" width="0.3031837916063676" height="0.9960106382978723" x="0.6968162083936325" y="0" />
<window name="ParticipantsWindow" width="0.1772793053545586" height="0.6795212765957446" x="0" y="0" />
<window name="ViewersWindow" width="0.1772793053545586" height="0.33643617021276595" x="0" y="0" />
<window name="ListenersWindow" width="0.1772793053545586" height="0.33643617021276595" x="0" y="0.34308510638297873" />
</layout>

View File

@ -39,6 +39,8 @@ package org.bigbluebutton.main.events {
public static const USER_VOICE_TALKING:String = "user voice talking event";
public static const CAMERA_SETTING:String = "camera settings event";
public static const OPEN_WEBCAM_PREVIEW:String = "open webcam preview event";
public static const MIC_SETTINGS_CLOSED:String = "MIC_SETTINGS_CLOSED";
public static const CAM_SETTINGS_CLOSED:String = "CAM_SETTINGS_CLOSED";
public var message:String;
public var payload:Object = new Object();

View File

@ -224,6 +224,9 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
private function onCancelClicked():void {
disableCamera();
var event:BBBEvent = new BBBEvent(BBBEvent.CAM_SETTINGS_CLOSED);
event.payload['clicked'] = "cancel";
dispatchEvent(event);
PopUpManager.removePopUp(this);
}

View File

@ -129,7 +129,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
private function onCancelClicked():void {
cleanUp();
var event:BBBEvent = new BBBEvent("MIC_SETTINGS_CLOSED");
var event:BBBEvent = new BBBEvent(BBBEvent.MIC_SETTINGS_CLOSED);
event.payload['clicked'] = "cancel";
dispatchEvent(event);
PopUpManager.removePopUp(this);

View File

@ -23,6 +23,9 @@ package org.bigbluebutton.modules.listeners.business
import mx.collections.ArrayCollection;
import mx.controls.Alert;
import org.bigbluebutton.core.UsersUtil;
import org.bigbluebutton.main.model.users.BBBUser;
import org.bigbluebutton.main.model.users.events.KickUserEvent;
import org.bigbluebutton.modules.listeners.business.vo.Listeners;
import org.bigbluebutton.modules.listeners.events.ListenersCommand;
import org.bigbluebutton.modules.listeners.events.ListenersEvent;
@ -111,6 +114,11 @@ package org.bigbluebutton.modules.listeners.business
_listenersService.muteAllUsers(false);
}
public function kickUser(event:KickUserEvent):void {
var user:BBBUser = UsersUtil.getUser(event.userid);
_listenersService.ejectUser(user.voiceUserid);
}
public function ejectUser(command:ListenersCommand):void
{
_listenersService.ejectUser(command.userid);

View File

@ -25,6 +25,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
<![CDATA[
import mx.events.FlexEvent;
import org.bigbluebutton.main.model.users.events.KickUserEvent;
import org.bigbluebutton.modules.listeners.business.ListenersProxy;
import org.bigbluebutton.modules.listeners.events.ListenersCommand;
import org.bigbluebutton.modules.listeners.events.StartListenersModuleEvent;
@ -49,6 +50,10 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
<MethodInvoker generator="{ListenersManager}" method="moduleEnded" />
</EventHandlers>
<EventHandlers type="{KickUserEvent.KICK_USER}" >
<MethodInvoker generator="{ListenersProxy}" method="kickUser" arguments="{event}" />
</EventHandlers>
<EventHandlers type="{ListenersCommand.EJECT_USER}" >
<MethodInvoker generator="{ListenersProxy}" method="ejectUser" arguments="{event}" />
</EventHandlers>

View File

@ -22,11 +22,14 @@ package org.bigbluebutton.modules.participants.business
import mx.collections.ArrayCollection;
import org.bigbluebutton.core.UsersUtil;
import org.bigbluebutton.core.managers.UserManager;
import org.bigbluebutton.modules.participants.events.VoiceConfEvent;
import org.bigbluebutton.main.model.users.BBBUser;
import org.bigbluebutton.main.model.users.events.KickUserEvent;
import org.bigbluebutton.modules.participants.events.ParticipantsEvent;
import org.bigbluebutton.modules.participants.events.StartParticipantsModuleEvent;
import org.bigbluebutton.modules.participants.events.StopParticipantsModuleEvent;
import org.bigbluebutton.modules.participants.events.VoiceConfEvent;
public class ParticipantsProxy
{
@ -86,6 +89,11 @@ package org.bigbluebutton.modules.participants.business
_listenersService.muteAllUsers(false);
}
public function kickUser(event:KickUserEvent):void {
var user:BBBUser = UsersUtil.getUser(event.userid);
_listenersService.ejectUser(user.voiceUserid);
}
public function ejectUser(command:VoiceConfEvent):void
{
_listenersService.ejectUser(command.userid);

View File

@ -24,7 +24,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
<mx:Script>
<![CDATA[
import mx.events.FlexEvent;
import org.bigbluebutton.main.model.users.events.KickUserEvent;
import org.bigbluebutton.modules.participants.business.ParticipantsProxy;
import org.bigbluebutton.modules.participants.events.VoiceConfEvent;
import org.bigbluebutton.modules.participants.events.StartParticipantsModuleEvent;
@ -49,6 +49,11 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
<MethodInvoker generator="{ParticipantsManager}" method="moduleEnded" />
</EventHandlers>
<EventHandlers type="{KickUserEvent.KICK_USER}" >
<MethodInvoker generator="{ParticipantsProxy}" method="kickUser" arguments="{event}" />
</EventHandlers>
<EventHandlers type="{VoiceConfEvent.EJECT_USER}" >
<MethodInvoker generator="{ParticipantsProxy}" method="ejectUser" arguments="{event}" />
</EventHandlers>

View File

@ -31,6 +31,7 @@
<mate:Listener type="{ShortcutEvent.RAISE_HAND}" method="remoteRaiseHand" />
<mate:Listener type="{ShortcutEvent.FOCUS_PARTICIPANTS_WINDOW}" method="focusWindow" />
<mate:Listener type="{ShortcutEvent.MUTE_ME_EVENT}" method="toggleMuteMeState" />
<mate:Listener type="{ParticipantsEvent.ROOM_MUTE_STATE}" method="setRoomMute" />
<mx:Script>
<![CDATA[
import com.asfusion.mate.events.Dispatcher;
@ -60,6 +61,7 @@
import org.bigbluebutton.main.views.MainCanvas;
import org.bigbluebutton.modules.participants.events.ParticipantRollEvent;
import org.bigbluebutton.modules.participants.events.VoiceConfEvent;
import org.bigbluebutton.modules.participants.events.ParticipantsEvent;
import org.bigbluebutton.modules.participants.model.ParticipantsOptions;
import org.bigbluebutton.util.i18n.ResourceUtil;
@ -68,6 +70,7 @@
private var keyCombos:Object;
private var modifier:String;
private var roomMuted:Boolean = false;
private var myMenu:Menu;
[Bindable]
@ -170,9 +173,12 @@
// everyone can see the audio settings
var myMenuData:Array = [{label: "Audio Settings", icon: images.audio}];
if (UserManager.getInstance().getConference().amIPresenter || amIModerator) {
if (amIModerator) {
myMenuData[1] = {type: "separator"};
if (!roomMuted)
myMenuData[2] = {label: "Mute All", icon: images.audio_muted};
else
myMenuData[2] = {label: "Unmute All", icon: images.audio};
myMenuData[3] = {label: "Lower All Hands", icon: images.hand_new};
}
@ -208,18 +214,22 @@
Security.showSettings(SecurityPanel.MICROPHONE);
}
private function setRoomMute(e:ParticipantsEvent):void {
roomMuted = e.mute_state;
}
private function muteAll():void {
// I can't do this one yet without access to the shared object
// it would be something like
/*
if (everyone's unmuted) {
if (amIModerator) {
if (!roomMuted) {
var muteCommand:VoiceConfEvent = new VoiceConfEvent(VoiceConfEvent.MUTE_ALL);
dispatchEvent(muteCommand);
roomMuted = true;
} else {
var muteCommand:VoiceConfEvent = new VoiceConfEvent(VoiceConfEvent.UNMUTE_ALL);
dispatchEvent(muteCommand);
var unmuteCommand:VoiceConfEvent = new VoiceConfEvent(VoiceConfEvent.UNMUTE_ALL);
dispatchEvent(unmuteCommand);
roomMuted = false;
}
}
*/
}
private function lowerHands():void {

View File

@ -28,7 +28,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
implements="org.bigbluebutton.common.IBbbToolbarComponent">
<mate:Listener type="{BBBEvent.JOIN_VOICE_CONFERENCE}" method="handleBBBJoinConferenceEvent"/>
<mate:Listener type="MIC_SETTINGS_CLOSED" method="handleMicSettingsClosedEvent"/>
<mate:Listener type="{BBBEvent.MIC_SETTINGS_CLOSED}" method="handleMicSettingsClosedEvent"/>
<mate:Listener type="{ShortcutEvent.SHARE_MICROPHONE}" method="remoteClick" />

View File

@ -25,21 +25,25 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
click="openPublishWindow()" creationComplete="init()"
mouseOver = "mouseOverHandler(event)"
mouseOut = "mouseOutHandler(event)"
toolTip="{ResourceUtil.getInstance().getString('bbb.toolbar.video.toolTip.start')}"
toolTip="{this.selected ? ResourceUtil.getInstance().getString('bbb.toolbar.video.toolTip.stop') : ResourceUtil.getInstance().getString('bbb.toolbar.video.toolTip.start')}"
visible="{isPresenter}"
implements="org.bigbluebutton.common.IBbbToolbarComponent">
<mate:Listener type="{ShortcutEvent.SHARE_WEBCAM}" method="remoteClick" />
<mate:Listener type="{BBBEvent.CAM_SETTINGS_CLOSED}" method="handleCamSettingsClosedEvent"/>
<mate:Listener type="{ShareCameraRequestEvent.SHARE_CAMERA_REQUEST}" receive="enabled=false" />
<mx:Script>
<![CDATA[
import com.asfusion.mate.events.Dispatcher;
import org.bigbluebutton.common.Images;
import org.bigbluebutton.main.views.MainToolbar;
import org.bigbluebutton.modules.videoconf.events.ShareCameraRequestEvent;
import org.bigbluebutton.modules.videoconf.events.ClosePublishWindowEvent;
import org.bigbluebutton.util.i18n.ResourceUtil;
import org.bigbluebutton.main.events.BBBEvent;
import org.bigbluebutton.main.events.ShortcutEvent;
import org.bigbluebutton.main.views.MainToolbar;
import org.bigbluebutton.modules.videoconf.events.ClosePublishWindowEvent;
import org.bigbluebutton.modules.videoconf.events.ShareCameraRequestEvent;
import org.bigbluebutton.util.i18n.ResourceUtil;
[Bindable] public var isPresenter:Boolean;
@ -74,14 +78,14 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
public function publishingStatus(status:Number):void {
if(status == START_PUBLISHING) {
_currentState = ON_STATE;
this.toolTip = ResourceUtil.getInstance().getString('bbb.toolbar.video.toolTip.stop');
//this.toolTip = ResourceUtil.getInstance().getString('bbb.toolbar.video.toolTip.stop');
camIcon = images.webcamOn;
this.enabled = true;
this.selected = true;
}
else {
_currentState = OFF_STATE;
this.toolTip = ResourceUtil.getInstance().getString('bbb.toolbar.video.toolTip.start');
//this.toolTip = ResourceUtil.getInstance().getString('bbb.toolbar.video.toolTip.start');
camIcon = images.webcam;
this.enabled = true;
this.selected = false;
@ -92,20 +96,26 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
private function openPublishWindow():void{
if(_currentState == ON_STATE) {
_currentState = OFF_STATE;
this.toolTip = ResourceUtil.getInstance().getString('bbb.toolbar.video.toolTip.start');
//this.toolTip = ResourceUtil.getInstance().getString('bbb.toolbar.video.toolTip.start');
camIcon = images.webcam;
this.selected = false;
dispatchEvent(new ClosePublishWindowEvent());
}
else {
_currentState = ON_STATE;
this.toolTip = ResourceUtil.getInstance().getString('bbb.toolbar.video.toolTip.stop');
//this.toolTip = ResourceUtil.getInstance().getString('bbb.toolbar.video.toolTip.stop');
camIcon = images.webcamOn;
this.selected = true;
dispatchEvent(new ShareCameraRequestEvent());
}
}
private function handleCamSettingsClosedEvent(e:BBBEvent):void {
this.enabled = true;
this.selected = false;
_currentState = OFF_STATE;
camIcon = images.webcam;
}
private function mouseOverHandler(event:MouseEvent):void {
if(_currentState == ON_STATE)
@ -131,6 +141,4 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
}
]]>
</mx:Script>
<mate:Listener type="{ShareCameraRequestEvent.SHARE_CAMERA_REQUEST}" receive="enabled=false" />
</mx:Button>