view Experiment.java @ 50:09fcd3fbfe1e

Print discrepancy in number of arguments if incorrect.
author Marcus Pearce <marcus.pearce@eecs.qmul.ac.uk>
date Wed, 25 Feb 2015 10:10:00 +0000
parents e4ad783e5f95
children
line wrap: on
line source
/*=============================================================================
 * File:       Experiment.java
 * Author:     Marcus Pearce <m.pearce@gold.ac.uk>
 * Created:    <2007-02-14 11:28:27 marcusp>
 * Time-stamp: <2015-02-25 09:43:12 marcusp>
 *=============================================================================
 */

import java.io.*;
import javax.swing.UIManager; 
import java.awt.*;
import javax.sound.midi.*;
import java.util.Scanner;

public class Experiment { 

    /* pathnames */ 
    private final String BASE_DIRECTORY = 
        new File("").getAbsolutePath() + File.separator; 
    private final String DATA_DIRECTORY = 
        BASE_DIRECTORY + "Data" + File.separator; 

    public String RESULTS_DIRECTORY = 
        BASE_DIRECTORY + "Results" + File.separator; 
    public String RESULTS_EXTENSION = ".dat"; 
    public String SUBJECT_RESULTS_FILE = 
        RESULTS_DIRECTORY + "subjects" + RESULTS_EXTENSION; 
    
    public String INSTRUCTIONS_FILE = 
        DATA_DIRECTORY + "instructions.html"; 

    public String MIDI_DIRECTORY = 
        DATA_DIRECTORY + "Midi" + File.separator;
    public String MIDIFILELIST_FILE = 
        MIDI_DIRECTORY + "filelist.txt"; 
    public String PRACTICE_MIDIFILELIST_FILE = 
        MIDI_DIRECTORY + "pfilelist.txt";
    public String POST_SCRIPT;


    /* The GUI */ 
    private ExperimentGui gui;
    private boolean fullScreen;

    /* whether to show the clock */
    private boolean showClock;
    /* the units of the clock as multiples of the tatum */
    private int clockUnits; 
    /* number of units that clock runs for before a probe event */ 
    private int numUnits; 

    /* whether to ask about familiarity of each song */
    private boolean askFamiliarity;
    /* whether to ask about liking of each song */
    private boolean askLiking;
    /* whether to include final questionnaire */
    private boolean finalQuestionnaire;
    
    /* the blocks of the experiment */ 
    Block[] blocks;
    int currentBlockID; 
    
    /* Subject ID */ 
    private String subjectID; 

    /* Results */ 
    private SubjectResults results; 

    /* the details of the rating scale */
    private int scaleLength;
    private String lowAnchor;
    private String highAnchor;

    /* the midi device */
    private int midiDevice;
    
    /* debugging */ 
    private boolean debug;
    
    /* Post-run script */
    private boolean runPostScript;

    /* accessors */ 
    public boolean getDebug() { return debug; }
    public boolean getAskLiking() { return askLiking; }
    public boolean getAskFamiliarity() { return askFamiliarity; }
    public boolean getFinalQuestionnaire() { return finalQuestionnaire; }

    public int getMidiDeviceNumber() { return midiDevice; }
    public int getScaleLength() { return scaleLength; }
    public String getLowAnchor() { return lowAnchor; }
    public String getHighAnchor() { return highAnchor; }

    public String getMidiDirectory() { return MIDI_DIRECTORY; }
    public SubjectResults getSubjectResults() { return results; }
    public Block getCurrentBlock() { return blocks[currentBlockID]; }
    public int getCurrentBlockID() { return currentBlockID + 1; }
    public boolean showClock() { return showClock; }
    public int getClockUnits() { return clockUnits; } 
    public int getNumUnits() { return numUnits; } 
    public String getInstructionsFile() { return INSTRUCTIONS_FILE; }
    public String getSubjectID() { return subjectID; }
    public boolean getRunPostScript() { return runPostScript; }
    public void setSubjectID(String id) { 
        subjectID = id; 
        results.setSubjectID(id); 
        results.setOutputFile(id);
        results.setSubjectDataFile(id);
        getCurrentBlock().getMelodyResults().setSubjectID(id); 
	System.out.println("Subject ID = " + subjectID);
    }

