/* * yasdi4j -- Java Binding for YASDI * Copyright (c) 2008 Michael Denk <code@michaeldenk.de> * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ package de.michaeldenk.yasdi4j; import java.io.IOException; import java.util.ArrayList; import java.util.List; /** * <code>YasdiMaster</code> is the high level interface to the YASDI master * library functions. * <p> * A typical invocation looks like this: After getting the instance of this * class, we have to initialize the master (this is to remind you, that you have * to call {@link #shutdown()} when you're done). initialize and shutdown may * only be called once. Once the master is shut down it is in a state where it * can't be used anymore, and it cannot be initialized again.<blockquote> * * <pre> * YasdiMaster master = YasdiMaster.getInstance(); * master.initialize(); * </pre> * * </blockquote> * <p> * After the initialization we have to set one or more drivers online (don't * forget to set them offline when you're done). For simplicity we only set the * first driver online.<blockquote> * * <pre> * YasdiDriver[] drivers = master.getDrivers(); * master.setDriverOnline(drivers[0]); * </pre> * * </blockquote> * <p> * Now we can start the device detection. Let's say we have only one device. * <blockquote> * * <pre> * master.detectDevices(1); * ... // do something with the devices * </pre> * * </blockquote> * <p> * We're finished, clean up. <blockquote> * * <pre> * master.setDriverOffline(drivers[0]); * master.shutdown(); * </pre> * * </blockquote> * * @author Michael Denk <code@michaeldenk.de> */ public class YasdiMaster { static { System.loadLibrary("yasdi"); System.loadLibrary("yasdimaster"); System.loadLibrary("yasdi4j"); } /** * The different states of the master. */ public enum State { NOT_INITIALIZED, INITIALIZED, DEVICE_DETECTION, SHUTDOWN }; @SuppressWarnings(value = "unused") private String configFile; private State state; private YasdiDriver[] drivers; private List<YasdiDriver> activeDrivers; private YasdiDevice[] devices; private List<YasdiDeviceListener> deviceListeners; private static YasdiMaster instance = new YasdiMaster(); /** * Constructs a new YasdiMaster that is initially not initialized. */ private YasdiMaster() { state = State.NOT_INITIALIZED; activeDrivers = new ArrayList<YasdiDriver>(); drivers = new YasdiDriver[0]; devices = new YasdiDevice[0]; deviceListeners = new ArrayList<YasdiDeviceListener>(); } /** * Returns the only instance of <code>YasdiMaster</code>. */ public static YasdiMaster getInstance() { return instance; } /** * Initializes the master with the INI file <tt>yasdi.ini</tt>. This is the * same as calling {@link #initialize(String) initialize("yasdi.ini")}. */ public void initialize() throws IOException { initialize("yasdi.ini"); } /** * Initializes the master with the INI file <tt>configFile</tt> * * @param configFile * @throws IOException * if <tt>configFile</tt> doesn't exist or is not readable. */ public void initialize(String configFile) throws IOException { if (state.equals(State.SHUTDOWN)) { throw new IllegalStateException("Master is already shut down"); } if (!state.equals(State.NOT_INITIALIZED)) { throw new IllegalStateException("Master is already initialized"); } if (configFile == null) { throw new NullPointerException(); } this.configFile = configFile; // initializes drivers c_initialize(configFile); state = State.INITIALIZED; } /** * Shuts down the master. This method should be called when you're done * using the master. When the master is shut down, you can't use it anymore * and you can't initialize it again. Thus this is the final method to call. */ public void shutdown() { ensureInitialized(); state = State.SHUTDOWN; deviceListeners.clear(); for (YasdiDriver d : activeDrivers) { c_setDriverOffline(d.getId()); } activeDrivers.clear(); devices = new YasdiDevice[0]; drivers = new YasdiDriver[0]; c_shutdown(); } /** * Resets the master. After calling this method, the master is in the same * state as after calling initialize. */ public void reset() { ensureInitialized(); state = State.INITIALIZED; deviceListeners.clear(); for (YasdiDriver d : activeDrivers) { c_setDriverOffline(d.getId()); } activeDrivers.clear(); devices = new YasdiDevice[0]; c_reset(); } /** * Returns the number of available drivers. */ public int getNrDrivers() { return drivers.length; } /** * Returns a copy of the array of available drivers. */ public YasdiDriver[] getDrivers() { YasdiDriver[] d = new YasdiDriver[drivers.length]; System.arraycopy(drivers, 0, d, 0, d.length); return d; } /** * Sets the driver <tt>d</tt> online. * * @throws IOException * if the driver can't be set online */ public void setDriverOnline(YasdiDriver d) throws IOException { ensureInitialized(); if (c_setDriverOnline(d.getId())) { activeDrivers.add(d); } else { throw new IOException("Unable to set driver " + d.getName() + " online"); } } /** * Sets the driver <tt>d</tt> offline. */ public void setDriverOffline(YasdiDriver d) { ensureInitialized(); c_setDriverOffline(d.getId()); activeDrivers.remove(d); } /** * Starts the device detection. * * @param nrDevices * the minimum nr of devices to detect * @throws IOException * if fewer than <tt>nrDevices</tt> devices are detected or if * no devices can be detected at all. */ public void detectDevices(int nrDevices) throws IOException { ensureInitialized(); state = State.DEVICE_DETECTION; try { c_detectDevices(nrDevices); } catch (IOException e) { state = State.INITIALIZED; throw e; } state = State.INITIALIZED; } /** * Returns the number of detected devices. */ public int getNrDevices() { return devices.length; } /** * Returns a copy of the array of detected devices. */ public YasdiDevice[] getDevices() { YasdiDevice[] d = new YasdiDevice[devices.length]; System.arraycopy(devices, 0, d, 0, d.length); return d; } /** * Adds a device event listener to the device event listener list. */ public void addDeviceListener(YasdiDeviceListener l) { if (l == null) { return; } deviceListeners.add(l); } /** * Removes a device event listener from the device event listener list. */ public void removeDeviceListener(YasdiDeviceListener l) { if (l == null) { return; } deviceListeners.remove(l); } /** * Sets the access level of YASDI (see YASDI manual for details). * * @param user * the user name * @param password * the password * @return true if the access level change was successful; false otherwise. */ public boolean setAccessLevel(String user, String password) { if (user == null || password == null) { throw new NullPointerException(); } return c_setAccessLevel(user, password); } /** * Returns the current state of the master. */ public State getState() { return state; } void ensureInitialized() { if (state.equals(State.NOT_INITIALIZED)) { throw new IllegalStateException("Master is not initialized"); } else if (state.equals(State.SHUTDOWN)) { throw new IllegalStateException("Master is already shut down"); } else if (state.equals(State.DEVICE_DETECTION)) { throw new IllegalStateException( "Master is in device detection state"); } } // used by native code @SuppressWarnings(value = "unused") private void deviceAdded(int handle, String name, long sn, String type) { YasdiDeviceEvent e = new YasdiDeviceEvent(new YasdiDevice(this, handle, name, sn, type)); for (YasdiDeviceListener l : deviceListeners) { l.deviceAdded(e); } } // used by native code @SuppressWarnings(value = "unused") private void deviceRemoved(int handle, String name, long sn, String type) { YasdiDeviceEvent e = new YasdiDeviceEvent(new YasdiDevice(this, handle, name, sn, type)); for (YasdiDeviceListener l : deviceListeners) { l.deviceRemoved(e); } } private native void c_initialize(String configFile) throws IOException; private native void c_shutdown(); private native void c_reset(); private native boolean c_setDriverOnline(int DriverID); private native void c_setDriverOffline(int DriverID); private native void c_detectDevices(int nrDevices) throws IOException; private native boolean c_setAccessLevel(String user, String password); }