package org.mconf.bbb.present;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.jboss.netty.channel.Channel;
import org.mconf.bbb.MainRtmpConnection;
import org.mconf.bbb.Module;
import org.mconf.bbb.api.ApplicationService;
import org.red5.server.api.IAttributeStore;
import org.red5.server.api.so.IClientSharedObject;
import org.red5.server.api.so.ISharedObjectBase;
import org.red5.server.api.so.ISharedObjectListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.flazr.rtmp.message.Command;
import com.flazr.rtmp.message.CommandAmf0;
public class PresentModule extends Module implements ISharedObjectListener {
private static final Logger log = LoggerFactory.getLogger(PresentModule.class);
private final IClientSharedObject presentationSO;
private String presentationName;
private int slideNumber;
public PresentModule(MainRtmpConnection handler, Channel channel) {
super(handler, channel);
presentationSO = handler.getSharedObject("presentationSO", false);
presentationSO.addSharedObjectListener(this);
presentationSO.connect(channel);
}
public void doGetPresentationInfo() {
Command cmd = new CommandAmf0("presentation.getPresentationInfo", null);
handler.writeCommandExpectingResult(channel, cmd);
}
@SuppressWarnings("unchecked")
public boolean onGetPresentationInfo(String resultFor, Command command) {
if (resultFor.equals("presentation.getPresentationInfo")) {
log.debug("onGetPresentationInfo");
Map<String, Object> presentationInfo = (Map<String, Object>) command.getArg(0);
// TODO parse out presentations and presenter info from presentationInfo object
// and store it somewhere
Object[] presentations = (Object[]) presentationInfo.get("presentations");
//String[] presentations = (String[]) presentationInfo.get("presentations");
Map<String,Object> presentation = (Map<String,Object>) presentationInfo.get("presentation");
Boolean sharing = (Boolean) presentation.get("sharing");
if (sharing) {
presentationName = (String) presentation.get("currentPresentation");
slideNumber = ((Double) presentation.get("slide")).intValue()+1;
// Problem loading slides here. When its a new room the slides aren't ready yet
loadPresentation();
}
return true;
}
return false;
}
private void loadPresentation() {
// GET slides xml
String url = "http://"+handler.getContext().getJoinService().getApplicationService().getServerUrl();
url = url + "/bigbluebutton/presentation/"
+ handler.getContext().getJoinService().getJoinedMeeting().getConference() + "/"
+ handler.getContext().getJoinService().getJoinedMeeting().getRoom() + "/"
+ presentationName + "/slides";
log.info("Loading presentation info for "+presentationName);
String result;
HttpClient client = new DefaultHttpClient();
HttpGet method = new HttpGet(url);
try {
HttpResponse httpResponse = client.execute(method);
if (httpResponse.getStatusLine().getStatusCode() == 500) {
log.debug("Slides not ready yet. Waiting for conversion.");
} else if (httpResponse.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
log.error("HTTP GET {} return {}", url, httpResponse.getStatusLine().getStatusCode());
} else {
// TODO parse out the slide info from result rather than just guessing slide info (i.e. textfile/1)
result = EntityUtils.toString(httpResponse.getEntity()).trim();
loadSlideContent("thumbnail");
loadSlideContent("textfile");
loadSlideContent("slide");
}
} catch (ClientProtocolException pe) {
log.error("Client Protocol Exception", pe);
} catch (IOException ie) {
log.error("IO Exception", ie);
} catch (Exception e) { // there are undeclared exceptions thrown by client.execute
log.error("Unknown exception", e);
}
}
private void loadSlideContent(String contentType) {
// GET thumbnail
// GET textfile
// GET slide
String url = "http://" + handler.getContext().getJoinService().getApplicationService().getServerUrl();
url = url + "/bigbluebutton/presentation/"
+ handler.getContext().getJoinService().getJoinedMeeting().getConference() + "/"
+ handler.getContext().getJoinService().getJoinedMeeting().getRoom() + "/"
+ presentationName + "/" + contentType + "/" +slideNumber;
log.info("Loading slide content for "+presentationName+"/"+contentType+"/"+slideNumber);
HttpClient client = new DefaultHttpClient();
HttpGet method = new HttpGet(url);
try {
HttpResponse httpResponse = client.execute(method);
if (httpResponse.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
log.error("HTTP GET {} return {}", url, httpResponse.getStatusLine().getStatusCode());
} else {
EntityUtils.consume(httpResponse.getEntity());
}
} catch (ClientProtocolException pe) {
log.error("Client Protocol Exception", pe);
} catch (IOException ie) {
log.error("IO Exception", ie);
}
}
@Override
public void onSharedObjectConnect(ISharedObjectBase so) {
log.debug("onSharedObjectConnect");
}
@Override
public void onSharedObjectDisconnect(ISharedObjectBase so) {
log.debug("onSharedObjectDisconnect");
}
@Override
public void onSharedObjectUpdate(ISharedObjectBase so, String key,
Object value) {
log.debug("onSharedObjectUpdate");
}
@Override
public void onSharedObjectUpdate(ISharedObjectBase so,
IAttributeStore values) {
log.debug("onSharedObjectUpdate");
}
@Override
public void onSharedObjectUpdate(ISharedObjectBase so,
Map<String, Object> values) {
log.debug("onSharedObjectUpdate");
}
@Override
public void onSharedObjectDelete(ISharedObjectBase so, String key) {
log.debug("onSharedObjectDelete");
}
@Override
public void onSharedObjectClear(ISharedObjectBase so) {
log.debug("onSharedObjectClear");
this.doGetPresentationInfo();
}
@Override
public void onSharedObjectSend(ISharedObjectBase so, String method,
List<?> params) {
log.debug("onSharedObjectSend");
log.debug("Method="+method);
if (method.equals("conversionUpdateMessageCallback") && params != null) {
} else if (method.equals("pageCountExceededUpdateMessageCallback") && params != null) {
} else if (method.equals("generatedSlideUpdateMessageCallback") && params != null) {
} else if (method.equals("conversionCompletedUpdateMessageCallback") && params != null) {
presentationName = (String) params.get(3);
slideNumber = 1;
loadPresentation();
} else if (method.equals("gotoSlideCallback") && params != null) {
slideNumber = ((Double)params.get(0)).intValue()+1;
loadSlideContent("thumbnail");
loadSlideContent("textfile");
loadSlideContent("slide");
} else if (method.equals("moveCallback") && params != null) {
} else if (method.equals("removePresentationCallback") && params != null) {
String removePresentationName = (String)params.get(0);
if (removePresentationName.equals(presentationName)) {
}
} else if (method.equals("sharePresentationCallback") && params != null) {
String shareName = (String) params.get(0); // name of presentation being shared
Boolean shared = (Boolean) params.get(1); // whether or not it is shared
if (shared) {
presentationName = shareName;
slideNumber = 1;
loadPresentation();
}
}
}
@Override
public boolean onCommand(String resultFor, Command command) {
log.debug("onCommand");
if (onGetPresentationInfo(resultFor, command)) {
return true;
} else {
return false;
}
}
}