    /* Constructor */ 
    public Experiment (int sc, int cu, int nu, int sl, int md, String la, String ha, String mfd, String inf, String rdr, int fam, int lik, int quest, int fs, String ps, int de) {
        
        // Setup variables 
	debug = (de != 0);
        results = new SubjectResults(this); 
        if (sc == 0) 
            showClock = false;
        else 
            showClock = true;
        clockUnits = positiveInteger(cu, 1); 
	numUnits = positiveInteger(nu, 4); 
        scaleLength = positiveInteger(sl, 7);
        midiDevice = md;
        lowAnchor = la;
        highAnchor = ha;
        MIDI_DIRECTORY = mfd + File.separator;
        MIDIFILELIST_FILE = MIDI_DIRECTORY + "filelist.txt"; 
        PRACTICE_MIDIFILELIST_FILE = MIDI_DIRECTORY + "pfilelist.txt"; 
        INSTRUCTIONS_FILE = inf;
        RESULTS_DIRECTORY = rdr + File.separator;
        
        if (fs == 0)
            fullScreen = false;
        else
            fullScreen = true;
        if (ps.equals("0"))
            runPostScript = false;
        else{
            runPostScript = true;
            POST_SCRIPT = ps;
        }
        if (fam == 0)
            askFamiliarity = false;
        else 
            askFamiliarity = true; 
        if (lik == 0)
            askLiking = false;
        else 
            askLiking = true; 
        if (quest == 0)
            finalQuestionnaire = false;
        else 
            finalQuestionnaire = true; 

	if (debug)
	    displayMIDIDevices();

        // Initialise the experiment 
        Block practice = new Block(this, gui, PRACTICE_MIDIFILELIST_FILE, 
                                   "Practice", false); 
        Block main = new Block(this, gui, MIDIFILELIST_FILE, 
                               "Main", true); 
        blocks  = new Block[2]; 
        blocks[0] = practice; 
        blocks[1] = main; 
        currentBlockID = 0; 

        // Create the GUI 
        gui = new ExperimentGui(this); 
    }

    public Boolean nextBlock() { 
        boolean lastBlock = true; 
        if (currentBlockID + 1 < blocks.length) 
            currentBlockID = currentBlockID + 1; 
        else 
            lastBlock = false; 
        return lastBlock; 
    }

    public void addToSubjectResults(MelodyResults mr) { results.addResult(mr); }

    public void runExperiment () { 
        (new Thread(gui)).start();
        getCurrentBlock().presentStimulus(); 
    }
    public boolean isRunning() {
	Block cur = getCurrentBlock();;
	return cur != null && cur.isRunning();
    }
    
    public boolean hasRun() {
	Block cur = getCurrentBlock();
	return cur == null || cur.hasRun();
    } 

    /* Show the GUI */ 
    public void showGUI(int width, int height) {
        GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
        if(fullScreen){
            if (gd.isFullScreenSupported()) {
                System.out.println("Entering full Screen... Press <enter> to continue.");
                Scanner scanner = new Scanner(System.in);
                scanner.nextLine();
                gui.setUndecorated(true);
                gd.setFullScreenWindow(gui);
            } else {
                System.out.println("Not Full Screen Supported :(");
                showDefaultGUI(width, height);
            }
        }
        else{
            showDefaultGUI(width, height);
        }
    }
    
    public void showDefaultGUI(int width, int height) {
        gui.pack();
        gui.setSize(width, height);
        // UIManager.put("Button.focus", UIManager.get("Button.select"));
        gui.setVisible(true);
    }

