コード例 #1
0
ファイル: PresenterModule.cs プロジェクト: DeSciL/Ogama
    /// <summary>
    /// This method steps through each of the stop conditions of the current slide.
    ///   If any of them matches the current state, check for
    ///   response correctness and set bChangeStimulus=true;
    /// </summary>
    /// <param name="slideContainer">
    /// The <see cref="SlidePresentationContainer"/> for which the slide should be parsed.
    /// </param>
    /// <param name="changeSlide">
    /// Out. <strong>True</strong> if new slide should be shown.
    /// </param>
    /// <param name="response">
    /// Out. The <see cref="StopCondition"/> that ended the slide.
    /// </param>
    private void CheckResponses(
      SlidePresentationContainer slideContainer,
      out bool changeSlide,
      out StopCondition response)
    {
      changeSlide = false;
      response = null;

      foreach (StopCondition condition in slideContainer.Slide.StopConditions)
      {
        if (condition is MouseStopCondition)
        {
          var msc = (MouseStopCondition)condition;
          if ((msc.CanBeAnyInputOfThisType && this.currentMousebutton != MouseButtons.None)
              || (this.currentMousebutton == msc.StopMouseButton))
          {
            foreach (VGElement shape in slideContainer.Slide.TargetShapes)
            {
              if (shape.Contains(this.PointToClient(MousePosition)))
              {
                response = new MouseStopCondition(msc.StopMouseButton, false, shape.Name, null, MousePosition);
                if (msc.Target != string.Empty && (shape.Name == msc.Target || msc.Target == "Any"))
                {
                  changeSlide = true;
                }

                break;
              }
            }

            if (msc.Target == string.Empty)
            {
              changeSlide = true;
              if (response == null)
              {
                response = new MouseStopCondition(msc.StopMouseButton, false, string.Empty, null, MousePosition);
              }
            }

            if (changeSlide)
            {
              // Check testing condition if specified.
              foreach (StopCondition correctCondition in slideContainer.Slide.CorrectResponses)
              {
                if (msc.Equals(correctCondition))
                {
                  response.IsCorrectResponse = true;
                  break;
                }

                response.IsCorrectResponse = false;
              }

              this.currentMousebutton = MouseButtons.None;
            }
          }
        }
        else if (condition is KeyStopCondition)
        {
          var ksc = (KeyStopCondition)condition;
          if ((ksc.CanBeAnyInputOfThisType && this.currentKey != Keys.None) || (this.currentKey == ksc.StopKey))
          {
            changeSlide = true;
            response = new KeyStopCondition(ksc.StopKey, false, null);

            // Check testing condition if specified.
            if (slideContainer.Slide.CorrectResponses != null)
            {
              // Check testing condition if specified.
              foreach (StopCondition correctCondition in slideContainer.Slide.CorrectResponses)
              {
                if (ksc.Equals(correctCondition))
                {
                  response.IsCorrectResponse = true;
                  break;
                }

                response.IsCorrectResponse = false;
              }
            }

            this.currentKey = Keys.None;
            break;
          }
        }
      }
    }
コード例 #2
0
ファイル: PresenterModule.cs プロジェクト: DeSciL/Ogama
    /// <summary>
    /// This method scans the <see cref="SlidePresentationContainer.ElementsWithAudioOnClick"/>
    ///   for an element that was clicked and plays it if it was the case.
    /// </summary>
    /// <param name="slideContainer">
    /// The <see cref="SlidePresentationContainer"/> to search for audio files.
    /// </param>
    /// <param name="point">
    /// A <see cref="Point"/> with the click location.
    /// </param>
    /// <param name="eventTime">
    /// A <see cref="Int64"/> with the timestamp of the mouse click.
    /// </param>
    private void CheckforAudioStimulusOnClick(SlidePresentationContainer slideContainer, Point point, long eventTime)
    {
      foreach (VGElement element in slideContainer.ElementsWithAudioOnClick)
      {
        if (element.Contains(point))
        {
          slideContainer.AudioPlayer.AddAudioChannel(element.Sound.FullFilename);
          if (slideContainer.AudioPlayer.PlayState != PlayState.Running)
          {
            slideContainer.AudioPlayer.Play();
          }

          var soundEvent = new MediaEvent();
          soundEvent.Type = EventType.Audio;
          soundEvent.Task = MediaEventTask.Start;
          soundEvent.Param = Path.GetFileName(element.Sound.Filename);
          this.OnTrialEventOccured(new TrialEventOccuredEventArgs(soundEvent, eventTime));

          break;
        }
      }
    }
