Skip to content

Commit

Permalink
Support automatic, experiment-side data file management via iodevice/…
Browse files Browse the repository at this point in the history
…data_file
  • Loading branch information
cstawarz committed Aug 1, 2019
1 parent c86b66b commit 9678cd5
Show file tree
Hide file tree
Showing 36 changed files with 554 additions and 78 deletions.
38 changes: 36 additions & 2 deletions apps/client/English.lproj/MainMenu.xib
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none">
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14460.31"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14490.70"/>
<capability name="Named colors" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
Expand Down Expand Up @@ -902,6 +902,7 @@
<customObject id="487" customClass="AppController">
<connections>
<outlet property="clientInstances" destination="462" id="488"/>
<outlet property="dataFileAutoOpenSheet" destination="3at-Cl-cQF" id="Ff4-7a-VUc"/>
<outlet property="dataFileCloseSheet" destination="768" id="823"/>
<outlet property="dataFileOpenSheet" destination="798" id="822"/>
<outlet property="disconnectSheet" destination="563" id="649"/>
Expand Down Expand Up @@ -2606,6 +2607,39 @@
</view>
<point key="canvasLocation" x="19" y="-32"/>
</window>
<window title="Data File Auto Open" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" hidesOnDeactivate="YES" releasedWhenClosed="NO" visibleAtLaunch="NO" frameAutosaveName="" animationBehavior="default" id="3at-Cl-cQF" customClass="NSPanel">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES" utility="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="196" y="112" width="297" height="105"/>
<rect key="screenRect" x="0.0" y="0.0" width="1920" height="1057"/>
<view key="contentView" id="DMC-K9-BnU">
<rect key="frame" x="0.0" y="0.0" width="297" height="105"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<textField verticalHuggingPriority="750" id="1ce-Bf-Jgg">
<rect key="frame" x="18" y="46" width="261" height="39"/>
<autoresizingMask key="autoresizingMask"/>
<textFieldCell key="cell" sendsActionOnEndEditing="YES" title="Data file streaming is currently controlled by the experiment." id="eGJ-RH-VM3">
<font key="font" usesAppearanceFont="YES"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<button verticalHuggingPriority="750" id="Gbz-KD-WzP">
<rect key="frame" x="132" y="19" width="32" height="19"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="roundRect" title="OK" bezelStyle="roundedRect" alignment="center" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="E72-9C-BqI">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="cellTitle"/>
</buttonCell>
<connections>
<action selector="closeDataFileAutoOpenSheet:" target="487" id="lBR-si-8KG"/>
</connections>
</button>
</subviews>
</view>
<point key="canvasLocation" x="479.5" y="359.5"/>
</window>
</objects>
<resources>
<image name="NSAddTemplate" width="11" height="11"/>
Expand Down
2 changes: 2 additions & 0 deletions apps/client/Source/AppController.h
Expand Up @@ -26,6 +26,7 @@

IBOutlet NSWindow *variableSetSheet;

IBOutlet NSWindow *dataFileAutoOpenSheet;
IBOutlet NSWindow *dataFileOpenSheet;
IBOutlet NSWindow *dataFileCloseSheet;

Expand Down Expand Up @@ -103,6 +104,7 @@

