/// <summary> /// Handle frames from Classroom Presenter when it is used as a CXP capability /// </summary> /// <param name="rtobj"></param> private void acceptCPCapabilityFrame(object rtobj) { // RTNodeChanged , RTStrokeAdd, and RTStrokeRemove contain a RTFrame which contains the CP message. if (rtobj is RTNodeChanged) { //Classroom Presenter wraps CPPageUpdate inside the RTFrame which is in turn wrapped in // the RTNodeChanged Extension. if (((RTNodeChanged)rtobj).Extension is RTFrame) { RTFrame rtf = (RTFrame)((RTNodeChanged)rtobj).Extension; if (rtf.ObjectTypeIdentifier == Constants.PageUpdateIdentifier) { if (rtf.Object is PresenterNav.CPPageUpdate) { PresenterNav.CPPageUpdate cppu = (PresenterNav.CPPageUpdate)rtf.Object; currentSlide.SetCPReference(cppu.DocRef.GUID, cppu.PageRef.Index); } } } } else if (rtobj is RTStroke) { if (((RTStroke)rtobj).Extension is RTFrame) { RTFrame rtf = (RTFrame)((RTStroke)rtobj).Extension; if (rtf.ObjectTypeIdentifier == Constants.StrokeDrawIdentifier) { if (rtf.Object is PresenterNav.CPDrawStroke) { PresenterNav.CPDrawStroke cpds = (PresenterNav.CPDrawStroke)rtf.Object; String key = SlideReference.MakeKey(cpds.DocRef.GUID, cpds.PageRef.Index); if (!slideImages.ContainsKey(key)) { slideImages.Add(key, new SlideImage()); } ((SlideImage)slideImages[key]).AddInk(cpds.Stroke.Ink, cpds.Stroke.Guid); } } } } else if (rtobj is RTStrokeAdd) { if (((RTStrokeAdd)rtobj).Extension is RTFrame) { RTFrame rtf = (RTFrame)((RTStrokeAdd)rtobj).Extension; if (rtf.ObjectTypeIdentifier == Constants.StrokeDrawIdentifier) { if (rtf.Object is PresenterNav.CPDrawStroke) { PresenterNav.CPDrawStroke cpds = (PresenterNav.CPDrawStroke)rtf.Object; String key = SlideReference.MakeKey(cpds.DocRef.GUID, cpds.PageRef.Index); if (!slideImages.ContainsKey(key)) { slideImages.Add(key, new SlideImage()); } ((SlideImage)slideImages[key]).AddInk(cpds.Stroke.Ink, cpds.Stroke.Guid); } } } } else if (rtobj is RTStrokeRemove) { if (((RTStrokeRemove)rtobj).Extension is RTFrame) { RTFrame rtf = (RTFrame)((RTStrokeRemove)rtobj).Extension; if (rtf.ObjectTypeIdentifier == Constants.StrokeDeleteIdentifier) { if (rtf.Object is PresenterNav.CPDeleteStroke) { PresenterNav.CPDeleteStroke cpds = (PresenterNav.CPDeleteStroke)rtf.Object; String key = SlideReference.MakeKey(cpds.DocRef.GUID, cpds.PageRef.Index); if (!slideImages.ContainsKey(key)) { slideImages.Add(key, new SlideImage()); } ((SlideImage)slideImages[key]).RemoveInk(cpds.Guid); } } } } //Other CP messages are sent directly in RTFrame else if (rtobj is RTFrame) { if (((RTFrame)rtobj).ObjectTypeIdentifier == Constants.CLASSROOM_PRESENTER_MESSAGE) { acceptCPNavFrame(((RTFrame)rtobj).Object); } else if (((RTFrame)rtobj).ObjectTypeIdentifier == Constants.RTDocEraseAllGuid) { //This case is a bit ugly because the RTDoc message contains no info about the deck and slide. // We need to apply to the current deck and slide (if any) if ((currentSlide.IsSet) && (slideImages.ContainsKey(currentSlide.GetStringHashCode()))) { ((SlideImage)slideImages[currentSlide.GetStringHashCode()]).RemoveAllInk(); } } } //Still other messages are in native format else if (rtobj is PresenterNav.CPMessage) { //CP still sends some messages in native format acceptCPNavFrame(rtobj); } }
/// <summary> /// Frames sent by Classroom Presenter 2.0 in Native stand-alone mode /// </summary> /// <param name="rtobj"></param> private void acceptCPNavFrame(object rtobj) { if (rtobj is PresenterNav.CPPageUpdate) { /// Presenter sends these once per second. These indicate current slide index, deck index /// and deck type. Just use this to update the current slide pointer PresenterNav.CPPageUpdate cppu = (PresenterNav.CPPageUpdate)rtobj; currentSlide.SetCPReference(cppu.DocRef.GUID, cppu.PageRef.Index); //CPPageUpdate has a deck type too, but we're not using it for now. //DumpPageUpdate((PresenterNav.CPPageUpdate)rtobj); } else if (rtobj is PresenterNav.CPScrollLayer) { ///Presenter sends these once per second, and during a scroll operation. ///Set the scroll position for the slide in question. PresenterNav.CPScrollLayer cpsl = (PresenterNav.CPScrollLayer)rtobj; String key = SlideReference.MakeKey(cpsl.DocRef.GUID, cpsl.PageRef.Index); if (!slideImages.ContainsKey(key)) { slideImages.Add(key, new SlideImage()); } ((SlideImage)slideImages[key]).SetScrollPos(cpsl.ScrollPosition, cpsl.ScrollExtent); //DumpScrollLayer((PresenterNav.CPScrollLayer)rtobj); } else if (rtobj is PresenterNav.CPDeckCollection) { //Presenter sends this once per second. The only thing we want to get from //this is the slide size (former ScreenConfiguration). This is a 'global' setting, not a per-slide setting. PresenterNav.CPDeckCollection cpdc = (PresenterNav.CPDeckCollection)rtobj; currentSlide.SetSize(cpdc.ViewPort.SlideSize); //DumpDeckCollection((PresenterNav.CPDeckCollection)rtobj); //The CPDeckCollection also has slide titles, but we don't care about them here. } else if (rtobj is WorkSpace.BeaconPacket) //the original beacon { //Presenter sends this once per second. The only thing we want to get from //this is the background color. This is another global presentation setting. WorkSpace.BeaconPacket bp = (WorkSpace.BeaconPacket)rtobj; currentSlide.SetBGColor(bp.BGColor); //DumpBeacon((BeaconPacket)rtobj); } else if (rtobj is PresenterNav.CPDrawStroke) //add a stroke { PresenterNav.CPDrawStroke cpds = (PresenterNav.CPDrawStroke)rtobj; String key = SlideReference.MakeKey(cpds.DocRef.GUID, cpds.PageRef.Index); if (!slideImages.ContainsKey(key)) { slideImages.Add(key, new SlideImage()); } ((SlideImage)slideImages[key]).AddInk(cpds.Stroke.Ink, cpds.Stroke.Guid); } else if (rtobj is PresenterNav.CPDeleteStroke) //delete one stroke { PresenterNav.CPDeleteStroke cpds = (PresenterNav.CPDeleteStroke)rtobj; String key = SlideReference.MakeKey(cpds.DocRef.GUID, cpds.PageRef.Index); if (!slideImages.ContainsKey(key)) { slideImages.Add(key, new SlideImage()); } ((SlideImage)slideImages[key]).RemoveInk(cpds.Guid); } else if (rtobj is PresenterNav.CPEraseLayer) //clear all strokes from one page { PresenterNav.CPEraseLayer cpel = (PresenterNav.CPEraseLayer)rtobj; String key = SlideReference.MakeKey(cpel.DocRef.GUID, cpel.PageRef.Index); if (!slideImages.ContainsKey(key)) { slideImages.Add(key, new SlideImage()); } ((SlideImage)slideImages[key]).RemoveAllInk(); } else if (rtobj is PresenterNav.CPEraseAllLayers) //clear all strokes from a deck { PresenterNav.CPEraseAllLayers cpeal = (PresenterNav.CPEraseAllLayers)rtobj; if (cpeal.DocRef.GUID != Guid.Empty) { foreach (String key in slideImages.Keys) { if (key.StartsWith(cpeal.DocRef.GUID.ToString())) { ((SlideImage)slideImages[key]).RemoveAllInk(); } } } } else if (rtobj is WorkSpace.OverlayMessage) //Student submission received { //These are seen when Student Submissions are submitted to the instructor, not when they are displayed. WorkSpace.OverlayMessage om = (WorkSpace.OverlayMessage)rtobj; String key = SlideReference.MakeKey(om.FeedbackDeck.GUID, om.SlideIndex.Index); if (!slideImages.ContainsKey(key)) { slideImages.Add(key, new SlideImage()); } //The slide image comes from a presentation slide. Here we want to store the current slide image. String refKey = SlideReference.MakeKey(om.PresentationDeck.GUID, om.PDeckSlideIndex.Index); if (slideImages.ContainsKey(refKey)) { SlideImage sourceImage = (SlideImage)slideImages[refKey]; bool isWhiteboard = true; Image img = sourceImage.GetSlideImage(this.currentSlide.BGColor, out isWhiteboard); ((SlideImage)slideImages[key]).SetImage(img, isWhiteboard); } //Add the ink from the student submission //OtherScribble appears to contain both student ink and any pre-existing instructor ink, but I think it //used to be in UserScribble. Let's include all ink in both scribbles. ((SlideImage)slideImages[key]).AddInk(((SlideViewer.InkScribble)om.SlideOverlay.UserScribble).Ink); ((SlideImage)slideImages[key]).AddInk(((SlideViewer.InkScribble)om.SlideOverlay.OtherScribble).Ink); } else if (rtobj is WorkSpace.ScreenConfigurationMessage) { // nothing to do here. } else { Type t = rtobj.GetType(); Debug.WriteLine("Unhandled Type:" + t.ToString()); } }