コード例 #3
0
ファイル: PresenterModule.cs プロジェクト: DeSciL/Ogama
 /// <summary>
 /// This method parses the given <see cref="VGElement"/>
 ///   for sound files and fills them in the <see cref="OgamaControls.AudioPlayer"/>.
 ///   If they should be played on click, they are stored in the
 ///   <see cref="SlidePresentationContainer.ElementsWithAudioOnClick"/> list.
 /// </summary>
 /// <param name="slideContainer">
 /// The <see cref="SlidePresentationContainer"/>
 ///   this element belongs to.
 /// </param>
 /// <param name="element">
 /// The <see cref="VGElement"/> to search for audio content
 /// </param>
 private static void ParseElementForAudio(SlidePresentationContainer slideContainer, VGElement element)
 {
   if (element.Sound != null && element.Sound.ShouldPlay)
   {
     if (!element.Sound.ShowOnClick)
     {
       slideContainer.AudioPlayer.AddAudioChannel(element.Sound.FullFilename);
     }
     else
     {
       slideContainer.ElementsWithAudioOnClick.Add(element);
     }
   }
 }
コード例 #4
0
ファイル: PresenterModule.cs プロジェクト: DeSciL/Ogama
    /// <summary>
    /// This method checks the <see cref="Slide.Links"/> collection,
    ///   if the given response is in it, if so it sets the newTrialID
    ///   ouput parameter, otherwise it will be -1.
    /// </summary>
    /// <param name="slideContainer">
    /// The <see cref="SlidePresentationContainer"/> for which to check the links for.
    /// </param>
    /// <param name="response">
    /// A <see cref="StopCondition"/> with the current response.
    /// </param>
    /// <param name="isLink">
    /// Out. <strong>True</strong> if this response is a link, otherwise <strong>false</strong>.
    /// </param>
    /// <param name="newTrialID">
    /// Out. An <see cref="Int32"/> with the new trial ID to link to.
    /// </param>
    private void CheckLinks(
      SlidePresentationContainer slideContainer,
      StopCondition response,
      out bool isLink,
      out int newTrialID)
    {
      isLink = false;
      newTrialID = -1;
      foreach (StopCondition condition in slideContainer.Slide.Links)
      {
        if (condition is MouseStopCondition && response is MouseStopCondition)
        {
          var linkMsc = (MouseStopCondition)condition;
          var responseMsc = (MouseStopCondition)response;
          if (linkMsc.StopMouseButton == responseMsc.StopMouseButton && linkMsc.Target == responseMsc.Target)
          {
            if (linkMsc.TrialID != null)
            {
              newTrialID = linkMsc.TrialID.Value;
            }

            isLink = true;
            break;
          }
        }
        else if (condition is KeyStopCondition && response is KeyStopCondition)
        {
          var linkKsc = (KeyStopCondition)condition;
          var responseKsc = (KeyStopCondition)response;
          if (linkKsc.StopKey == responseKsc.StopKey)
          {
            if (linkKsc.TrialID != null)
            {
              newTrialID = linkKsc.TrialID.Value;
            }

            isLink = true;
            break;
          }
        }
      }
    }