// Open / Close Data File
- (IBAction)launchDataFileSheetForItem:(NSCollectionViewItem *)item;
- (IBAction) closeDataFileAutoOpenSheet: (id)sender;
- (IBAction) closeDataFileOpenSheet: (id)sender;
- (IBAction) closeDataFileCloseSheet: (id)sender;
- (IBAction) openDataFile: (id) sender;
Expand Down
18 changes: 6 additions & 12 deletions apps/client/Source/AppController.m
Expand Up @@ -320,24 +320,15 @@ - (IBAction)launchDataFileSheetForItem:(NSCollectionViewItem *)item{
sheetOrigin = [[[self window] contentView] convertRect:[[item view] bounds] fromView:[item view]];
[self setModalClientInstanceInCharge:[item representedObject]];

BOOL is_loaded = [modalClientInstanceInCharge dataFileOpen];

NSWindow *sheet_to_use;

NSString *dataFileName = [modalClientInstanceInCharge dataFileName];


if(dataFileName == Nil){
dataFileName = @"/";
}

if(is_loaded){
if (modalClientInstanceInCharge.dataFileWillAutoOpen) {
sheet_to_use = dataFileAutoOpenSheet;
} else if (modalClientInstanceInCharge.dataFileOpen) {
sheet_to_use = dataFileCloseSheet;
} else {
sheet_to_use = dataFileOpenSheet;
}


#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
[NSApp beginSheet: sheet_to_use
Expand All @@ -348,6 +339,9 @@ - (IBAction)launchDataFileSheetForItem:(NSCollectionViewItem *)item{
#pragma clang diagnostic pop
}

- (IBAction) closeDataFileAutoOpenSheet: (id)sender {
[NSApp endSheet: dataFileAutoOpenSheet];
}
- (IBAction) closeDataFileOpenSheet: (id)sender {
[NSApp endSheet: dataFileOpenSheet];
}
Expand Down
2 changes: 2 additions & 0 deletions apps/client/Source/MWClientInstance.h
Expand Up @@ -61,6 +61,7 @@
NSString *variableSetName;
NSMutableArray *serversideVariableSetNames;

BOOL dataFileWillAutoOpen;
BOOL dataFileOpen;
NSString *dataFileName;
BOOL dataFileOverwrite;
Expand Down Expand Up @@ -129,6 +130,7 @@
@property NSMutableArray *serversideVariableSetNames;

// Data File state
@property BOOL dataFileWillAutoOpen;
@property BOOL dataFileOpen;
@property(copy, readwrite) NSString *dataFileName;
@property BOOL dataFileOverwrite;
Expand Down
9 changes: 8 additions & 1 deletion apps/client/Source/MWClientInstance.m
Expand Up @@ -78,6 +78,7 @@ - (id)initWithAppController:(AppController *)_controller {
forVariableCode:RESERVED_SYSTEM_EVENT_CODE
onMainThread:YES];

[self setDataFileWillAutoOpen:NO];
[self setDataFileOpen:false];
[self setExperimentLoaded:false];
[self setServerConnected:false];
Expand Down Expand Up @@ -154,6 +155,7 @@ - (void)shutDown {
@synthesize variableSetLoaded;

// Data File state
@synthesize dataFileWillAutoOpen;
@synthesize dataFileOpen;
@synthesize dataFileName;
@synthesize dataFileOverwrite;
Expand Down Expand Up @@ -267,6 +269,7 @@ - (void)enforceDisconnectedState{
[self setServerName:Nil];
[self setVariableSetName:Nil];

[self setDataFileWillAutoOpen:NO];
[self setDataFileOpen:NO];
[self setDataFileName:Nil];
[self setDataFileOverwrite:NO];
Expand Down Expand Up @@ -547,7 +550,7 @@ - (void)toggleExperimentRunning:(id)running{
} else {
//start

if (!self.dataFileOpen && appController.shouldAutoOpenDataFile) {
if (!(self.dataFileWillAutoOpen || self.dataFileOpen) && appController.shouldAutoOpenDataFile) {
NSString *userName = NSUserName();
NSString *experimentBaseName = self.clientsideExperimentPath.lastPathComponent.stringByDeletingPathExtension;

Expand Down Expand Up @@ -794,6 +797,10 @@ - (void)handleSystemEvent:(MWCocoaEvent *)event {
self.variableSetLoaded = YES;
}

if (state.hasKey(M_DATA_FILE_AUTO_OPEN)) {
self.dataFileWillAutoOpen = state.getElement(M_DATA_FILE_AUTO_OPEN).getBool();
}

if (state.hasKey(M_DATA_FILE_NAME)) {
[self setDataFileName:[NSString stringWithCString:state.getElement(M_DATA_FILE_NAME).getString().c_str()
encoding:NSASCIIStringEncoding]];
Expand Down
2 changes: 2 additions & 0 deletions core/Core/ComponentRegistries/ComponentRegistry.cpp
Expand Up @@ -20,6 +20,7 @@
#include "StandardSounds.h"
#include "Averagers.h"
#include "SimpleStaircase.h"
#include "DataFileDevice.hpp"
#include "DummyIODevice.h"
#include "LegacyIODevice.h"
#include "StimulusDisplayDevice.h"
Expand Down Expand Up @@ -123,6 +124,7 @@ ComponentRegistry::ComponentRegistry() {
registerFactory("bias_monitor", new BiasMonitorFactory());

// IO devices
registerFactory<StandardComponentFactory, DataFileDevice>();
registerFactory<StandardComponentFactory, DummyIODevice>();
registerFactory<StandardComponentFactory, IOChannelRequest>();
registerFactory<StandardComponentFactory, StimulusDisplayDevice>();
Expand Down
33 changes: 33 additions & 0 deletions core/Core/DataFiles/DataFileDevice.cpp
@@ -0,0 +1,33 @@
//
// DataFileDevice.cpp
// MWorksCore
//
// Created by Christopher Stawarz on 7/25/19.
//

#include "DataFileDevice.hpp"

#include "DataFileManager.h"


BEGIN_NAMESPACE_MW


const std::string DataFileDevice::FILENAME("filename");


void DataFileDevice::describeComponent(ComponentInfo &info) {
IODevice::describeComponent(info);
info.setSignature("iodevice/data_file");
info.addParameter(FILENAME);
}


DataFileDevice::DataFileDevice(const ParameterValueMap &parameters) :
IODevice(parameters)
{
DataFileManager::instance()->setAutoOpenFilename(parsedText(parameters[FILENAME]));
}


END_NAMESPACE_MW
32 changes: 32 additions & 0 deletions core/Core/DataFiles/DataFileDevice.hpp
@@ -0,0 +1,32 @@
//
// DataFileDevice.hpp
// MWorksCore
//
// Created by Christopher Stawarz on 7/25/19.
//

#ifndef DataFileDevice_hpp
#define DataFileDevice_hpp

#include "IODevice.h"


BEGIN_NAMESPACE_MW


class DataFileDevice : public IODevice {

public:
static const std::string FILENAME;

static void describeComponent(ComponentInfo &info);

explicit DataFileDevice(const ParameterValueMap &parameters);

};


END_NAMESPACE_MW


#endif /* DataFileDevice_hpp */
80 changes: 73 additions & 7 deletions core/Core/DataFiles/DataFileManager.cpp
Expand Up @@ -135,16 +135,22 @@ void DataFileManager::DataFile::handleEvents() {
SINGLETON_INSTANCE_STATIC_DECLARATION(DataFileManager)


bool DataFileManager::openFile(std::string filename, bool overwrite) {
static inline std::string getFullFilename(const std::string &filename) {
return appendDataFileExtension(prependDataFilePath(filename).string());
}


bool DataFileManager::openFile(const std::string &filename, bool overwrite) {
lock_guard lock(mutex);

if (dataFile) {
mwarning(M_FILE_MESSAGE_DOMAIN, "Data file already open at \"%s\"", dataFile->getFilename().c_str());
return true;
}

filename = appendDataFileExtension(prependDataFilePath(filename).string());

return openFile(getFullFilename(filename), overwrite, dataFile);
}


bool DataFileManager::openFile(const std::string &filename, bool overwrite, std::unique_ptr<DataFile> &dataFile) {
if (!DataFile::create(filename, overwrite, dataFile)) {
global_outgoing_event_buffer->putEvent(SystemEventFactory::dataFileOpenedResponse(filename, M_COMMAND_FAILURE));
return false;
Expand All @@ -167,9 +173,13 @@ bool DataFileManager::openFile(std::string filename, bool overwrite) {

void DataFileManager::closeFile() {
lock_guard lock(mutex);
if (!dataFile) {
return;
if (dataFile) {
closeFile(dataFile);
}
}


void DataFileManager::closeFile(std::unique_ptr<DataFile> &dataFile) {
mprintf(M_FILE_MESSAGE_DOMAIN, "Closing data file...");
auto filename = dataFile->getFilename(); // Make a copy to use after dataFile is destroyed
dataFile.reset();
Expand All @@ -188,4 +198,60 @@ std::string DataFileManager::getFilename() const {
}


void DataFileManager::setAutoOpenFilename(const boost::shared_ptr<Variable> &filename) {
lock_guard lock(mutex);
if (autoOpenFilename) {
throw SimpleException(M_FILE_MESSAGE_DOMAIN, "Automatic data-file management is already configured");
}
autoOpenFilename = filename;
}


void DataFileManager::clearAutoOpenFilename() {
lock_guard lock(mutex);
autoOpenFilename.reset();
}


bool DataFileManager::canAutoOpenFile() const {
lock_guard lock(mutex);
return bool(autoOpenFilename);
}


bool DataFileManager::autoOpenFile() {
lock_guard lock(mutex);

if (!autoOpenFilename) {
// Nothing to do
return true;
}

// Evaluate the filename
std::string filename;
try {
filename = autoOpenFilename->getValue().getString();
} catch (const SimpleException &e) {
merror(M_FILE_MESSAGE_DOMAIN, "Filename evaluation failed: %s", e.what());
return false;
}
if (filename.empty()) {
merror(M_FILE_MESSAGE_DOMAIN, "Evaluated filename is empty");
return false;
}
filename = getFullFilename(filename);

if (dataFile) {
if (dataFile->getFilename() == filename) {
// The desired file is already open. Nothing else to do.
return true;
}
// Close the current file
closeFile(dataFile);
}

return openFile(filename, false, dataFile); // Never overwrite
}


END_NAMESPACE_MW
15 changes: 13 additions & 2 deletions core/Core/DataFiles/DataFileManager.h
Expand Up @@ -54,14 +54,25 @@ class DataFileManager {
public:
REGISTERED_SINGLETON_CODE_INJECTION(DataFileManager)

bool openFile(std::string filename, bool overwrite);
bool openFile(const std::string &filename, bool overwrite);
void closeFile();
std::string getFilename() const;

void setAutoOpenFilename(const boost::shared_ptr<Variable> &filename);
void clearAutoOpenFilename();
bool canAutoOpenFile() const;
bool autoOpenFile();

private:
static bool openFile(const std::string &filename, bool overwrite, std::unique_ptr<DataFile> &dataFile);
static void closeFile(std::unique_ptr<DataFile> &dataFile);

std::unique_ptr<DataFile> dataFile;
boost::shared_ptr<Variable> autoOpenFilename;

using lock_guard = std::lock_guard<std::mutex>;
// canAutoOpenFile and getFilename are called (via SystemEventFactory::currentExperimentState)
// from within openFile, so the mutex must be recursive
using lock_guard = std::lock_guard<std::recursive_mutex>;
mutable lock_guard::mutex_type mutex;

};
Expand Down
1 change: 1 addition & 0 deletions core/Core/Events/EventConstants.h
Expand Up @@ -125,6 +125,7 @@ enum MessageDomain { M_GENERIC_MESSAGE_DOMAIN = 0,
#define M_CURRENT_PROTOCOL "current protocol"
#define M_SAVED_VARIABLES "saved variables"
#define M_CURRENT_SAVED_VARIABLES "current saved variables"
#define M_DATA_FILE_AUTO_OPEN "data file auto open"
#define M_DATA_FILE_NAME "data file name"

#define M_DATA_FILE_FILENAME "file"
Expand Down

0 comments on commit 9678cd5

Please sign in to comment.