/// <summary> /// The <see cref="PresenterModule.TrialChanged"/> event handler. /// Stores the trial information into the database /// and updates the live viewer with the new slide. /// </summary> /// <param name="sender"> /// Source of the event. /// </param> /// <param name="e"> /// A <see cref="TrialChangedEventArgs"/> with the event data. /// </param> private void ObjPresenterTrialChanged(object sender, TrialChangedEventArgs e) { // Set time critical values long currentTime = this.counterChangedTime; this.xScrollOffset = 0; this.yScrollOffset = 0; // If the last trial was a disabled trial (PreFixationSlide) // Only update start times if (e.FinishedTrial[e.FinishedTrial.Count - 1].IsDisabled) { // Update new trial this.currentTrialStarttime = currentTime - this.recordingStarttime; if (this.chbRecordAudio.Checked || this.chbRecordVideo.Checked) { this.currentTrialVideoStartTime = e.WebcamTime; } this.Invoke(this.delegateNewSlideAvailable); return; } if (e.FinishedTrial.Name != "DummyTrial") { // Update current trial this.precedingTrial = e.FinishedTrial; // When rawData list exceeds sample limit or this was the last trial // write the samples into the database if (this.rawDataLists[this.listCounter].Count > MINSAMPLESFORWRITINGTODATABASE || e.NextTrial == null) { // Stop recording if this was the last trial or cancelled if (e.NextTrial == null) { // Stop tracking this.currentTracker.Stop(); // Give the presentation thread time to close. Application.DoEvents(); } // switch to next raw data list for writing lock (this) { // Save copy to dataset table in new thread AsyncHelper.FireAndForget( new WaitCallback(StoreRecordsInDataSetTable), new DataToTable(this.rawDataLists[this.listCounter], this.subjectRawDataTable)); // Clear list, cause its content was copied during creation of DataToTable this.rawDataLists[this.listCounter].Clear(); this.listCounter++; if (this.listCounter == NUMWRITINGTHREADS) { this.listCounter = 0; } } } // Write new trial information var trialData = new TrialsData { SubjectName = this.currentTracker.Subject.SubjectName, TrialName = this.precedingTrial.Name, TrialSequence = this.trialSequenceCounter - 1, TrialID = this.precedingTrial.ID, Category = this.precedingTrial[0].Category, TrialStartTime = this.currentTrialStarttime, Duration = (int)(currentTime - this.recordingStarttime - this.currentTrialStarttime) }; if (this.trialSequenceCounter > 0) { this.trialDataList.Add(trialData); } // Store usercam start event if applicable if (this.chbRecordAudio.Checked || this.chbRecordVideo.Checked) { var usercamVideoEvent = new MediaEvent { EventID = this.trialEventList.Count, Param = this.currentTrialVideoStartTime.ToString(CultureInfo.InvariantCulture), Task = MediaEventTask.Start, Time = 0, Type = EventType.Usercam, SubjectName = this.currentTracker.Subject.SubjectName, TrialSequence = this.trialSequenceCounter - 1 }; if (this.trialSequenceCounter > 0) { this.trialEventList.Add(usercamVideoEvent); } } // Store subjects response event var inputEvent = new InputEvent { EventID = this.trialEventList.Count, SubjectName = this.currentTracker.Subject.SubjectName, Task = InputEventTask.SlideChange, Time = trialData.Duration, TrialSequence = this.trialSequenceCounter - 1, Type = EventType.Response }; if (e.Response != null) { inputEvent.Param = e.Response.ToString(); } if (this.trialSequenceCounter >= 0) { this.trialEventList.Add(inputEvent); } } // Update new trial this.currentTrialStarttime = currentTime - this.recordingStarttime; if (this.chbRecordAudio.Checked || this.chbRecordVideo.Checked) { this.currentTrialVideoStartTime = e.WebcamTime; } // Update recorder modules viewer var updateLiveViewerThread = new Thread(this.NewSlideAvailable); updateLiveViewerThread.SetApartmentState(ApartmentState.STA); updateLiveViewerThread.Start(); }
/// <summary> /// Overridden <see cref="ProcessCmdKey(ref Message,Keys)"/> method. /// Captures all pressed keys including /// Alt, Ctrl, Space, Esc that are normally not raised as KeyDown in a form. /// </summary> /// <param name="msg"> /// This parameter contains the Windows Message, such as WM_KEYDOWN /// </param> /// <param name="keyData"> /// The keyData parameter contains the key code of the key that was pressed. If CTRL or ALT was also /// pressed, the keyData parameter contains the ModifierKey information. /// </param> /// <returns> /// True if Key should be processed ? /// </returns> protected override bool ProcessCmdKey(ref Message msg, Keys keyData) { const int WM_KEYDOWN = 0x100; const int WM_SYSKEYDOWN = 0x104; if (((msg.Msg == WM_KEYDOWN) || (msg.Msg == WM_SYSKEYDOWN)) && (!this.closing)) { long eventTime = -1; if (this.getTimeMethod != null) { eventTime = this.getTimeMethod(); } if (this.watch.ElapsedMilliseconds > MINIMUMKEYPRESSINTERVALLMS) { // Check for markers if (keyData == Keys.F12) { // Store marker event var keyEvent = new MediaEvent { Type = EventType.Marker, Task = MediaEventTask.None, Param = string.Empty }; this.OnTrialEventOccured(new TrialEventOccuredEventArgs(keyEvent, eventTime)); } else { this.currentKey = keyData; if (!this.CheckforSlideChange(false)) { // Store key event only when slide has not changed // otherwise the event will be stored during // trialchanged event. var keyEvent = new InputEvent { Type = EventType.Key, Task = InputEventTask.Down }; var ksc = new KeyStopCondition(keyData, false, null); keyEvent.Param = ksc.ToString(); this.OnTrialEventOccured(new TrialEventOccuredEventArgs(keyEvent, eventTime)); } this.watch.Reset(); this.watch.Start(); } } } return base.ProcessCmdKey(ref msg, keyData); }
/// <summary> /// The <see cref="PresenterModule.TrialEventOccured"/> event handler. /// Stores the new trial event into the list. /// </summary> /// <param name="sender"> /// Source of the event. /// </param> /// <param name="e"> /// A <see cref="TrialEventOccuredEventArgs"/> with the event data. /// </param> private void ObjPresenterSlideChanged(object sender, SlideChangedEventArgs e) { if (e.NextSlide.IsDisabled) { return; } long time = this.counterChangedTime - this.recordingStarttime - this.currentTrialStarttime; // Store slide changed event var slideChangedEvent = new MediaEvent { EventID = this.trialEventList.Count, Param = e.SlideCounter + "#" + e.NextSlide.Name, Task = MediaEventTask.Show, Time = time, Type = EventType.Slide, SubjectName = this.currentTracker.Subject.SubjectName, TrialSequence = this.trialSequenceCounter }; if (this.trialSequenceCounter >= 0) { this.trialEventList.Add(slideChangedEvent); this.WriteTrialEventToRawData(slideChangedEvent); } // Store subjects response event var inputEvent = new InputEvent { EventID = this.trialEventList.Count }; if (e.Response != null) { inputEvent.Param = e.Response.ToString(); } inputEvent.SubjectName = this.currentTracker.Subject.SubjectName; inputEvent.Task = InputEventTask.SlideChange; inputEvent.Time = time; inputEvent.TrialSequence = this.trialSequenceCounter; inputEvent.Type = EventType.Response; if (this.trialSequenceCounter >= 0) { this.trialEventList.Add(inputEvent); this.WriteTrialEventToRawData(slideChangedEvent); } this.Invoke(this.delegateNewSlideAvailable); }
/// <summary> /// The <see cref="Control.MouseUp"/> event handler. /// Resets the <see cref="currentMousebutton"/> to /// <see cref="MouseButtons.None"/>. /// </summary> /// <param name="sender"> /// Source of the event. /// </param> /// <param name="e"> /// A <see cref="MouseEventArgs"/> with the event data. /// </param> private void FrmPresenterMouseUp(object sender, MouseEventArgs e) { this.currentMousebutton = MouseButtons.None; long eventTime = -1; if (this.getTimeMethod != null) { eventTime = this.getTimeMethod(); } var mouseEvent = new InputEvent(); mouseEvent.Type = EventType.Mouse; mouseEvent.Task = InputEventTask.Up; var msc = new MouseStopCondition(e.Button, false, string.Empty, null, e.Location); mouseEvent.Param = msc.ToString(); this.OnTrialEventOccured(new TrialEventOccuredEventArgs(mouseEvent, eventTime)); }
/// <summary> /// The <see cref="Control.MouseDown"/> event handler. /// Sets the <see cref="currentMousebutton"/> and raises /// the <see cref="TrialEventOccured"/> event. /// </summary> /// <remarks> /// If the mouse button is a response that indicates /// a slide change, do it. /// </remarks> /// <param name="sender"> /// Source of the event. /// </param> /// <param name="e"> /// A <see cref="MouseEventArgs"/> with the event data. /// </param> private void FrmPresenterMouseDown(object sender, MouseEventArgs e) { this.currentMousebutton = e.Button; long eventTime = -1; if (this.getTimeMethod != null) { eventTime = this.getTimeMethod(); } if (!this.CheckforSlideChange(false)) { var mouseEvent = new InputEvent(); mouseEvent.Type = EventType.Mouse; mouseEvent.Task = InputEventTask.Down; var msc = new MouseStopCondition(e.Button, false, string.Empty, null, e.Location); mouseEvent.Param = msc.ToString(); this.OnTrialEventOccured(new TrialEventOccuredEventArgs(mouseEvent, eventTime)); this.CheckforAudioStimulusOnClick(this.shownSlideContainer, e.Location, eventTime); } }
/// <summary> /// The <see cref="Control.MouseDown"/> event handler which sends /// a mouse down event. /// </summary> /// <param name="sender"> /// Source of the event /// </param> /// <param name="e"> /// A <see cref="HtmlElementEventArgs"/> with the event data /// </param> private void WebBrowserMouseDown(object sender, HtmlElementEventArgs e) { // Set flag for navigated event this.isWebbrowserClicked = true; long eventTime = -1; if (this.getTimeMethod != null) { eventTime = this.getTimeMethod(); } var browserControl = sender as HtmlDocument; if (browserControl != null) { var htmlElement = browserControl.GetElementsByTagName("HTML")[0]; var bodyElement = browserControl.Body; var scrollTop = htmlElement.ScrollTop > bodyElement.ScrollTop ? htmlElement.ScrollTop : bodyElement.ScrollTop; var scrollLeft = htmlElement.ScrollLeft > bodyElement.ScrollLeft ? htmlElement.ScrollLeft : bodyElement.ScrollLeft; var mouseEvent = new InputEvent(); mouseEvent.Type = EventType.Mouse; mouseEvent.Task = InputEventTask.Down; var msc = new MouseStopCondition( e.MouseButtonsPressed, false, string.Empty, null, new Point(e.ClientMousePosition.X + scrollLeft, e.ClientMousePosition.Y + scrollTop)); mouseEvent.Param = msc.ToString(); this.OnTrialEventOccured(new TrialEventOccuredEventArgs(mouseEvent, eventTime)); } }
/// <summary> /// This method parses the trial event table for the mouse events made by the given /// subject during the trial with the given sequence number /// </summary> /// <param name="subjectName">A <see cref="String"/> with the subject name.</param> /// <param name="trialSequence">The <see cref="Int32"/> with the sequence number /// of this trial for the given subject.</param> /// <returns>A <see cref="SortedList{Int64, InputEvent}"/> with the mouse events made by the given /// subject during the trial with the given sequence number.</returns> public static SortedList<long, InputEvent> GetTrialMouseEvents( string subjectName, int trialSequence) { SortedList<long, InputEvent> returnList = new SortedList<long, InputEvent>(); DataTable table = Document.ActiveDocument.DocDataSet.TrialEventsAdapter.GetDataBySubjectAndSequence(subjectName, trialSequence); foreach (DataRow row in table.Rows) { string typeString = row["EventType"].ToString(); EventType type = EventType.None; try { type = (EventType)Enum.Parse(typeof(EventType), typeString, true); } catch (ArgumentException) { continue; } int id = Convert.ToInt32(row["EventID"]); long time = Convert.ToInt64(row["EventTime"]); string taskString = row["EventTask"].ToString(); string param = row["EventParam"].ToString(); InputEvent newEvent = null; switch (type) { case EventType.Mouse: newEvent = new InputEvent(); newEvent.EventID = id; newEvent.Param = param; ((InputEvent)newEvent).Task = (InputEventTask)Enum.Parse(typeof(InputEventTask), taskString, true); newEvent.Time = time; newEvent.Type = type; if (!returnList.ContainsKey(time)) { returnList.Add(time, newEvent); } break; case EventType.Response: newEvent = new InputEvent(); newEvent.EventID = id; newEvent.Param = param; ((InputEvent)newEvent).Task = (InputEventTask)Enum.Parse(typeof(InputEventTask), taskString, true); newEvent.Time = time; newEvent.Type = type; StopCondition stc = null; try { stc = (StopCondition)TypeDescriptor.GetConverter(typeof(StopCondition)).ConvertFrom(param); } catch (Exception) { // Ignore errors because we just want to catch MouseStopConditions } if (stc != null & stc is MouseStopCondition & !returnList.ContainsKey(time)) { returnList.Add(time, newEvent); } break; } } return returnList; }
/// <summary> /// Extracts the events in a sorted trial events list for the given subject and trial /// events data table. /// </summary> /// <param name="subjectName">A <see cref="String"/> with the subject name.</param> /// <param name="table">The trial events data table containing the data from /// the database, can be for one or more trials.</param> /// <param name="usercamID">Out. The event id of the user camera start time.</param> /// <returns>A <see cref="SortedList{Int32, TrialEvent}"/> /// with the events occured in this experiment.</returns> private static SortedList<int, TrialEvent> ExtractEvents( string subjectName, DataTable table, out int usercamID) { usercamID = -1; int lastTrialSequence = -1; long timeToAdd = 0; SortedList<int, TrialEvent> returnList = new SortedList<int, TrialEvent>(); if (table.Rows.Count > 0) { lastTrialSequence = Convert.ToInt32(table.Rows[0]["TrialSequence"]); } foreach (DataRow row in table.Rows) { string typeString = row["EventType"].ToString(); EventType type = EventType.None; try { type = (EventType)Enum.Parse(typeof(EventType), typeString, true); } catch (ArgumentException) { continue; } int trialSequence = Convert.ToInt32(row["TrialSequence"]); if (trialSequence != lastTrialSequence) { DataTable trialTable = Document.ActiveDocument.DocDataSet.TrialsAdapter.GetDataBySubjectAndSequence(subjectName, trialSequence); // Check for deleted trials, but left raw data... if (trialTable.Rows.Count == 0) { continue; } lastTrialSequence = trialSequence; long trialStartTime = Convert.ToInt64(trialTable.Rows[0]["TrialStartTime"]); timeToAdd = trialStartTime; } int eventID = Convert.ToInt32(row["EventID"]); long time = Convert.ToInt64(row["EventTime"]) + timeToAdd; string taskString = row["EventTask"].ToString(); string param = row["EventParam"].ToString(); TrialEvent newEvent = null; switch (type) { case EventType.None: break; case EventType.Mouse: newEvent = new InputEvent(); newEvent.SubjectName = subjectName; newEvent.TrialSequence = trialSequence; newEvent.EventID = eventID; newEvent.Param = param; ((InputEvent)newEvent).Task = (InputEventTask)Enum.Parse(typeof(InputEventTask), taskString, true); newEvent.Time = time; newEvent.Type = type; returnList.Add(eventID, newEvent); break; case EventType.Key: newEvent = new InputEvent(); newEvent.SubjectName = subjectName; newEvent.TrialSequence = trialSequence; newEvent.EventID = eventID; newEvent.Param = param; ((InputEvent)newEvent).Task = (InputEventTask)Enum.Parse(typeof(InputEventTask), taskString, true); newEvent.Time = time; newEvent.Type = type; returnList.Add(eventID, newEvent); break; case EventType.Slide: newEvent = new MediaEvent(); newEvent.SubjectName = subjectName; newEvent.TrialSequence = trialSequence; newEvent.EventID = eventID; newEvent.Param = param; ((MediaEvent)newEvent).Task = (MediaEventTask)Enum.Parse(typeof(MediaEventTask), taskString, true); newEvent.Time = time; newEvent.Type = type; returnList.Add(eventID, newEvent); break; case EventType.Flash: newEvent = new MediaEvent(); newEvent.SubjectName = subjectName; newEvent.TrialSequence = trialSequence; newEvent.EventID = eventID; newEvent.Param = param; ((MediaEvent)newEvent).Task = (MediaEventTask)Enum.Parse(typeof(MediaEventTask), taskString, true); newEvent.Time = time; newEvent.Type = type; returnList.Add(eventID, newEvent); break; case EventType.Audio: newEvent = new MediaEvent(); newEvent.SubjectName = subjectName; newEvent.TrialSequence = trialSequence; newEvent.EventID = eventID; newEvent.Param = param; ((MediaEvent)newEvent).Task = (MediaEventTask)Enum.Parse(typeof(MediaEventTask), taskString, true); newEvent.Time = time; newEvent.Type = type; returnList.Add(eventID, newEvent); break; case EventType.Video: newEvent = new MediaEvent(); newEvent.SubjectName = subjectName; newEvent.TrialSequence = trialSequence; newEvent.EventID = eventID; newEvent.Param = param; ((MediaEvent)newEvent).Task = (MediaEventTask)Enum.Parse(typeof(MediaEventTask), taskString, true); newEvent.Time = time; newEvent.Type = type; returnList.Add(eventID, newEvent); break; case EventType.Usercam: newEvent = new MediaEvent(); newEvent.SubjectName = subjectName; newEvent.TrialSequence = trialSequence; newEvent.EventID = eventID; newEvent.Param = param; ((MediaEvent)newEvent).Task = (MediaEventTask)Enum.Parse(typeof(MediaEventTask), taskString, true); newEvent.Time = time; newEvent.Type = type; usercamID = eventID; returnList.Add(eventID, newEvent); break; case EventType.Response: newEvent = new InputEvent(); newEvent.SubjectName = subjectName; newEvent.TrialSequence = trialSequence; newEvent.EventID = eventID; newEvent.Param = param; ((InputEvent)newEvent).Task = (InputEventTask)Enum.Parse(typeof(InputEventTask), taskString, true); newEvent.Time = time; newEvent.Type = type; if (!returnList.ContainsKey(eventID)) { returnList.Add(eventID, newEvent); } break; case EventType.Marker: newEvent = new MediaEvent(); newEvent.SubjectName = subjectName; newEvent.TrialSequence = trialSequence; newEvent.EventID = eventID; newEvent.Param = param; ((MediaEvent)newEvent).Task = (MediaEventTask)Enum.Parse(typeof(MediaEventTask), taskString, true); newEvent.Time = time; newEvent.Type = type; returnList.Add(eventID, newEvent); break; case EventType.Scroll: newEvent = new MediaEvent(); newEvent.SubjectName = subjectName; newEvent.TrialSequence = trialSequence; newEvent.EventID = eventID; newEvent.Param = param; ((MediaEvent)newEvent).Task = (MediaEventTask)Enum.Parse(typeof(MediaEventTask), taskString, true); newEvent.Time = time; newEvent.Type = type; returnList.Add(eventID, newEvent); break; case EventType.Webpage: newEvent = new MediaEvent(); newEvent.SubjectName = subjectName; newEvent.TrialSequence = trialSequence; newEvent.EventID = eventID; newEvent.Param = param; ((MediaEvent)newEvent).Task = (MediaEventTask)Enum.Parse(typeof(MediaEventTask), taskString, true); newEvent.Time = time; newEvent.Type = type; returnList.Add(eventID, newEvent); break; default: break; } } return returnList; }