コード例 #5
0
ファイル: PresenterModule.cs プロジェクト: DeSciL/Ogama
    /// <summary>
    /// This method setups the mouse cursor of the new slide.
    ///   Its sets the position and visibility of the cursor.
    /// </summary>
    /// <param name="slideContainer">
    /// The <see cref="SlidePresentationContainer"/>
    ///   that should be initialized.
    /// </param>
    private void SetupMouse(SlidePresentationContainer slideContainer)
    {
      // Show or hide mouse cursor at specified position.
      if (slideContainer.Slide.MouseCursorVisible)
      {
        // Reset the cursor position to initial location if applicable
        if (slideContainer.Slide.ForceMousePositionChange)
        {
          var newPoint = new Point(
            slideContainer.Slide.MouseInitialPosition.X + this.presentationBounds.Left,
            slideContainer.Slide.MouseInitialPosition.Y + this.presentationBounds.Top);
          Cursor.Position = newPoint;
        }

        if (this.hiddenCursor)
        {
          Cursor.Show();
          this.hiddenCursor = false;
        }
      }
      else
      {
        if (!this.hiddenCursor)
        {
          Cursor.Hide();
          this.hiddenCursor = true;
        }
      }
    }
コード例 #6
0
ファイル: PresenterModule.cs プロジェクト: DeSciL/Ogama
    /// <summary>
    ///   Initializes a new instance of the PresenterModule class.
    /// </summary>
    public PresenterModule()
    {
      this.InitializeComponent();

      this.nfi = new CultureInfo("en-US", false).NumberFormat;
      this.nfi.NumberGroupSeparator = string.Empty;

      // Retrieves the BufferedGraphicsContext for the 
      // current application domain.
      this.context = BufferedGraphicsManager.Current;

      // Sets the maximum size for the primary graphics buffer
      // of the buffered graphics context for the application
      // domain.  Any allocation requests for a buffer larger 
      // than this will create a temporary buffered graphics 
      // context to host the graphics buffer.
      this.context.MaximumBuffer = new Size(this.Width + 1, this.Height + 1);

      this.preparedSlideOne = new SlidePresentationContainer { ContainerControl = this.panelOne };

      // Allocates a graphics buffer the size of this form
      // using the pixel format of the Graphics created by 
      // the Form.CreateGraphics() method, which returns a 
      // Graphics object that matches the pixel format of the form.
      var width = Document.ActiveDocument.ExperimentSettings.WidthStimulusScreen;
      var height = Document.ActiveDocument.ExperimentSettings.HeightStimulusScreen;

      this.preparedSlideOne.DrawingSurface = this.context.Allocate(
        this.panelOne.CreateGraphics(),
        new Rectangle(0, 0, width, height));
      this.panelOne.DrawingSurface = this.preparedSlideOne.DrawingSurface;

      this.preparedSlideTwo = new SlidePresentationContainer();
      this.preparedSlideTwo.ContainerControl = this.panelTwo;
      this.preparedSlideTwo.DrawingSurface = this.context.Allocate(
        this.panelTwo.CreateGraphics(),
        new Rectangle(0, 0, width, height));
      this.panelTwo.DrawingSurface = this.preparedSlideTwo.DrawingSurface;

      this.keyboardCallback = this.KeyboardHookCallback;
      this.mouseCallback = this.MouseHookCallback;
    }