    /* Main method */
    public static void main(String[] args) {

        Toolkit.getDefaultToolkit();
	
        System.out.println("Working Directory = " +
                           System.getProperty("user.dir"));
        
        int nargs = 16;

	if (args.length == nargs) {

        // Parse Arguments 
        int n = 0;
        int sc = Integer.parseInt(args[n++]); 
        int cu = Integer.parseInt(args[n++]); 
        int nu = Integer.parseInt(args[n++]); 
        String mdInput = args[n++];
        int md = -1;
        int sl = Integer.parseInt(args[n++]); 
        String la = args[n++];
        String ha = args[n++];
        String mfd = args[n++];
        String inf = args[n++];
        String rdr = args[n++];
        int fam = Integer.parseInt(args[n++]);
        int lik = Integer.parseInt(args[n++]);
        int quest = Integer.parseInt(args[n++]);
        int fs = Integer.parseInt(args[n++]);
        String ps = args[n++];
        int de = Integer.parseInt(args[n++]);

    if(isBooleanFormat(mdInput)){
        boolean defaultMD = Boolean.parseBoolean(mdInput);
        
        if(!defaultMD){
            displayMIDIDevices();
            System.out.print("Specify the desired MIDI Device: ");
            Scanner scan = new Scanner(System.in);
            String input = scan.next();
            
            while(!isMIDIDevice(input)){
                System.out.print("Enter a valid input:");
                input = scan.next();
            }
            md = Integer.parseInt(input);
        }
        else{
            md = -1;
        }
    }
    else if(isMIDIDevice(mdInput)){
            md = Integer.parseInt(mdInput);
    }
    else{
        System.out.println("Unexpected number of arguments: " + args.length + ". Should be " + nargs + ".");
        showUsage();
    }

        // Create experiment 
        Experiment exp = new Experiment(sc, cu, nu, sl, md, la, ha, mfd, inf, rdr, fam, lik, quest, fs, ps, de);
        
        // Show the GUI 
        int width=(int)Toolkit.getDefaultToolkit().getScreenSize().getWidth();
        int height=(int)Toolkit.getDefaultToolkit().getScreenSize().getHeight();
        exp.showGUI(width, height); 

	} else {
        showUsage();
	}
    }
    
    public static void showUsage(){
        System.out.println("Usage: " + "\t" + "java Experiment " +
                           "<show clock?> <clock units> <number of units> " +
                           "<default MIDI device?> " +
                           "<scale length> <low anchor> <high anchor> " +
                           "<midi file directory> <instructions file> <results directory> " +
                           " <familiarity> " + " <pleasantness> " + " <questionnaire> " + " <fullscreen> " + " <post-run script> " + " <debug>");
        System.exit(1);
    }

    /*
     * Print a list of accessible MIDI devices
     */
    public static void displayMIDIDevices() {
	System.out.println("Searching for MIDI devices...");
	    
	MidiDevice.Info[] devices = MidiSystem.getMidiDeviceInfo();
	if (devices.length == 0) {
	    System.out.println("No MIDI devices found");
	} else {
	    for (int i=0; i<devices.length; i++) {
            MidiDevice.Info m = devices[i];
            System.out.println(i+". MIDI device: " + m.getName() + " - " + m.getDescription());
	    }
	}
    }
    
    public static boolean isBooleanFormat(String s){
        if(s.toLowerCase().equals("true") || s.toLowerCase().equals("false")){
            return true;
        }
        else {
            return false;
        }
    }

	public static boolean isMIDIDevice(String dev){
		boolean output;
        MidiDevice.Info[] devices = MidiSystem.getMidiDeviceInfo();
        
		try {
			int device = Integer.parseInt(dev);
            if(device>devices.length-1 || device<0){
                output = false;
            }
            else { output = true; }
		} catch(NumberFormatException e) {
			output = false;
		}
		return output;
	}

    private int positiveInteger(int x, int def) {
	if (x > 0) 
	    return x;
	else
	    return def;
    }

}