コード例 #7
0
ファイル: PresenterModule.cs プロジェクト: DeSciL/Ogama
    /// <summary>
    ///   This method swaps the slide buffers by swapping the
    ///   position of the controls panelOne and panelTwo and
    ///   updating the shownSlide.
    /// </summary>
    private void PresentPreparedSlide()
    {
      // Detach scroll event listeners
      if (this.shownSlideContainer != null)
      {
        foreach (VGElement element in this.shownSlideContainer.Slide.ActiveXStimuli)
        {
          if (element is VGBrowser)
          {
            var browser = element as VGBrowser;
            try
            {
              browser.WebBrowser.NewWindow -= this.WebBrowser_NewWindow;
              if (browser.WebBrowser.Document != null)
              {
                if (browser.WebBrowser.Document.Window != null)
                {
                  // browser.WebBrowser.Document.Window.Scroll -= this.WebBrowserScroll;
                }

                browser.WebBrowser.DocumentCompleted -= this.WebBrowserDocumentCompleted;
                browser.WebBrowser.Navigating -= this.WebBrowserNavigating;
                browser.WebBrowser.Document.MouseDown -= this.WebBrowserMouseDown;
              }
            }
            catch (NullReferenceException ex)
            {
              ExceptionMethods.HandleExceptionSilent(ex);
            }
          }
        }
      }

      switch (this.shownContainer)
      {
        case ShownContainer.One:
          this.Controls.SetChildIndex(this.panelTwo, 0);
          this.shownSlideContainer = this.preparedSlideTwo;
          this.shownContainer = ShownContainer.Two;
          break;
        case ShownContainer.None:
        case ShownContainer.Two:
          this.Controls.SetChildIndex(this.panelOne, 0);
          this.shownSlideContainer = this.preparedSlideOne;
          this.shownContainer = ShownContainer.One;
          break;
      }

      // Care for desktop recording slides
      var slidePresentationContainer = this.shownSlideContainer;
      if (slidePresentationContainer != null && slidePresentationContainer.Slide.IsDesktopSlide)
      {
        this.WindowState = FormWindowState.Minimized;
        this.keyboardHookID = MessageHook.SetKeyboardHook(this.keyboardCallback);
        this.mouseHookID = MessageHook.SetMouseHook(this.mouseCallback);
      }
      else
      {
        this.WindowState = FormWindowState.Maximized;
      }

      // Reset response fields
      this.currentMousebutton = MouseButtons.None;
      this.currentKey = Keys.None;

      // Need a refresh here because otherwise the video
      // capture will be started before the screen has been redrawn
      // and it would start with a frame of the old
      // slide.
      this.Refresh();

      if (this.shownSlideContainer.Timer.Period > 1)
      {
        this.shownSlideContainer.Timer.Start();
      }
    }
コード例 #8
0
ファイル: PresenterModule.cs プロジェクト: DeSciL/Ogama
    /// <summary>
    /// This method sends trigger signals to the ports if
    ///   triggering is enabled in the module.
    ///   First it sends the general trigger, and the the slide trigger, if
    ///   it is enabled.
    /// </summary>
    /// <param name="slideContainer">
    /// The <see cref="SlidePresentationContainer"/> that should send the slide trigger.
    /// </param>
    /// <remarks>
    /// This method is called in a separate thread, because
    ///   the signaling time could be long lasting.
    /// </remarks>
    private void SendTrigger(SlidePresentationContainer slideContainer)
    {
      try
      {
        if (this.enableTrigger)
        {
          // Send general trigger if applicable
          if (this.generalTrigger.Signaling != TriggerSignaling.None)
          {
            this.generalTrigger.Send();
          }

          // Send Slide trigger if applicable
          if (this.generalTrigger.Signaling != TriggerSignaling.Override)
          {
            if (slideContainer.Slide.TriggerSignal.Signaling == TriggerSignaling.Enabled)
            {
              slideContainer.Slide.TriggerSignal.Send();
            }
          }
        }
      }
      catch (Exception ex)
      {
        MessageBox.Show(ex.Message);
      }
    }
コード例 #9
0
ファイル: PresenterModule.cs プロジェクト: DeSciL/Ogama
    /// <summary>
    /// This method is called whenever the slide has been swapped to the
    ///   foreground and its replay of audio streams and
    ///   optional screen capturing should be started.
    /// </summary>
    /// <param name="slideContainer">
    /// The <see cref="SlidePresentationContainer"/>
    ///   that should be initiated for replay.
    /// </param>
    private void PlaySlideContainer(SlidePresentationContainer slideContainer)
    {
      if (slideContainer.AudioPlayer.PlayState != PlayState.Running)
      {
        slideContainer.AudioPlayer.Play();
      }

      var countFlash = 0;

      if (this.shownSlideContainer.Slide.HasActiveXContent)
      {
        foreach (VGElement element in slideContainer.Slide.ActiveXStimuli)
        {
          if (element is VGFlash)
          {
            var flash = element as VGFlash;
            flash.SendMessagesToParent(true);
            flash.Play();
            countFlash++;
          }
          else if (element is VGBrowser)
          {
            var browser = element as VGBrowser;

            if (browser.WebBrowser.IsDisposed)
            {
              throw new ObjectDisposedException("Browser of new slide is already disposed...");
            }

            browser.SendMessagesToParent(true);
            if (browser.WebBrowser.InvokeRequired)
            {
              Application.DoEvents();
            }

            while (browser.WebBrowser.ReadyState != WebBrowserReadyState.Complete)
            {
              Application.DoEvents();
              if (this.closing)
              {
                return;
              }
            }

            // Set input focus to the webbrowser, otherwise the 
            // mouse will not act like a webbrowser mouse showing a
            // hand on a link etc.
            browser.WebBrowser.Focus();
          }
        }
      }

      // Just do screen capturing on flash content or desktop recording
      if (countFlash > 0 || this.shownSlideContainer.Trial.HasDesktopRecordingContent)
      {
        if (this.screenCapture != null && !this.screenCapture.IsRunning)
        {
          this.screenCapture.Start();
        }
      }
    }
コード例 #10
0
ファイル: PresenterModule.cs プロジェクト: DeSciL/Ogama
    /// <summary>
    /// This method parses the <see cref="Slide.VGStimuli"/>
    ///   for elements with sound files and fills them in the <see cref="OgamaControls.AudioPlayer"/>.
    ///   If they should be played on click, they are stored in the
    ///   <see cref="SlidePresentationContainer.ElementsWithAudioOnClick"/> list.
    /// </summary>
    /// <param name="slideContainer">
    /// The <see cref="SlidePresentationContainer"/>
    ///   to pe parsed for audio content that should be prepared for replay.
    /// </param>
    private void ParseElementsForAudio(SlidePresentationContainer slideContainer)
    {
      slideContainer.ElementsWithAudioOnClick.Clear();
      foreach (VGElement element in slideContainer.Slide.VGStimuli)
      {
        ParseElementForAudio(slideContainer, element);
      }

      foreach (VGElement element in slideContainer.Slide.ActiveXStimuli)
      {
        ParseElementForAudio(slideContainer, element);
      }
    }
コード例 #11
0
ファイル: PresenterModule.cs プロジェクト: DeSciL/Ogama
    /// <summary>
    /// This method initializes the next slide in the given
    ///   <see cref="SlidePresentationContainer"/>.
    ///   That is setting a time stop condition timer,
    ///   setup audio replay, and load flash objects.
    ///   Because this can last a significant amount of time
    ///   it should be done in a background thread.
    /// </summary>
    /// <param name="slideContainer">
    /// The <see cref="SlidePresentationContainer"/>
    ///   that should be initialized.
    /// </param>
    private void InitializeNextSlide(SlidePresentationContainer slideContainer)
    {
      try
      {
        // Reset Timer to 1ms period indicating that it should not be used during
        // call to PlaySlideContainer
        slideContainer.Timer.Period = 1;

        // Reset the timer according to stop condition if applicable.
        foreach (StopCondition condition in slideContainer.Slide.StopConditions)
        {
          if (condition is TimeStopCondition)
          {
            var timeCondition = (TimeStopCondition)condition;
            slideContainer.Timer.Period = timeCondition.Duration;
            break;
          }
        }

        // Search for audio files
        this.ParseElementsForAudio(slideContainer);

        // Load background sound
        if (slideContainer.Slide.BackgroundSound != null)
        {
          if (slideContainer.Slide.BackgroundSound.ShouldPlay)
          {
            slideContainer.AudioPlayer.AddAudioChannel(slideContainer.Slide.BackgroundSound.FullFilename);
          }
        }

        // Check for flash stimuli and load them into the
        // flashObject activeX control.
        foreach (VGElement element in slideContainer.Slide.ActiveXStimuli)
        {
          if (element is VGFlash)
          {
            var flash = element as VGFlash;
            flash.InitializeOnControl(slideContainer.ContainerControl, true, new System.Drawing.Drawing2D.Matrix());
          }
          else if (element is VGBrowser)
          {
            var browser = element as VGBrowser;
            this.currentVgBrowser = browser;
            browser.InitializeOnControl(slideContainer.ContainerControl, true);
            browser.WebBrowser.NewWindow += this.WebBrowser_NewWindow;
            browser.WebBrowser.DocumentCompleted += this.WebBrowserDocumentCompleted;
            browser.WebBrowser.Navigating += this.WebBrowserNavigating;

            // if (browser.WebBrowser.Url != null && browser.WebBrowser.Document != null)
            // {
            // // Attach Scroll events in document completed handler
            // browser.WebBrowser.Document.MouseDown += this.WebBrowserMouseDown;
            // }
            browser.WebBrowser.Navigate(browser.BrowserURL);
            this.numberOfTimesNavigated = 0;
            this.maxBrowseDepth = browser.BrowseDepth;
            this.currentBrowserTreeNode =
              (BrowserTreeNode)Document.ActiveDocument.ExperimentSettings.SlideShow.GetNodeByID(slideContainer.Trial.ID);
          }
        }
      }
      catch (Exception ex)
      {
        ExceptionMethods.HandleExceptionSilent(ex);
      }
    }
コード例 #12
0
ファイル: PresenterModule.cs プロジェクト: DeSciL/Ogama
    /// <summary>
    /// This method asynchronously calls the drawing method of the slide of
    ///   the given container to the given slidecontainers drawing surface.
    /// </summary>
    /// <param name="slideToDraw">
    /// The <see cref="SlidePresentationContainer"/>
    ///   whichs slide should be drawn to its buffer.
    /// </param>
    private void DrawToBuffer(SlidePresentationContainer slideToDraw)
    {
      if (slideToDraw.Slide.PresentationSize == Size.Empty)
      {
        slideToDraw.Slide.PresentationSize = Document.ActiveDocument.PresentationSize;
      }

      // Draw slides contents.
      this.DrawSlideAsyncMethod(slideToDraw.Slide, slideToDraw.DrawingSurface.Graphics);
    }
コード例 #13
0
ファイル: PresenterModule.cs プロジェクト: DeSciL/Ogama
    /// <summary>
    /// This method releases the resources used in the given
    ///   <see cref="SlidePresentationContainer"/> but not all.
    ///   Some items should not be disposed because they are reused for
    ///   the next slide.
    /// </summary>
    /// <param name="slideContainer">
    /// The <see cref="SlidePresentationContainer"/>
    ///   to be disposed and prepared for next use.
    /// </param>
    private void DisposeSlideContainer(SlidePresentationContainer slideContainer)
    {
      // Explicitely dispose flash objects 
      // otherwise we will get an exception from 
      // the MDA reportAvOnComRelease
      if (slideContainer.ContainerControl.Controls.Count > 0)
      {
        foreach (Control ctrl in slideContainer.ContainerControl.Controls)
        {
          if (ctrl is AxFlashControl)
          {
            if (ctrl.InvokeRequired)
            {
              MethodInvoker ctrlDisposeDelegate = ctrl.Dispose;
              ctrl.Invoke(ctrlDisposeDelegate);
            }
            else
            {
              ctrl.Dispose();
            }
          }
          else if (ctrl is WebBrowser)
          {
            if (ctrl.InvokeRequired)
            {
              MethodInvoker ctrlDisposeDelegate = ctrl.Dispose;
              ctrl.Invoke(ctrlDisposeDelegate);
            }
          }
        }
      }

      foreach (VGElement element in slideContainer.Slide.ActiveXStimuli)
      {
        if (element is VGFlash)
        {
          var flash = element as VGFlash;
          flash.SendMessagesToParent(false);
        }
        else if (element is VGBrowser)
        {
          var browser = element as VGBrowser;
          browser.SendMessagesToParent(false);
        }
      }

      if (this.InvokeRequired)
      {
        MethodInvoker controlsClearMethod = slideContainer.ContainerControl.Controls.Clear;
        this.Invoke(controlsClearMethod);
      }
      else
      {
        slideContainer.ContainerControl.Controls.Clear();
      }

      slideContainer.Slide.Dispose();

      // Stop audio playback and release player
      slideContainer.AudioPlayer.CloseAudioFile();
      slideContainer.ElementsWithAudioOnClick.Clear();

      // Stop current running timer.
      if (slideContainer.Timer.IsRunning)
      {
        slideContainer.Timer.Stop();
      }
    }