diff --git a/java/build.gradle b/java/build.gradle new file mode 100644 index 0000000..a81b2f9 --- /dev/null +++ b/java/build.gradle @@ -0,0 +1,16 @@ +subprojects { + apply plugin: 'java' + apply plugin: 'eclipse' + + repositories { + mavenCentral() + } + + dependencies { + } + + version = '0.1' + + jar { + } +} diff --git a/java/itunescontroller/.classpath b/java/itunescontroller/.classpath new file mode 100644 index 0000000..4589d57 --- /dev/null +++ b/java/itunescontroller/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/java/itunescontroller/.project b/java/itunescontroller/.project new file mode 100644 index 0000000..3e38131 --- /dev/null +++ b/java/itunescontroller/.project @@ -0,0 +1,18 @@ + + + itunescontroller + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.springsource.ide.eclipse.gradle.core.nature + org.eclipse.jdt.core.javanature + + diff --git a/java/itunescontroller/build.gradle b/java/itunescontroller/build.gradle new file mode 100644 index 0000000..9c99f6a --- /dev/null +++ b/java/itunescontroller/build.gradle @@ -0,0 +1,3 @@ +dependencies { + compile 'net.sf.jacob-project:jacob:1.+' +} diff --git a/java/itunescontroller/src/main/java/com/dt/iTunesController/ITArtwork.java b/java/itunescontroller/src/main/java/com/dt/iTunesController/ITArtwork.java new file mode 100644 index 0000000..53846c9 --- /dev/null +++ b/java/itunescontroller/src/main/java/com/dt/iTunesController/ITArtwork.java @@ -0,0 +1,55 @@ +package com.dt.iTunesController; +import com.jacob.com.Dispatch; + +/** + * Represents a artwork. + * + * Defines a single piece of artwork. + * + * Artwork is always associated with an individual track. + * To add a piece of artwork to a track, use IITTrack::AddArtworkFromFile(). + * The IITTrack::Artwork property + * + * To get a collection of artwork associated with a track call + * ITTrack.getArtwork(). + * + * @author Steve Eyre + * @version 0.2 + */ +public class ITArtwork extends ITObject { + + public ITArtwork (Dispatch d) { + super(d); + } + + /** + * Delete this object. + */ + public void delete() { + Dispatch.call(object, "Delete"); + } + + /** + * Returns the kind of the object. + * @return Returns the kind of the object. + */ + public ITArtworkFormat getFormat() { + return ITArtworkFormat.values()[Dispatch.get(object, "Format").getInt()]; + } + + // TODO: Comments + + public boolean getIsDownloadedArtwork() { + return Dispatch.get(object, "IsDownloadedArtwork").getBoolean(); + } + + public String getDescription() { + return Dispatch.get(object, "Description").getString(); + + } + + public void SaveArtworkToFile(String filePath) { + Dispatch.call(object, "SaveArtworkToFile",filePath); + } + +} diff --git a/java/itunescontroller/src/main/java/com/dt/iTunesController/ITArtworkCollection.java b/java/itunescontroller/src/main/java/com/dt/iTunesController/ITArtworkCollection.java new file mode 100644 index 0000000..c1d8afa --- /dev/null +++ b/java/itunescontroller/src/main/java/com/dt/iTunesController/ITArtworkCollection.java @@ -0,0 +1,55 @@ +package com.dt.iTunesController; +import com.jacob.com.Dispatch; + +/** + * Represents a collection of Artwork objects. + * + * Note that collection indices are always 1-based. + * + * You can retrieve all the Artworks defined for a source using + * ITSource.getArtwork(). + * + * @author Steve Eyre + * @version 0.2 + */ +public class ITArtworkCollection { + + protected Dispatch object; + + public ITArtworkCollection(Dispatch d) { + object = d; + } + + /** + * Returns the number of playlists in the collection. + * @return Returns the number of playlists in the collection. + */ + public int getCount() { + return Dispatch.get(object, "Count").getInt(); + } + + /** + * Returns an ITArtwork object corresponding to the given index (1-based). + * @param index Index of the playlist to retrieve, must be less than or + * equal to ITArtworkCollection.getCount(). + * @return Returns an ITArtwork object corresponding to the given index. + * Will be set to NULL if no playlist could be retrieved. + */ + public ITArtwork getItem (int index) { + Dispatch item = Dispatch.call(object, "Item", index).toDispatch(); + return new ITArtwork(item); + } + + /** + * Returns an ITArtwork object with the specified persistent ID. See the + * documentation on ITObject for more information on persistent IDs. + * @param highID The high 32 bits of the 64-bit persistent ID. + * @param lowID The low 32 bits of the 64-bit persistent ID. + * @return Returns an ITArtwork object with the specified persistent ID. + * Will be set to NULL if no playlist could be retrieved. + */ + public ITArtwork getItemByPersistentID (int highID, int lowID) { + Dispatch item = Dispatch.call(object, "ItemByPersistentID", highID, lowID).toDispatch(); + return new ITArtwork(item); + } +} diff --git a/java/itunescontroller/src/main/java/com/dt/iTunesController/ITArtworkFormat.java b/java/itunescontroller/src/main/java/com/dt/iTunesController/ITArtworkFormat.java new file mode 100644 index 0000000..ed4b61e --- /dev/null +++ b/java/itunescontroller/src/main/java/com/dt/iTunesController/ITArtworkFormat.java @@ -0,0 +1,13 @@ +package com.dt.iTunesController; + +/** + * Specifies the Artwork kind. + * @author Steve Eyre + * @version 0.2 + */ +public enum ITArtworkFormat { + ITArtworkFormatUnknown, + ITArtworkFormatJPEG, + ITArtworkFormatPNG, + ITArtworkFormatBMP; +} diff --git a/java/itunescontroller/src/main/java/com/dt/iTunesController/ITAudioCDPlaylist.java b/java/itunescontroller/src/main/java/com/dt/iTunesController/ITAudioCDPlaylist.java new file mode 100644 index 0000000..bc12943 --- /dev/null +++ b/java/itunescontroller/src/main/java/com/dt/iTunesController/ITAudioCDPlaylist.java @@ -0,0 +1,76 @@ +package com.dt.iTunesController; +import com.jacob.com.Dispatch; + +/** + * Represents an audio CD playlist. + * + * An audio CD playlist is always associated with an IITSource of kind + * ITSourceKindAudioCD. + * + * You can retrieve all the playlists defined for a source using + * ITSource.getPlaylists(). + * @author Steve Eyre + * @version 0.2 + */ +public class ITAudioCDPlaylist extends ITPlaylist { + + public ITAudioCDPlaylist(Dispatch d) { + super(d); + } + + /** + * Returns the audio CD's artist. + * @return Returns the audio CD's artist. + */ + public String getArtist() { + return Dispatch.get(object, "Artist").getString(); + } + + /** + * Returns true if this audio CD is a compilation album. + * @return Returns true if this audio CD is a compilation album. + */ + public boolean isCompilation() { + return Dispatch.get(object, "Compilation").getBoolean(); + } + + /** + * Returns the audio CD's composer. + * @return Returns the audio CD's composer. + */ + public String getComposer() { + return Dispatch.get(object, "Composer").getString(); + } + + /** + * Returns the total number of discs in this CD's album. + * @return Returns the total number of discs in this CD's album. + */ + public long getDiscCount() { + return Dispatch.get(object, "DiscCount").getLong(); + } + + /** + * Returns the index of the CD disc in the source album. + * @return Returns the index of the CD disc in the source album. + */ + public long getDiscNumber() { + return Dispatch.get(object, "DiscNumber").getLong(); + } + + /** + * Returns the audio CD's genre. + * @return Returns the audio CD's genre. + */ + public String getGenre() { + return Dispatch.get(object, "Genre").getString(); + } + + /** + * Reveals the CD playlist in the main browser window. + */ + public void reveal() { + Dispatch.call(object, "Reveal"); + } + +} diff --git a/java/itunescontroller/src/main/java/com/dt/iTunesController/ITBrowserWindow.java b/java/itunescontroller/src/main/java/com/dt/iTunesController/ITBrowserWindow.java new file mode 100644 index 0000000..16dc6cf --- /dev/null +++ b/java/itunescontroller/src/main/java/com/dt/iTunesController/ITBrowserWindow.java @@ -0,0 +1,45 @@ +package com.dt.iTunesController; +import com.jacob.com.Dispatch; + +/** + * Represents the main browser window. + * + * You can retrieve the main browser window using + * iTunes.BrowserWindow(). + * + * @author Steve Eyre + * @version 0.2 + */ + +public class ITBrowserWindow extends ITWindow { + + public ITBrowserWindow (Dispatch d) { + super(d); + } + + /** + * Returns the kind of the object. + * @return Returns the kind of the object. + */ + public boolean getMiniPlayer() { + return Dispatch.get(object, "MiniPlayer").getBoolean(); + } + + // TODO: Comments + + public ITTrackCollection getSelectedTracks() { + Dispatch collection = Dispatch.call(object, "SelectedTracks").getDispatch(); + return new ITTrackCollection(collection); + } + + public ITPlaylist getSelectedPlaylist() { + Dispatch playlist = Dispatch.get(object, "SelectedPlaylist").toDispatch(); + return new ITPlaylist(playlist); + } + + public void setSelectedPlaylist(ITPlaylist playlist) { + Dispatch dispatchRef = playlist.fetchDispatch(); + Dispatch.put(object, "SelectedPlaylist", dispatchRef); + } + +} diff --git a/java/itunescontroller/src/main/java/com/dt/iTunesController/ITCOMDisabledReason.java b/java/itunescontroller/src/main/java/com/dt/iTunesController/ITCOMDisabledReason.java new file mode 100644 index 0000000..500280c --- /dev/null +++ b/java/itunescontroller/src/main/java/com/dt/iTunesController/ITCOMDisabledReason.java @@ -0,0 +1,12 @@ +package com.dt.iTunesController; + +/** + * Specifies the reason the COM interface is being disabled. + * @author Steve Eyre + * @version 0.2 + */ +public enum ITCOMDisabledReason { + ITCOMDisabledReasonOther, + ITCOMDisabledReasonDialog, + ITCOMDisabledReasonQuitting; +} diff --git a/java/itunescontroller/src/main/java/com/dt/iTunesController/ITEQPreset.java b/java/itunescontroller/src/main/java/com/dt/iTunesController/ITEQPreset.java new file mode 100644 index 0000000..1d00cfb --- /dev/null +++ b/java/itunescontroller/src/main/java/com/dt/iTunesController/ITEQPreset.java @@ -0,0 +1,236 @@ +package com.dt.iTunesController; + +import com.jacob.com.Dispatch; + +/** + * Represents an equalizer preset. + * You can retrieve or set the currently selected EQ preset using the + * iTunes.getCurrentEQPreset() method. + * @author Steve Eyre + * @version 0.2 + */ +public class ITEQPreset { + + protected Dispatch object; + + public ITEQPreset(Dispatch d) { + object = d; + } + + /** + * Returns the name of the EQ Preset (e.g. "Acoustic"). + * @return Returns the name of the EQ Preset (e.g. "Acoustic"). + */ + public String getName() { + return Dispatch.get(object, "Name").getString(); + } + + /** + * Returns true if the EQ preset can be modified. + * @return True if the EQ preset can be modified. + */ + public boolean getModifiable() { + return Dispatch.get(object, "Modifiable").getBoolean(); + } + + /** + * Set the equalizer preamp level (-12.0 db to +12.0 db). + * @param level The new equalizer preamp level (-12.0 db to +12.0 db). + */ + public void setPreamp(double level) { + Dispatch.put(object, "Preamp", level); + } + + /** + * Returns the equalizer preamp level (-12.0db to +12.0db). + * @return Returns the equalizer preamp level (-12.0db to +12.0db). + */ + public double getPreamp() { + return Dispatch.get(object, "Preamp").getDouble(); + } + + /** + * Set the equalizer 32Hz level (-12.0 db to +12.0 db). + * @param level The new equalizer 32Hz level (-12.0 db to +12.0db). + */ + public void setBand1(double level) { + Dispatch.put(object, "Band1", level); + } + + /** + * Returns the equalizer 32Hz level (-12.0 db to +12.0 db). + * @return Returns the equalizer 32Hz level (-12.0 db to +12.0 db). + */ + public double getBand1() { + return Dispatch.get(object, "Band1").getDouble(); + } + + /** + * Set the equalizer 64Hz level (-12.0 db to +12.0 db). + * @param level The new equalizer 64Hz level (-12.0 db to +12.0db). + */ + public void setBand2(double level) { + Dispatch.put(object, "Band2", level); + } + + /** + * Returns the equalizer 64Hz level (-12.0 db to +12.0 db). + * @return Returns the equalizer 64Hz level (-12.0 db to +12.0 db). + */ + public double getBand2() { + return Dispatch.get(object, "Band2").getDouble(); + } + + /** + * Set the equalizer 125Hz level (-12.0 db to +12.0 db). + * @param level The new equalizer 125Hz level (-12.0 db to +12.0db). + */ + public void setBand3(double level) { + Dispatch.put(object, "Band3", level); + } + + /** + * Returns the equalizer 125Hz level (-12.0 db to +12.0 db). + * @return Returns the equalizer 125Hz level (-12.0 db to +12.0 db). + */ + public double getBand3() { + return Dispatch.get(object, "Band3").getDouble(); + } + + /** + * Set the equalizer 250Hz level (-12.0 db to +12.0 db). + * @param level The new equalizer 250Hz level (-12.0 db to +12.0db). + */ + public void setBand4(double level) { + Dispatch.put(object, "Band4", level); + } + + /** + * Returns the equalizer 250Hz level (-12.0 db to +12.0 db). + * @return Returns the equalizer 250Hz level (-12.0 db to +12.0 db). + */ + public double getBand4() { + return Dispatch.get(object, "Band4").getDouble(); + } + + /** + * Set the equalizer 500Hz level (-12.0 db to +12.0 db). + * @param level The new equalizer 500Hz level (-12.0 db to +12.0db). + */ + public void setBand5(double level) { + Dispatch.put(object, "Band5", level); + } + + /** + * Returns the equalizer 500Hz level (-12.0 db to +12.0 db). + * @return Returns the equalizer 500Hz level (-12.0 db to +12.0 db). + */ + public double getBand5() { + return Dispatch.get(object, "Band5").getDouble(); + } + + /** + * Set the equalizer 1KHz level (-12.0 db to +12.0 db). + * @param level The new equalizer 1KHz level (-12.0 db to +12.0db). + */ + public void setBand6(double level) { + Dispatch.put(object, "Band6", level); + } + + /** + * Returns the equalizer 1KHz level (-12.0 db to +12.0 db). + * @return Returns the equalizer 1KHz level (-12.0 db to +12.0 db). + */ + public double getBand6() { + return Dispatch.get(object, "Band6").getDouble(); + } + + /** + * Set the equalizer 2KHz level (-12.0 db to +12.0 db). + * @param level The new equalizer 2KHz level (-12.0 db to +12.0db). + */ + public void setBand7(double level) { + Dispatch.put(object, "Band7", level); + } + + /** + * Returns the equalizer 2KHz level (-12.0 db to +12.0 db). + * @return Returns the equalizer 2KHz level (-12.0 db to +12.0 db). + */ + public double getBand7() { + return Dispatch.get(object, "Band7").getDouble(); + } + + /** + * Set the equalizer 4KHz level (-12.0 db to +12.0 db). + * @param level The new equalizer 4KHz level (-12.0 db to +12.0db). + */ + public void setBand8(double level) { + Dispatch.put(object, "Band8", level); + } + + /** + * Returns the equalizer 4KHz level (-12.0 db to +12.0 db). + * @return Returns the equalizer 4KHz level (-12.0 db to +12.0 db). + */ + public double getBand8() { + return Dispatch.get(object, "Band8").getDouble(); + } + + /** + * Set the equalizer 8KHz level (-12.0 db to +12.0 db). + * @param level The new equalizer 8KHz level (-12.0 db to +12.0db). + */ + public void setBand9(double level) { + Dispatch.put(object, "Band9", level); + } + + /** + * Returns the equalizer 8KHz level (-12.0 db to +12.0 db). + * @return Returns the equalizer 8KHz level (-12.0 db to +12.0 db). + */ + public double getBand9() { + return Dispatch.get(object, "Band9").getDouble(); + } + + /** + * Set the equalizer 16KHz level (-12.0 db to +12.0 db). + * @param level The new equalizer 16KHz level (-12.0 db to +12.0db). + */ + public void setBand10(double level) { + Dispatch.put(object, "Band10", level); + } + + /** + * Returns the equalizer 16KHz level (-12.0 db to +12.0 db). + * @return Returns the equalizer 16KHz level (-12.0 db to +12.0 db). + */ + public double getBand10() { + return Dispatch.get(object, "Band10").getDouble(); + } + + /** + * Delete this EQ Preset. + * Any EQ preset can be deleted, including built-in presets, except for the + * Manual preset. + * @param updateAllTracks If true, any tracks that use this EQ preet will be + * set to have no assigned EQ preset. + */ + public void delete(boolean updateAllTracks) { + Dispatch.call(object, "Delete", updateAllTracks); + } + + /** + * Rename this EQ Preset. + * The name of any EQ preset can be changed, including built-in presets, + * except for the Manual preset. + * EQ preset names cannot start with leading spaces. If you specify a name + * that starts with leading spaces they will be stripped out. + * @param updateAllTracks If true, any tracks that use this EQ preet will be + * updated with the new preset name. + */ + public void rename(String newName, boolean updateAllTracks) { + Dispatch.call(object, "Rename", newName, updateAllTracks); + } + +} diff --git a/java/itunescontroller/src/main/java/com/dt/iTunesController/ITFileOrCDTrack.java b/java/itunescontroller/src/main/java/com/dt/iTunesController/ITFileOrCDTrack.java new file mode 100644 index 0000000..570896c --- /dev/null +++ b/java/itunescontroller/src/main/java/com/dt/iTunesController/ITFileOrCDTrack.java @@ -0,0 +1,39 @@ +package com.dt.iTunesController; +import com.jacob.com.Dispatch; + +/** + * Represents a file or CD track. + * @author Steve Eyre + * @version 0.2 + */ +public class ITFileOrCDTrack extends ITTrack { + + public ITFileOrCDTrack (Dispatch d) { + super(d); + } + + /** + * Reveals the track in the main browser window. + */ + public void reveal() { + Dispatch.call(object, "Reveal"); + } + + public ITVideoKind getVideoKind() { + return ITVideoKind.values()[Dispatch.get(object, "VideoKind").getInt()]; + } + + public ITRatingKind getRatingKind() { + return ITRatingKind.values()[Dispatch.get(object, "RatingKind").getInt()]; + } + + public String getLocation() { + return Dispatch.get(object, "Location").getString(); + } + + public ITArtworkCollection getArtworks() { + Dispatch artworks = Dispatch.get(object, "Artwork").toDispatch(); + return new ITArtworkCollection(artworks); + } + +} diff --git a/java/itunescontroller/src/main/java/com/dt/iTunesController/ITLibraryPlaylist.java b/java/itunescontroller/src/main/java/com/dt/iTunesController/ITLibraryPlaylist.java new file mode 100644 index 0000000..c19cba8 --- /dev/null +++ b/java/itunescontroller/src/main/java/com/dt/iTunesController/ITLibraryPlaylist.java @@ -0,0 +1,20 @@ +package com.dt.iTunesController; +import com.jacob.com.Dispatch; + +/** + * Represents a library playlist. + * + * A library playlist consists of all the tracks in a user's library. + * + * For convenience, you can retrieve the main library playlist using + * iTunes.getLibraryPlaylist(). + * @author Steve Eyre + * @version 0.2 + */ +public class ITLibraryPlaylist extends ITPlaylist { + + public ITLibraryPlaylist(Dispatch d) { + super(d); + } + +} diff --git a/java/itunescontroller/src/main/java/com/dt/iTunesController/ITObject.java b/java/itunescontroller/src/main/java/com/dt/iTunesController/ITObject.java new file mode 100644 index 0000000..27475fd --- /dev/null +++ b/java/itunescontroller/src/main/java/com/dt/iTunesController/ITObject.java @@ -0,0 +1,112 @@ +package com.dt.iTunesController; +import com.jacob.com.Dispatch; + +/** + * Defines a source, playlist or track. + * + * An ITObject uniquely identifies a source, playlist, or track in iTunes using + * four separate IDs. These are runtime IDs, they are only valid while the + * current instance of iTunes is running. + * + * As of iTunes 7.7, you can also identify an ITObject using a 64-bit persistent + * ID, which is valid across multiple invocations of iTunes. + * + * The main use of the ITObject interface is to allow clients to track iTunes + * database changes using + * iTunesEventsInterface.onDatabaseChangedEvent(). + * + * You can retrieve an ITObject with a specified runtime ID using + * iTunes.getITObjectByID(). + * + * An ITObject will always have a valid, non-zero source ID. + * + * An ITObject corresponding to a playlist or track will always have a valid + * playlist ID. The playlist ID will be zero for a source. + * + * An ITObject corresponding to a track will always have a valid track and + * track database ID. These IDs will be zero for a source or playlist. + * + * A track ID is unique within the track's playlist. A track database ID is + * unique across all playlists. For example, if the same music file is in two + * different playlists, each of the tracks could have different track IDs, but + * they will have the same track database ID. + * + * An ITObject also has a 64-bit persistent ID which can be used to identify + * the ITObject across multiple invocations of iTunes. + * + * @author Steve Eyre + * @version 0.2 + */ +public class ITObject { + + protected Dispatch object; + + public ITObject(Dispatch d) { + object = d; + } + + /** + * Returns the JACOB Dispatch object for this object. + * @return Returns the JACOB Dispatch object for this object. + */ + public Dispatch fetchDispatch() { + return object; + } + + /** + * Set the name of the object. + * @param name The new name of the object. + */ + public void setName (String name) { + Dispatch.put(object, "Name", name); + } + + /** + * Returns the name of the object. + * @return Returns the name of the object. + */ + public String getName() { + return Dispatch.get(object, "Name").getString(); + } + + /** + * Returns the index of the object in internal application order. + * @return The index of the object in internal application order. + */ + public int getIndex() { + return Dispatch.get(object, "Index").getInt(); + } + + /** + * Returns the ID that identifies the source. + * @return Returns the ID that identifies the source. + */ + public int getSourceID() { + return Dispatch.get(object, "SourceID").getInt(); + } + + /** + * Returns the ID that identifies the playlist. + * @return Returns the ID that identifies the playlist. + */ + public int getPlaylistID() { + return Dispatch.get(object, "PlaylistID").getInt(); + } + + /** + * Returns the ID that identifies the track within the playlist. + * @return Returns the ID that identifies the track within the playlist. + */ + public int getTrackID() { + return Dispatch.get(object, "TrackID").getInt(); + } + + /** + * Returns the ID that identifies the track, independent of its playlist. + * @return Returns the ID that identifies the track, independent of its playlist. + */ + public int getTrackDatabaseID() { + return Dispatch.get(object, "TrackDatabaseID").getInt(); + } + +} diff --git a/java/itunescontroller/src/main/java/com/dt/iTunesController/ITObjectPersistentID.java b/java/itunescontroller/src/main/java/com/dt/iTunesController/ITObjectPersistentID.java new file mode 100644 index 0000000..e5c674b --- /dev/null +++ b/java/itunescontroller/src/main/java/com/dt/iTunesController/ITObjectPersistentID.java @@ -0,0 +1,53 @@ +package com.dt.iTunesController; + +/** + * Simple utility wrapper class to represent the persistent object identity + * ID numbers. Use the getHigh() and getLow() methods individually to get + * each ID, or the combined hex string through toString(). + * + * @author Steve Eyre + * @version 0.2 + */ +public class ITObjectPersistentID { + + private long High; + private long Low; + private String hexString; + + /** + * Create the ITObjectPersistentID. This class is not intended to be created + * manually, and this function should only be used by classes implementing + * this utility. + * @param high The High Persistent ID + * @param low The Low Persistent ID + */ + public ITObjectPersistentID(long high, long low) { + this.High=high; + this.Low=low; + this.hexString = String.format("%8s%8s",Long.toHexString(this.High),Long.toHexString(this.Low)).toUpperCase().replace(' ','0'); + } + + /** + * Returns the high persistent ID. + * @return The high persistent ID. + */ + public long getHigh() { + return this.High; + } + + /** + * Returns the low persistent ID. + * @return The low persistent ID. + */ + public long getLow() { + return this.Low; + } + + /** + * Return a string representation (in hex) of the persistent IDs. + * @return String representation of the persistent IDs. + */ + public String toString() { + return this.hexString; + } +} diff --git a/java/itunescontroller/src/main/java/com/dt/iTunesController/ITOperationStatus.java b/java/itunescontroller/src/main/java/com/dt/iTunesController/ITOperationStatus.java new file mode 100644 index 0000000..cf764aa --- /dev/null +++ b/java/itunescontroller/src/main/java/com/dt/iTunesController/ITOperationStatus.java @@ -0,0 +1,62 @@ +package com.dt.iTunesController; +import com.jacob.com.Dispatch; + +/** + * Represents the status of an asynchronous add or convert operation. + * + * When a track is added using TLibraryPlaylist.addFile(), + * ITLibraryPlaylist.AddFiles(), IITUserPlaylist.addFile(), or + * ITUserPlaylist.addFiles(), the add may not complete immediately if iTunes + * needs to make a copy of the file. + * + * Similarly, when converting or importing a file or track using + * iTunes.convertFile(), iTunes.convertFiles(), + * iTunes.convertTrack() or iTunes.convertTracks(), + * the conversion will never complete immediately. + * + * These methods return an ITOperationStatus object, which can be + * polled todetermine when the operation is done. This object will also return + * the collection of newly added or converted tracks. + * + * As of version 1.1 of the iTunes type library, you should use + * iTunes.convertFile2(), iTunes.convertFiles2(), + * iTunes.convertTrack2() or iTunes.convertTracks2() + * instead of the original convert methods. These new methods return an + * ITConvertOperationStatus object to allow clients to retrieve + * additional conversion progress information. + * + * @author Steve Eyre + * @version 0.2 + */ +public class ITOperationStatus { + + protected Dispatch object; + + public ITOperationStatus(Dispatch d) { + object = d; + } + + /** + * Returns true if the operation is still in progress. + * You cannot retrieve the ITOperationStatus.getTracks() + * property until the operation completes. + * @return Returns true if the operation is still in progress. + */ + public boolean getInProgress() { + return Dispatch.get(object, "InProgress").getBoolean(); + } + + /** + * Returns a collection containing the tracks that were generated by the + * operation. + * You cannot retrieve this property until + * ITOperationStatus.getInProgress() returns false + * @return Returns a collection containing the tracks that were generated by + * the operation. + */ + public ITTrackCollection getTracks() { + Dispatch tracks = Dispatch.get(object, "Tracks").toDispatch(); + return new ITTrackCollection(tracks); + } + +} diff --git a/java/itunescontroller/src/main/java/com/dt/iTunesController/ITPlayerState.java b/java/itunescontroller/src/main/java/com/dt/iTunesController/ITPlayerState.java new file mode 100644 index 0000000..4be2a70 --- /dev/null +++ b/java/itunescontroller/src/main/java/com/dt/iTunesController/ITPlayerState.java @@ -0,0 +1,13 @@ +package com.dt.iTunesController; + +/** + * Specifies the state of the player. + * @author Steve Eyre + * @version 0.2 + */ +public enum ITPlayerState { + ITPlayerStateStopped, + ITPlayerStatePlaying, + ITPlayerStateFastForward, + ITPlayerStateRewind; +} diff --git a/java/itunescontroller/src/main/java/com/dt/iTunesController/ITPlaylist.java b/java/itunescontroller/src/main/java/com/dt/iTunesController/ITPlaylist.java new file mode 100644 index 0000000..6c937cf --- /dev/null +++ b/java/itunescontroller/src/main/java/com/dt/iTunesController/ITPlaylist.java @@ -0,0 +1,180 @@ +package com.dt.iTunesController; +import com.jacob.com.Dispatch; + +/** + * Represents a playlist. + * + * A playlist is always associated with an ITSource. + * + * You can retrieve all the playlists defined for a source using + * ITSource.getPlaylists(). + * + * For convenience, you can retrieve the main library playlist using + * iTunes.getLibraryPlaylist(). + * + * You can create a new playlist using iTunes.createPlaylist(). + * + * @author Steve Eyre + * @version 0.2 + */ +public class ITPlaylist extends ITObject { + + public ITPlaylist (Dispatch d) { + super(d); + } + + /** + * Delete this object. + */ + public void delete() { + Dispatch.call(object, "Delete"); + } + + /** + * Start playing the first track in this object. + */ + public void playFirstTrack() { + Dispatch.call(object, "PlayFirstTrack"); + } + + /** + * Print this object. + * @param showPrintDialog If true, display the print dialog. + * @param printKind The printout kind. + * @param theme The name of the theme to use. This corresponds to the name + * of a Theme combo box item in the print dialog for the specified printKind + * (e.g. "Track length"). This string cannot be longer than 255 characters, + * but it may be empty. + */ + public void print(boolean showPrintDialog, ITPlaylistPrintKind printKind, String theme) { + Dispatch.call(object, "Print", showPrintDialog, printKind.ordinal(), theme); + } + + /** + * Returns a collection containing the tracks with the specified text. + * @param searchText The text to search for. This string cannot be longer + * than 255 chracters. + * @param searchFields Specifies which fields of each track should be + * searched for searchText. + * @return Collection of IITTrack objects. This will be NULL if no tracks + * meet the search criteria. + */ + public ITTrackCollection search (String searchText, ITPlaylistSearchField searchFields) { + Dispatch collection = Dispatch.call(object, "Search", searchText, searchFields.ordinal()).getDispatch(); + return new ITTrackCollection(collection); + } + + /** + * Returns the kind of the object. + * @return Returns the kind of the object. + */ + public ITPlaylistKind getKind() { + return ITPlaylistKind.values()[Dispatch.get(object, "Kind").getInt()]; + } + + /** + * Returns an ITSource object corresponding to the source that contains the + * object. + * @return Returns an ITSource object corresponding to the source that + * contains the object. + */ + public ITSource getSource() { + Dispatch source = Dispatch.get(object, "Source").toDispatch(); + return new ITSource(source); + } + + /** + * Returns the total length of all songs in the object (in seconds). + * @return Returns the total length of all songs in the object (in + * seconds). + */ + public int getDuration() { + return Dispatch.get(object, "Duration").getInt(); + } + + /** + * Set whether songs in the object should be played in random order. + * @param shouldShuffle True if songs in the object should be played in + * random order. + */ + public void setShuffle(boolean shouldShuffle) { + Dispatch.put(object, "Shuffle", shouldShuffle); + } + + /** + * Returns the total size of all songs in the object (in bytes). + * @return Returns the total size of all songs in the object (in bytes). + */ + public double getSize() { + return Dispatch.get(object, "Size").getDouble(); + } + + /** + * Sets the playback repeat mode. + * @param repeatMode The new playback repeat mode. + */ + public void setSongRepeat(ITPlaylistRepeatMode repeatMode) { + Dispatch.put(object, "SongRepeat", repeatMode.ordinal()); + } + + /** + * Cycle repeat modes. + */ + public void cycleSongRepeat() { + int repeat = Dispatch.get(object, "SongRepeat").getInt(); + Dispatch.put(object, "SongRepeat", (repeat + 1) % 3); + } + + /** + * Returns the playback repeat mode. + * @return Returns the playback repeat mode. + */ + public ITPlaylistRepeatMode getSongRepeat() { + return ITPlaylistRepeatMode.values()[Dispatch.get(object, "SongRepeat").getInt()]; + } + + /** + * Returns the total length of all songs in the object (in MM:SS format). + * @return Returns the total length of all songs in the object (in + * MM:SS format). + */ + public String getTime() { + return Dispatch.get(object, "Time").getString(); + } + + /** + * Returns true if the object is visible in the sources list. + * @return True if the object is visible in the sources list. + */ + public boolean getVisible() { + return Dispatch.get(object, "Visible").getBoolean(); + } + + /** + * Returns a collection containing the tracks in this object. + * @return Collection of ITTrack objects. + */ + public ITTrackCollection getTracks() { + Dispatch tracks = Dispatch.get(object, "Tracks").toDispatch(); + return new ITTrackCollection(tracks); + } + + /** + * Returns the shuffle state. + * @return true if current state is shuffle. + */ + public boolean getShuffle() { + return Dispatch.get(object, "Shuffle").getBoolean(); + } + + /** + * Toggle the shuffle state. + */ + public void toggleShuffle() { + setShuffle(!getShuffle()); + } + + public boolean containsTrack(ITTrack track) { + return getTracks().containsTrack(track); + } +} diff --git a/java/itunescontroller/src/main/java/com/dt/iTunesController/ITPlaylistCollection.java b/java/itunescontroller/src/main/java/com/dt/iTunesController/ITPlaylistCollection.java new file mode 100644 index 0000000..3717735 --- /dev/null +++ b/java/itunescontroller/src/main/java/com/dt/iTunesController/ITPlaylistCollection.java @@ -0,0 +1,67 @@ +package com.dt.iTunesController; +import com.jacob.com.Dispatch; + +/** + * Represents a collection of playlist objects. + * + * Note that collection indices are always 1-based. + * + * You can retrieve all the playlists defined for a source using + * ITSource.getPlaylists(). + * + * @author Steve Eyre + * @version 0.2 + */ +public class ITPlaylistCollection { + + protected Dispatch object; + + public ITPlaylistCollection(Dispatch d) { + object = d; + } + + /** + * Returns the number of playlists in the collection. + * @return Returns the number of playlists in the collection. + */ + public int getCount() { + return Dispatch.get(object, "Count").getInt(); + } + + /** + * Returns an ITPlaylist object corresponding to the given index (1-based). + * @param index Index of the playlist to retrieve, must be less than or + * equal to ITPlaylistCollection.getCount(). + * @return Returns an ITPlaylist object corresponding to the given index. + * Will be set to NULL if no playlist could be retrieved. + */ + public ITPlaylist getItem (int index) { + Dispatch item = Dispatch.call(object, "Item", index).toDispatch(); + return new ITPlaylist(item); + } + + /** + * Returns an ITPlaylist object withthe specified name. + * @param name The name of the playlist to retrieve. + * @return Returns an ITPlaylist object corresponding to the given index. + * Will be set to NULL if no playlist could be retrieved. + */ + public ITPlaylist ItemByName (String name) { + Dispatch item = Dispatch.call(object, "ItemByName", name).toDispatch(); + return new ITPlaylist(item); + } + + /** + * Returns an ITPlaylist object with the specified persistent ID. See the + * documentation on ITObject for more information on persistent IDs. + * @param highID The high 32 bits of the 64-bit persistent ID. + * @param lowID The low 32 bits of the 64-bit persistent ID. + * @return Returns an ITPlaylist object with the specified persistent ID. + * Will be set to NULL if no playlist could be retrieved. + */ + public ITPlaylist getItemByPersistentID (int highID, int lowID) { + Dispatch item = Dispatch.call(object, "ItemByPersistentID", highID, lowID).toDispatch(); + return new ITPlaylist(item); + } + +} diff --git a/java/itunescontroller/src/main/java/com/dt/iTunesController/ITPlaylistKind.java b/java/itunescontroller/src/main/java/com/dt/iTunesController/ITPlaylistKind.java new file mode 100644 index 0000000..e6f685f --- /dev/null +++ b/java/itunescontroller/src/main/java/com/dt/iTunesController/ITPlaylistKind.java @@ -0,0 +1,15 @@ +package com.dt.iTunesController; + +/** + * Specifies the playlist kind. + * @author Steve Eyre + * @version 0.2 + */ +public enum ITPlaylistKind { + ITPlaylistKindUnknown, + ITPlaylistKindLibrary, + ITPlaylistKindUser, + ITPlaylistKindCD, + ITPlaylistKindDevice, + ITPlaylistKindRadioTuner; +} diff --git a/java/itunescontroller/src/main/java/com/dt/iTunesController/ITPlaylistPrintKind.java b/java/itunescontroller/src/main/java/com/dt/iTunesController/ITPlaylistPrintKind.java new file mode 100644 index 0000000..6fc8ef8 --- /dev/null +++ b/java/itunescontroller/src/main/java/com/dt/iTunesController/ITPlaylistPrintKind.java @@ -0,0 +1,14 @@ +package com.dt.iTunesController; + +/** + * Specifies the kind of playlist printout. + * @author Steve Eyre + * @version 0.2 + */ +public enum ITPlaylistPrintKind { + + ITPlaylistPrintKindPlaylist, + ITPlaylistPrintKindAlbumlist, + ITPlaylistPrintKindInsert; + +} diff --git a/java/itunescontroller/src/main/java/com/dt/iTunesController/ITPlaylistRepeatMode.java b/java/itunescontroller/src/main/java/com/dt/iTunesController/ITPlaylistRepeatMode.java new file mode 100644 index 0000000..4b6fc16 --- /dev/null +++ b/java/itunescontroller/src/main/java/com/dt/iTunesController/ITPlaylistRepeatMode.java @@ -0,0 +1,14 @@ +package com.dt.iTunesController; + +/** + * Specifies the playlist playback repeat mode. + * @author Steve Eyre + * @version 0.2 + */ +public enum ITPlaylistRepeatMode { + + ITPlaylistRepeatModeOff, + ITPlaylistRepeatModeOne, + ITPlaylistRepeatModeAll; + +} diff --git a/java/itunescontroller/src/main/java/com/dt/iTunesController/ITPlaylistSearchField.java b/java/itunescontroller/src/main/java/com/dt/iTunesController/ITPlaylistSearchField.java new file mode 100644 index 0000000..420b305 --- /dev/null +++ b/java/itunescontroller/src/main/java/com/dt/iTunesController/ITPlaylistSearchField.java @@ -0,0 +1,16 @@ +package com.dt.iTunesController; + +/** + * Specifies the fields in each track that will be searched by + * ITPlaylist.search(). + * @author Steve Eyre + * @version 0.2 + */ +public enum ITPlaylistSearchField { + ITPlaylistSearchFieldAll, + ITPlaylistSearchFieldVisible, + ITPlaylistSearchFieldArtists, + ITPlaylistSearchFieldAlbums, + ITPlaylistSearchFieldComposers, + ITPlaylistSearchFieldSongNames; +} diff --git a/java/itunescontroller/src/main/java/com/dt/iTunesController/ITRatingKind.java b/java/itunescontroller/src/main/java/com/dt/iTunesController/ITRatingKind.java new file mode 100644 index 0000000..7d1cb22 --- /dev/null +++ b/java/itunescontroller/src/main/java/com/dt/iTunesController/ITRatingKind.java @@ -0,0 +1,11 @@ +package com.dt.iTunesController; + +/** + * Specifies the rating kind. + * @author Steve Eyre + * @version 0.2 + */ +public enum ITRatingKind { + ITRatingKindUser, + ITRatingKindComputed; +} diff --git a/java/itunescontroller/src/main/java/com/dt/iTunesController/ITSource.java b/java/itunescontroller/src/main/java/com/dt/iTunesController/ITSource.java new file mode 100644 index 0000000..b0d93fc --- /dev/null +++ b/java/itunescontroller/src/main/java/com/dt/iTunesController/ITSource.java @@ -0,0 +1,51 @@ +package com.dt.iTunesController; +import com.jacob.com.Dispatch; + +/** + * Represents an entry in the Source list (music library, CD, device, etc.). + * You can retrieve all the sources using iTunes.getSources(). + * @author Steve Eyre + * @version 0.2 + */ +public class ITSource extends ITObject { + + public ITSource(Dispatch d) { + super(d); + } + + /** + * Returns the kind of the source. + * @return Returns the kind of the source. + */ + public ITSourceKind getKind() { + return ITSourceKind.values()[Dispatch.get(object, "Kind").getInt()]; + } + + /** + * Returns the total size of the source, if it has a fixed size. + * @return Returns the total size of the source, if it has a fixed size. + */ + public double getCapacity() { + return Dispatch.get(object, "Capacity").getDouble(); + } + + /** + * Returns the free space on the source, if it has a fixed size. + * @return Returns the free space on the source, if it has a fixed size. + */ + public double getFreespace() { + return Dispatch.get(object, "Freespace").getDouble(); + } + + /** + * Returns a collection containing the playlists in this source. + * The source's primary playlist is always the first playlist in the + * collection. + * @return Collection of IITPlaylist objects. + */ + public ITPlaylistCollection getPlaylists() { + Dispatch playlists = Dispatch.get(object, "Playlists").toDispatch(); + return new ITPlaylistCollection(playlists); + } + +} diff --git a/java/itunescontroller/src/main/java/com/dt/iTunesController/ITSourceCollection.java b/java/itunescontroller/src/main/java/com/dt/iTunesController/ITSourceCollection.java new file mode 100644 index 0000000..357bdec --- /dev/null +++ b/java/itunescontroller/src/main/java/com/dt/iTunesController/ITSourceCollection.java @@ -0,0 +1,66 @@ +package com.dt.iTunesController; +import com.jacob.com.Dispatch; + +/** + * Represents a collection of source objects. + * + * Note that collection indices are always 1-based. + * + * You can retrieve all the sources using ITSource.getSources(). + * + * @author Steve Eyre + * @version 0.2 + */ +public class ITSourceCollection { + + protected Dispatch object; + + public ITSourceCollection(Dispatch d) { + object = d; + } + + /** + * Returns the number of sources in the collection. + * @return Returns the number of sources in the collection. + */ + public int getCount() { + return Dispatch.get(object, "Count").getInt(); + } + + /** + * Returns an ITSource object corresponding to the given index (1-based). + * @param index Index of the source to retrieve, must be less than or + * equal to ITSourceCollection.getCount(). + * @return Returns an ITSource object corresponding to the given index. + * Will be set to NULL if no source could be retrieved. + */ + public ITSource getItem (int index) { + Dispatch item = Dispatch.call(object, "Item", index).toDispatch(); + return new ITSource(item); + } + + /** + * Returns an ITSource object withthe specified name. + * @param name The name of the source to retrieve. + * @return Returns an ITSource object corresponding to the given index. + * Will be set to NULL if no source could be retrieved. + */ + public ITSource getItemByName (String name) { + Dispatch item = Dispatch.call(object, "ItemByName", name).toDispatch(); + return new ITSource(item); + } + + /** + * Returns an ITSource object with the specified persistent ID. See the + * documentation on ITObject for more information on persistent IDs. + * @param highID The high 32 bits of the 64-bit persistent ID. + * @param lowID The low 32 bits of the 64-bit persistent ID. + * @return Returns an ITSource object with the specified persistent ID. + * Will be set to NULL if no source could be retrieved. + */ + public ITSource getItemByPersistentID (int highID, int lowID) { + Dispatch item = Dispatch.call(object, "ItemByPersistentID", highID, lowID).toDispatch(); + return new ITSource(item); + } + +} \ No newline at end of file diff --git a/java/itunescontroller/src/main/java/com/dt/iTunesController/ITSourceKind.java b/java/itunescontroller/src/main/java/com/dt/iTunesController/ITSourceKind.java new file mode 100644 index 0000000..f332249 --- /dev/null +++ b/java/itunescontroller/src/main/java/com/dt/iTunesController/ITSourceKind.java @@ -0,0 +1,17 @@ +package com.dt.iTunesController; + +/** + * Specifies the source kind. + * @author Steve Eyre + * @version 0.2 + */ +public enum ITSourceKind { + ITSourceKindUnknown, + ITSourceKindLibrary, + ITSourceKindIPod, + ITSourceKindAudioCD, + ITSourceKindMP3CD, + ITSourceKindDevice, + ITSourceKindRadioTuner, + ITSourceKindSharedLibrary; +} diff --git a/java/itunescontroller/src/main/java/com/dt/iTunesController/ITTrack.java b/java/itunescontroller/src/main/java/com/dt/iTunesController/ITTrack.java new file mode 100644 index 0000000..57bb11b --- /dev/null +++ b/java/itunescontroller/src/main/java/com/dt/iTunesController/ITTrack.java @@ -0,0 +1,493 @@ +package com.dt.iTunesController; +import java.util.Date; + +import com.jacob.com.Dispatch; + +/** + * Represents a track. + * + * A track represents a song in a single playlist. A song may be in more than + * one playlist, in which case it would be represented by multiple tracks. + * + * You can retrieve the currently targeted (playing) track using + * iTunes.getCurrentTrack(). + * + * Typically, an ITrack is accessed through an ITTrackCollection. + * + * You can retrieve all the tracks defined for a playlist using + * ITPlaylist.getTracks(). + * + * You can retrieve the currently selected track or tracks using + * iTunes.getSelectedTracks(). + * + * @author Steve Eyre + * @version 0.2 + */ +public class ITTrack extends ITObject { + + public ITTrack (Dispatch d) { + super(d); + } + + /** + * Delete this object. + */ + public void delete() { + Dispatch.call(object, "Delete"); + } + + /** + * Start playing this object. + */ + public void play() { + Dispatch.call(object, "Play"); + } + + /** + * Set the name of the album containing the object.; + * @param album The new name of the album containing the object. + */ + public void setAlbum(String album) { + Dispatch.put(object, "Album", album); + } + + /** + * Returns the name of the album containing the object. + * @return Returns the name of the album containing the object. + */ + public String getAlbum() { + return Dispatch.get(object, "Album").getString(); + } + + /** + * Set the name of the artist/source of the object. + * @param artist The new artist/source of the object. + */ + public void setArtist(String artist) { + Dispatch.put(object, "Artist", artist); + } + + /** + * Returns the name of the artist/source of the object. + * @return Returns the name of the artist/source of the object. + */ + public String getArtist() { + return Dispatch.get(object, "Artist").getString(); + } + + /** + * Returns the bit rate of the object (in kbps). + * @return Returns the bit rate of the object (in kbps). + */ + public int getBitRate() { + return Dispatch.get(object, "BitRate").getInt(); + } + + /** + * Set the tempo of the object (in beats per minute). + * @param beatsPerMinute The new tempo of the object (in beats per minute). + */ + public void setBPM(int beatsPerMinute) { + Dispatch.put(object, "BPM", beatsPerMinute); + } + + /** + * Returns the tempo of the object (in beats per minute). + * @return Returns the tempo of the object (in beats per minute). + */ + public int getBPM() { + return Dispatch.get(object, "BPM").getInt(); + } + + /** + * Set freeform notes about the object. + * @param comment The new freeform notes about the object. + */ + public void setComment(String comment) { + Dispatch.put(object, "Comment", comment); + } + + /** + * Returns freeform notes about the object. + * @return Returns freeform notes about the object. + */ + public String getComment() { + return Dispatch.get(object, "Comment").getString(); + } + + /** + * Set whether this object is from a compilation album. + * @param isCompilation True if this object should be from a compilation album. + */ + public void setCompilation(boolean isCompilation) { + Dispatch.put(object, "Compilation", isCompilation); + } + + /** + * Returns true if this object is from a compilation album. + * @return Returns true if this object is from a compilation album. + */ + public boolean getCompilation() { + return Dispatch.get(object, "Compilation").getBoolean(); + } + + /** + * Set the composer of the object. + * @param composer The new composer of the object. + */ + public void setComposer (String composer) { + Dispatch.put(object, "Composer", composer); + } + + /** + * Returns the composer of the object. + * @return Returns the composer of the object. + */ + public String getComposer() { + return Dispatch.get(object, "Composer").getString(); + } + + /** + * Returns the date the object was added to the playlist. + * @return Returns the date the object was added to the playlist. + */ + public Date getDateAdded() { + return Dispatch.get(object, "DateAdded").getJavaDate(); + } + + /** + * Set the total number of discs in the source album. + * @param discCount The new total number of discs in the source album. + */ + public void setDiscCount (int discCount) { + Dispatch.put(object, "DiscCount", discCount); + } + + /** + * Returns the total number of discs in the source album. + * @return Returns the total number of discs in the source album. + */ + public int getDiscCount() { + return Dispatch.get(object, "DiscCount").getInt(); + } + + /** + * Set the index of the disc containing the object on the source album. + * @param discNumber The new index of the disc containing the object on the + * source album. + */ + public void setDiscNumber (int discNumber) { + Dispatch.put(object, "DiscNumber", discNumber); + } + + /** + * Returns the index of the disc containing the object on the source album. + * @return Returns the index of the disc containing the object on the source + * album. + */ + public int getDiscNumber() { + return Dispatch.get(object, "DiscNumber").getInt(); + } + + /** + * Returns the length of the object (in seconds). + * @return Returns the length of the object (in seconds). + */ + public int getDuration() { + return Dispatch.get(object, "Duration").getInt(); + } + + /** + * Set whether this object is checked for playback. + * @param shouldBeEnabled True if the object should be checked for playback. + */ + public void setEnabled (boolean shouldBeEnabled) { + Dispatch.put(object, "Enabled", shouldBeEnabled); + } + + /** + * Returns true if the object is checked for playback. + * @return Returns true if the object is checked for playback. + */ + public boolean getEnabled() { + return Dispatch.get(object, "Enabled").getBoolean(); + } + + /** + * Set the name of the EQ preset of the object. + * @param eq The new name of the EQ preset of the object. + */ + public void setEQ (String eq) { + Dispatch.put(object, "EQ", eq); + } + + /** + * Returns the name of the EQ preset of the object. + * @return Returns the name of the EQ preset of the object. + */ + public String getEQ() { + return Dispatch.get(object, "EQ").getString(); + } + + /** + * Set the stop time of the object (in seconds). + * @param finish The new stop time of the object (in seconds). + */ + public void setFinish(int finish) { + Dispatch.put(object, "Finish", finish); + } + + /** + * Returns the stop time of the object (in seconds). + * @return Returns the stop time of the object (in seconds). + */ + public int getFinish() { + return Dispatch.get(object, "Finish").getInt(); + } + + /** + * Returns the music/audio genre (category) of the object. + * @param genre Returns the music/audio genre (category) of the object. + */ + public void setGenre(String genre) { + Dispatch.put(object, "Genre", genre); + } + + /** + * Set the music/audio genre (category) of the object. + * @return The new music/audio genre (category) of the object. + */ + public String getGenre() { + return Dispatch.get(object, "Genre").getString(); + } + + /** + * Set the grouping (piece) of the object. + * Generally used to denote movements within classical work. + * @param grouping The new grouping (piece) of the object. + */ + public void setGrouping (String grouping) { + Dispatch.put(object, "Grouping", grouping); + } + + /** + * Returns the grouping (piece) of the object. + * Generally used to denote movements within classical work. + * @return Returns the grouping (piece) of the object. + */ + public String getGrouping() { + return Dispatch.get(object, "Grouping").getString(); + } + + public ITTrackKind getKind() { + return ITTrackKind.values()[Dispatch.get(object, "Kind").getInt()]; + } + + /** + * Returns the text description of the object (e.g. "AAC audio file"). + * @return Returns the text description of the object (e.g. "AAC audio file"). + */ + public String getKindAsString() { + return Dispatch.get(object, "KindAsString").getString(); + } + + /** + * Returns the modification date of the content of the object. + * @return Returns the modification date of the content of the object. + */ + public Date getModificationDate() { + return Dispatch.get(object, "ModificationDate").getJavaDate(); + } + + /** + * Set the number of times the object has been played. This property cannot + * be set if the object is not playable (e.g. a PDF file). + * @param playedCount The new number of times the object has been played. + */ + public void setPlayedCount (int playedCount) { + Dispatch.put(object, "PlayedCount", playedCount); + } + + /** + * Returns the number of times the object has been played. + * @return Returns the number of times the object has been played. + */ + public int getPlayedCount() { + return Dispatch.get(object, "PlayedCount").getInt(); + } + + /** + * Set the date and time the object was last played. This property cannot be + * set if the object is not playable (e.g. a PDF file). + * A value of zero means no played date. + * @param playedDate The new date and time the object was last played. + */ + public void setPlayedDate (Date playedDate) { + Dispatch.put(object, "PlayedDate", playedDate); + } + + /** + * Returns the date and time the object was last played. + * A value of zero means no played date. + * @return Returns the date and time the object was last played. + */ + public Date getPlayedDate() { + return Dispatch.get(object, "PlayedDate").getJavaDate(); + } + + /** + * Returns an ITPlaylist object corresponding to the playlist that contains + * the object. Use ITFileOrCDTrack::Playlists() or IITURLTrack::Playlists() + * to get the collection of all playlists that contain the song this object + * represents. + * @return Returns an ITPlaylist object corresponding to the playlist that + * contains the object. + */ + public ITPlaylist getPlaylist() { + Dispatch playlist = Dispatch.get(object, "Playlist").toDispatch(); + return new ITPlaylist(playlist); + } + + /** + * Returns the play order index of the object in the owner playlist + * (1-based). + * You can pass this index to IITTrackCollection::ItemByPlayOrder() for the + * collection returned by ITPlaylist::Tracks() to retrieve an ITTrack + * object corresponding to this object. + * @return Returns the play order index of the object in the owner playlist. + */ + public int getPlayOrderIndex() { + return Dispatch.get(object, "PlayOrderIndex").getInt(); + } + + /** + * Set the rating of the object (0 to 100). If the object rating is set to 0, + * it will be computed based on the album rating. + * @param rating The new rating of the object (0 to 100). + */ + public void setRating (int rating) { + Dispatch.put(object, "Rating", rating); + } + + /** + * Returns the rating of the object (0 to 100). If the object rating has never + * been set, or has been set to 0, it will be computed based on the album + * rating. + * @return Returns the rating of the object (0 to 100). + */ + public int getRating() { + return Dispatch.get(object, "Rating").getInt(); + } + + /** + * Returns the sample rate of the object (in Hz). + * @return Returns the sample rate of the object (in Hz). + */ + public int getSampleRate() { + return Dispatch.get(object, "SampleRate").getInt(); + } + + /** + * Returns the size of the object (in bytes). + * @return Returns the size of the object (in bytes). + */ + public int getSize() { + return Dispatch.get(object, "Size").getInt(); + } + + /** + * Set the start time of the object (in seconds). + * @param start The new start time of the object (in seconds). + */ + public void setStart (int start) { + Dispatch.put(object, "Start", start); + } + + /** + * Returns the start time of the object (in seconds). + * @return Returns the start time of the object (in seconds). + */ + public int getStart() { + return Dispatch.get(object, "Start").getInt(); + } + + /** + * Returns the length of the object (in MM:SS format). + * @return Returns the length of the object (in MM:SS format). + */ + public String getTime() { + return Dispatch.get(object, "Time").getString(); + } + + /** + * Set the total number of tracks on the source album. + * @param trackCount The new total number of tracks on the source album. + */ + public void setTrackCount (int trackCount) { + Dispatch.put(object, "TrackCount", trackCount); + } + + /** + * Returns the total number of tracks on the source album. + * @return Returns the total number of tracks on the source album. + */ + public int getTrackCount() { + return Dispatch.get(object, "TrackCount").getInt(); + } + + /** + * Set the index of the object on the source album. + * @param trackNumber The new index of the object on the source album. + */ + public void setTrackNumber (int trackNumber) { + Dispatch.put(object, "TrackNumber", trackNumber); + } + + /** + * Returns the index of the object on the source album. + * @return Returns the index of the object on the source album. + */ + public int getTrackNumber() { + return Dispatch.get(object, "TrackNumebr").getInt(); + } + + /** + * Set the relative volume adjustment of the object (-100% to 100%). + * @param volumeAdjustment Set the relative volume adjustment of the object + * (-100% to 100%). + */ + public void setVolumeAdjustment (int volumeAdjustment) { + Dispatch.put(object, "VolumeAdjustment", volumeAdjustment); + } + + /** + * Returns the relative volume adjustment of the object (-100% to 100%). + * @return Returns the relative volume adjustment of the object (-100% to 100%). + */ + public int getVolumeAdjustment() { + return Dispatch.get(object, "VolumeAdjustment").getInt(); + } + + /** + * Set the year the object was recorded/released. + * @param year The new year the object was recorded/released. + */ + public void setYear (int year) { + Dispatch.put(object, "Year", year); + } + + /** + * Returns the year the object was recorded/released. + * @return Returns the year the object was recorded/released. + */ + public int getYear() { + return Dispatch.get(object, "Year").getInt(); + } + + public ITArtworkCollection getArtwork() { + Dispatch art = Dispatch.get(object, "Artwork").toDispatch(); + return new ITArtworkCollection(art); + + } + +} diff --git a/java/itunescontroller/src/main/java/com/dt/iTunesController/ITTrackCollection.java b/java/itunescontroller/src/main/java/com/dt/iTunesController/ITTrackCollection.java new file mode 100644 index 0000000..3e1f3bf --- /dev/null +++ b/java/itunescontroller/src/main/java/com/dt/iTunesController/ITTrackCollection.java @@ -0,0 +1,99 @@ +package com.dt.iTunesController; +import com.jacob.com.Dispatch; + +/** + * Represents a collection of track objects. + * + * Note that collection indices are always 1-based. + * + * You can retrieve all the tracks defined for a playlist using + * ITPlaylist.getTracks(). + * + * You can retrieve the currently selected track or tracks using + * iTunes.getSelectedTracks(). + * + * @author Steve Eyre + * @version 0.2 + */ +public class ITTrackCollection { + + protected Dispatch object; + + public ITTrackCollection(Dispatch d) { + object = d; + } + + /** + * Returns the number of tracks in the collection. + * @return Returns the number of tracks in the collection. + */ + public int getCount() { + return Dispatch.get(object, "Count").getInt(); + } + + /** + * Returns an ITTrack object corresponding to the given index (1-based). + * @param index Index of the track to retrieve, must be less than or + * equal to ITTrackCollection.getCount(). + * @return Returns an ITTrack object corresponding to the given index. + * Will be set to NULL if no track could be retrieved. + */ + public ITTrack getItem (int index) { + Dispatch item = Dispatch.call(object, "Item", index).toDispatch(); + ITTrack track = new ITTrack(item); + if (track.getKind()==ITTrackKind.ITTrackKindFile) { + return new ITFileOrCDTrack(item); + } else if (track.getKind()==ITTrackKind.ITTrackKindCD) { + return new ITFileOrCDTrack(item); + } else if (track.getKind()==ITTrackKind.ITTrackKindURL ) { + return new ITURLTrack(item); + } else { + return track; + } + } + + /** + * Returns an ITTrack object corresponding to the given index (1-based). + * @param index Index of the track to retrieve, must be less than or + * equal to ITTrackCollection.getCount(). + * @return Returns an ITTrack object corresponding to the given index. + * Will be set to NULL if no track could be retrieved. + */ + public ITTrack getItemByPlayOrder(int index) { + Dispatch item = Dispatch.call(object, "ItemByPlayOrder", index).toDispatch(); + return new ITTrack(item); + } + + /** + * Returns an ITTrack object withthe specified name. + * @param name The name of the track to retrieve. + * @return Returns an ITTrack object corresponding to the given index. + * Will be set to NULL if no track could be retrieved. + */ + public ITTrack ItemByName (String name) { + Dispatch item = Dispatch.call(object, "ItemByName", name).toDispatch(); + return new ITTrack(item); + } + + /** + * Returns an ITTrack object with the specified persistent ID. See the + * documentation on ITObject for more information on persistent IDs. + * @param highID The high 32 bits of the 64-bit persistent ID. + * @param lowID The low 32 bits of the 64-bit persistent ID. + * @return Returns an ITTrack object with the specified persistent ID. + * Will be set to NULL if no track could be retrieved. + */ + public ITTrack getItemByPersistentID (int highID, int lowID) { + Dispatch item = Dispatch.call(object, "ItemByPersistentID", highID, lowID).toDispatch(); + return new ITTrack(item); + } + + public boolean containsTrack(ITTrack track) { + String name = track.getName(); + try { + return ItemByName(name).getName().equals(name); + } catch (IllegalStateException e) { + return false; + } + } +} diff --git a/java/itunescontroller/src/main/java/com/dt/iTunesController/ITTrackKind.java b/java/itunescontroller/src/main/java/com/dt/iTunesController/ITTrackKind.java new file mode 100644 index 0000000..ec233a1 --- /dev/null +++ b/java/itunescontroller/src/main/java/com/dt/iTunesController/ITTrackKind.java @@ -0,0 +1,15 @@ +package com.dt.iTunesController; + +/** + * Specifies the track kind. + * @author Steve Eyre + * @version 0.2 + */ +public enum ITTrackKind { + ITTrackKindUnknown, + ITTrackKindFile, + ITTrackKindCD, + ITTrackKindURL, + ITTrackKindDevice, + ITTrackKindSharedLibrary; +} diff --git a/java/itunescontroller/src/main/java/com/dt/iTunesController/ITURLTrack.java b/java/itunescontroller/src/main/java/com/dt/iTunesController/ITURLTrack.java new file mode 100644 index 0000000..9829190 --- /dev/null +++ b/java/itunescontroller/src/main/java/com/dt/iTunesController/ITURLTrack.java @@ -0,0 +1,175 @@ +package com.dt.iTunesController; +import com.jacob.com.Dispatch; + +/** + * Represents a URL track. + * + * A URL track references a network audio stream. + * @author Steve Eyre + * @version 0.2 + */ +public class ITURLTrack extends ITTrack { + + public ITURLTrack (Dispatch d) { + super(d); + } + + /** + * Returns the URL of the stream represented by this track. + * @return The URL of the stream represented by this track. + */ + public String getURL () { + return Dispatch.get(object, "URL").getString(); + } + + /** + * Set the URL of the stream represented by this track. + * @param url The URL of the stream represented by this track. + */ + public void setURL (String url) { + Dispatch.call(object, "URL", url); + } + + /** + * Returns true if this track is a podcast track. If a podcast track is an + * IITURLTrack, the podcast episode has not been downloaded. + * @return Returns true if this track is a podcast track. + */ + public boolean isPodcast () { + return Dispatch.get(object, "Podcast").getBoolean(); + } + + /** + * Returns the category for the track. + * @return Returns the category for the track. + */ + public String getCategory () { + return Dispatch.get(object, "Category").getString(); + } + + /** + * Sets the category for the track. + * @param category Sets the category for the track. + */ + public void setCategory (String category) { + Dispatch.call(object, "Category", category); + } + + /** + * Returns the description for the track. + * @return Returns the description for the track. + */ + public String getDescription () { + return Dispatch.get(object, "Description").getString(); + } + + /** + * Sets the description for the track. + * @param description The new description for the track. + */ + public void setDescription (String description) { + Dispatch.call(object, "Description", description); + } + + /** + * Returns the long description for the track. + * @return Returns the description for the track. + */ + public String getLongDescription () { + return Dispatch.get(object, "LongDescription").getString(); + } + + /** + * Sets the long description for the track. + * @param longDescription The new long description for the track. + */ + public void setLongDescription (String longDescription) { + Dispatch.call(object, "LongDescription", longDescription); + } + + /** + * Returns the user or computed rating of the album that this track belongs + * to (0 to 100). If the album rating has never been set, or has been set to + * 0, it will be computed based on the ratings of tracks in the album. + * @return Returns the album rating of the album that this track belongs to (0 to 100). + */ + public long getAlbumRating () { + return Dispatch.get(object, "AlbumRating").getLong(); + } + + /** + * Set the album rating of the album that this track belongs to (0 to 100). + * If the album rating is set to 0, it will be computed based on the ratings + * of tracks in the album. + * @param albumRating The new album rating of the album that this track + * belongs to (0 to 100). If rating is outside this range, it will be + * pinned. + */ + public void setAlbumRating (long albumRating) { + Dispatch.call(object, "AlbumRating", albumRating); + } + + /** + * Returns the album rating kind. If the album rating has never been set, or + * has been set to 0, the kind is ITRatingKindComputed. Otherwise, the kind + * is ITRatingKindUser. + * @return Returns the album rating kind. + */ + public ITRatingKind getAlbumRatingKind () { + return ITRatingKind.values()[Dispatch.get(object, "AlbumRatingKind").getInt()]; + } + + /** + * Returns the track rating kind. If the track rating has never been set, or + * has been set to 0, the kind is ITRatingKindComputed. Otherwise, the kind + * is ITRatingKindUser. + * @return Returns the track rating kind. + */ + public ITRatingKind getRatingKind () { + return ITRatingKind.values()[Dispatch.get(object, "RatingKind").getInt()]; + } + + /** + * Returns a collection of playlists that contain the song that this track + * represents. + * + * This is the same collection of playlists that are shown in the "Show in + * Playlist" contextual menu for a track, plus the specific playlist that + * contains this track. + * + * A track represents a song in a single playlist, use + * ITTrack.getPlaylist() to get the specific playlist that + * contains this track. + * @return Collection of ITPlaylist objects. + */ + public ITPlaylistCollection getPlaylists () { + Dispatch playlists = Dispatch.get(object, "Playlists").toDispatch(); + return new ITPlaylistCollection(playlists); + } + + /** + * Update the podcast feed for this track. This is equivalent to the user + * choosing Update Podcast from the contextual menu for the podcast feed + * that contains this track. + */ + public void updatePodcastFeed () { + Dispatch.call(object, "UpdatePodcastFeed"); + } + + /** + * Start downloading the podcast episode that corresponds to this track. + * This is equivalent to the user clicking the Get button next to this + * track. + */ + public void downloadPodcastEpisode () { + Dispatch.call(object, "DownloadPodcastEpisode"); + } + + /** + * Reveals the track in the main browser window. + */ + public void reveal() { + Dispatch.call(object, "Reveal"); + } + +} diff --git a/java/itunescontroller/src/main/java/com/dt/iTunesController/ITUserPlaylist.java b/java/itunescontroller/src/main/java/com/dt/iTunesController/ITUserPlaylist.java new file mode 100644 index 0000000..b4025cf --- /dev/null +++ b/java/itunescontroller/src/main/java/com/dt/iTunesController/ITUserPlaylist.java @@ -0,0 +1,60 @@ +package com.dt.iTunesController; +import com.jacob.com.Dispatch; + +/** + * Represents a user-defined playlist. + * + * A user playlist includes both smart and manual user-defined playlists. + * @author Steve Eyre + * @version 0.2 + */ +public class ITUserPlaylist extends ITPlaylist { + + public ITUserPlaylist(Dispatch d) { + super(d); + } + + /** + * Add a file or files inside a folder to the playlist. + * You cannot use this method to add a file that requires conversion to be + * added (e.g. a CD track), use iTunes.convertFile() or + * iTunes.convertFile2() instead. If you add a folder that + * contains files that require conversion, they will be skipped. + * @param filePath The full path to the file or folder to add. + * @return Returns an ITOperationStatus object corresponding to the + * asynchronous operation. If an error occurs, or no files were added, this + * will be set to NULL. + */ + public ITOperationStatus addFile (String filePath) { + Dispatch status = Dispatch.call(object, "AddFile", filePath).toDispatch(); + return new ITOperationStatus(status); + } + + /** + * Add a streaming audio URL to the playlist. + * @param url The URL to add. The length of the URL can be 255 characters or + * less. + * @return Returns an ITURLTrack object corresponding to the new track. + */ + public ITURLTrack addURL (String url) { + Dispatch URLTrack = Dispatch.call(object, "AddURL", url).toDispatch(); + return new ITURLTrack(URLTrack); + } + + /** + * Add an existing track to the playlist. + * You cannot use this method to add a CD track (ITTrackKindCD) to another + * playlist, use iTunes.convertTrack() or + * iTunes.convertTrack2() instead. + * You cannot add a shared library track (ITTrackKindSharedLibrary) to + * another playlist. + * @param track The track to add. + * @return Returns an IITTrack object corresponding to the new track. + */ + public ITTrack addTrack (ITTrack track) { + Dispatch trackToAdd = track.fetchDispatch(); + Dispatch addedTrack = Dispatch.call(object, "AddTrack", trackToAdd).toDispatch(); + return new ITTrack(addedTrack); + } + +} diff --git a/java/itunescontroller/src/main/java/com/dt/iTunesController/ITVideoKind.java b/java/itunescontroller/src/main/java/com/dt/iTunesController/ITVideoKind.java new file mode 100644 index 0000000..d318724 --- /dev/null +++ b/java/itunescontroller/src/main/java/com/dt/iTunesController/ITVideoKind.java @@ -0,0 +1,13 @@ +package com.dt.iTunesController; + +/** + * Specifies the Video kind. + * @author Steve Eyre + * @version 0.2 + */ +public enum ITVideoKind { + ITVideoKindNone, + ITVideoKindMovie, + ITVideoKindMusicVideo, + ITVideoKindTVShow; +} diff --git a/java/itunescontroller/src/main/java/com/dt/iTunesController/ITWindow.java b/java/itunescontroller/src/main/java/com/dt/iTunesController/ITWindow.java new file mode 100644 index 0000000..4af825f --- /dev/null +++ b/java/itunescontroller/src/main/java/com/dt/iTunesController/ITWindow.java @@ -0,0 +1,32 @@ +package com.dt.iTunesController; +import com.jacob.com.Dispatch; + +/** + * Represents an iTunes window. + */ + +public class ITWindow { + + protected Dispatch object; + + public ITWindow(Dispatch d) { + object = d; + } + + /** + * Returns the JACOB Dispatch object for this object. + * @return Returns the JACOB Dispatch object for this object. + */ + public Dispatch fetchDispatch() { + return object; + } + + /** + * Returns the name of the object. + * @return Returns the name of the object. + */ + public String getName() { + return Dispatch.get(object, "Name").getString(); + } + +} diff --git a/java/itunescontroller/src/main/java/com/dt/iTunesController/ITWindowCollection.java b/java/itunescontroller/src/main/java/com/dt/iTunesController/ITWindowCollection.java new file mode 100644 index 0000000..df1f3cf --- /dev/null +++ b/java/itunescontroller/src/main/java/com/dt/iTunesController/ITWindowCollection.java @@ -0,0 +1,55 @@ +package com.dt.iTunesController; +import com.jacob.com.Dispatch; + +/** + * Represents a collection of window objects. + * + * Note that collection indices are always 1-based. + * + * You can retrieve all the windows using + * iTunes.getWindows(). + * + * @author Steve Eyre + * @version 0.2 + */ +public class ITWindowCollection { + + protected Dispatch object; + + public ITWindowCollection(Dispatch d) { + object = d; + } + + // TODO: iTunes.getWindows() + + /** + * Returns the number of playlists in the collection. + * @return Returns the number of playlists in the collection. + */ + public int getCount() { + return Dispatch.get(object, "Count").getInt(); + } + + /** + * Returns an ITWindow object corresponding to the given index (1-based). + * @param index Index of the playlist to retrieve, must be less than or + * equal to ITWindowCollection.getCount(). + * @return Returns an ITWindow object corresponding to the given index. + * Will be set to NULL if no playlist could be retrieved. + */ + public ITWindow getItem (int index) { + Dispatch item = Dispatch.call(object, "Item", index).toDispatch(); + return new ITWindow(item); + } + /** + * Returns an ITWindow object with the specified name. + * @param name The name of the window to retrieve. + * @return Returns an ITWindow object corresponding to the given index. + * Will be set to NULL if no ITWindow could be retrieved. + */ + public ITWindow ItemByName (String name) { + Dispatch item = Dispatch.call(object, "ItemByName", name).toDispatch(); + return new ITWindow(item); + } + +} diff --git a/java/itunescontroller/src/main/java/com/dt/iTunesController/iTunes.java b/java/itunescontroller/src/main/java/com/dt/iTunesController/iTunes.java new file mode 100644 index 0000000..6a54d07 --- /dev/null +++ b/java/itunescontroller/src/main/java/com/dt/iTunesController/iTunes.java @@ -0,0 +1,539 @@ +package com.dt.iTunesController; + +import com.jacob.activeX.ActiveXComponent; +import com.jacob.com.ComThread; +import com.jacob.com.Dispatch; +import com.jacob.com.DispatchEvents; + +/** + * Defines the top-level iTunes application object. + * + * This interface defines the top-level iTunes application object. All other + * iTunes interfaces are accessed through this object. + * + * @author Steve Eyre + * @version 0.2 + */ +public class iTunes { + ActiveXComponent iTunes; + iTunesEvents iTunesEvents; + DispatchEvents dispatchEvents; + + /** + * Initiate iTunes Controller. + * @return + */ + public void connect() { + iTunes = new ActiveXComponent("iTunes.Application"); + } + + /** + * Add an event handler to the iTunes controller. + * @param itef The class that will handle the iTunes events. + */ + public void addEventHandler(iTunesEventsInterface itef) { + iTunesEvents = new iTunesEvents(itef); + dispatchEvents = new DispatchEvents(iTunes, iTunesEvents); + //System.out.println("New event handler added."); + } + + /** + * Reposition to the beginning of the current track or go to the previous + * track if already at start of current track. + */ + public void backTrack() { + iTunes.invoke("BackTrack"); + } + + /** + * Skip forward in a playing track. + */ + public void fastForward() { + iTunes.invoke("FastForward"); + } + + /** + * Advance to the next track in the current playlist. + */ + public void nextTrack() { + iTunes.invoke("NextTrack"); + } + + /** + * Pause playback. + */ + public void pause() { + iTunes.invoke("Pause"); + } + + /** + * Play the currently targeted track. + */ + public void play() { + iTunes.invoke("ASDSDPlay"); + } + + /** + * Play the specified file path, adding it to the library if not already + * present. + */ + public void playFile(String filePath) { + iTunes.invoke("PlayFile", filePath); + } + + /** + * Toggle the playing/paused state of the current track. + */ + public void playPause() { + iTunes.invoke("PlayPause"); + } + + /** + * Return to the previous track in the current playlist. + */ + public void previousTrack() { + iTunes.invoke("PreviousTrack"); + } + + /** + * Disable fast forward/rewind and resume playback, if playing. + */ + public void resume() { + iTunes.invoke("Resume"); + } + + /** + * Skip backwards in a playing track. + */ + public void rewind() { + iTunes.invoke("Rewind"); + } + + /** + * Stop playback. + */ + public void stop() { + iTunes.invoke("Stop"); + } + + /** + * Retrieves the current state of the player buttons in the window + * containing the currently targeted track. If there is no currently + * targeted track, returns the current state of the player buttons + * in the main browser window. + */ + public void getPlayerButtonsState(boolean previousEnabled, + String playPause, boolean nextEnabled) { + + } + + /** + * Returns true if this version of the iTunes type library is compatible + * with the specified version. + * @param majorVersion Major version of iTunes interface. + * @param minorVersion Minor version of iTunes interface. + * @return Returns true if this version is compatible with the indicated + * interface version. + */ + public boolean getCheckVersion (int majorVersion, int minorVersion) { + return iTunes.invoke("CheckVersion", majorVersion, minorVersion).getBoolean(); + } + + /** + * Returns an IITObject corresponding to the specified IDs. + * The object may be a source, playlist, or track. + * @param sourceID The ID that identifies the source. Valid for a source, + * playlist, or track. + * @param playlistID The ID that identifies the playlist. Valid for a + * playlist or track. Must be zero for a source. + * @param trackID The ID that identifies the track within the playlist. + * Valid for a track. Must be zero for a source or playlist. + * @param databaseID The ID that identifies the track, independent of its + * playlist. Valid for a track. Must be zero for a source or playlist. + * @return Returns an IITObject object corresponding to the specified IDs. + * Will be set to NULL if no object could be retrieved. + */ + public ITObject getITObjectByID(int sourceID, int playlistID, int trackID, int databaseID) { + Dispatch object = Dispatch.call(iTunes, "GetITObjectByID", sourceID, playlistID, trackID, databaseID).toDispatch(); + return new ITObject(object); + } + + /** + * Creates a new playlist in the main library. + * @param playlistName The name of the new playlist (may be empty). + * @return Returns an ITPlaylist object corresponding to the new playlist. + */ + public ITPlaylist createPlaylist(String playlistName) { + Dispatch cplaylist = Dispatch.call(iTunes, "CreatePlaylist", playlistName).toDispatch(); + ITPlaylist playlist = new ITPlaylist(cplaylist); + ITPlaylistKind playlistKind = playlist.getKind(); + if (playlistKind == ITPlaylistKind.ITPlaylistKindCD) + return new ITAudioCDPlaylist(cplaylist); + else if (playlist.getKind() == ITPlaylistKind.ITPlaylistKindLibrary) + return new ITLibraryPlaylist(cplaylist); + else if (playlist.getKind() == ITPlaylistKind.ITPlaylistKindUser) + return new ITUserPlaylist(cplaylist); + else + return playlist; + } + + /** + * Open the specified iTunes Store or streaming audio URL. + * @param url The URL to open. The length of the URL cannot exceed 512 + * characters. iTunes Store URLs start with itms:// or itmss://. Streaming + * audio URLs start with http://. + */ + public void openURL (String url) { + iTunes.invoke("OpenURL", url); + } + + /** + * Go to the iTunes Store home page. + */ + public void gotoMusicStoreHomePage() { + iTunes.invoke("GoToMusicStoreHomePage"); + } + + /** + * Update the contents of the iPod. + */ + public void updateIPod() { + iTunes.invoke("UpdateIPod"); + } + + /** + * Exits the iTunes application. + */ + public void quit() { + iTunes.invoke("Quit"); + } + + /** + * Creates a new EQ preset. + * The EQ preset will be created "flat", i.e. the preamp and all band levels + * will be set to 0. + * EQ preset names cannot start with leading spaces. If you specify a name + * that starts with leading spaces they will be stripped out. + * If eqPresetName is empty, the EQ preset will be created with + * a default name. + * @param eqPresetName The name of the new EQ Preset (may be empty) + * @return Returns an ITEQPreset object corresponding to the new EQ Preset. + */ + public ITEQPreset createEQPreset(String eqPresetName) { + Dispatch eqPreset = Dispatch.call(iTunes, "CreateEQPreset", eqPresetName).toDispatch(); + return new ITEQPreset(eqPreset); + } + + /** + * Creates a new playlist in an existing source. + * You may not be able to create a playlist in every source. For example, + * you cannot create a playlist in an audio CD source, or in an iPod source + * if it is in auto update mode. + * If playlistName is empty, the playlist will be created with + * a default name. + * @param playlistName The name of the new playlist (may be empty). + * @param source The source that will contain the new playlist. + * @return Returns an ITPlaylist object corresponding to the new playlist. + */ + public ITPlaylist createPlaylistInSource(String playlistName, ITSource source) { + Dispatch cplaylist = Dispatch.call(iTunes, "CreatePlaylistInSource", playlistName, source.fetchDispatch()).toDispatch(); + ITPlaylist playlist = new ITPlaylist(cplaylist); + ITPlaylistKind playlistKind = playlist.getKind(); + if (playlistKind == ITPlaylistKind.ITPlaylistKindCD) + return new ITAudioCDPlaylist(cplaylist); + else if (playlist.getKind() == ITPlaylistKind.ITPlaylistKindLibrary) + return new ITLibraryPlaylist(cplaylist); + else if (playlist.getKind() == ITPlaylistKind.ITPlaylistKindUser) + return new ITUserPlaylist(cplaylist); + else + return playlist; + } + + /** + * Subscribes to the specified podcast feed URL. Any "unsafe" characters in + * the URL should already be converted into their corresponding escape + * sequences, iTunes will not do this. + * @param url The URL to subscribe to. + */ + public void subscribeToPodcast(String url) { + iTunes.invoke("SubscribeToPodcast", url); + } + + /** + * Updates all podcast feeds. This is equivalent to the user pressing the + * Update button when Podcasts is selected in the Source list. + */ + public void updatePodcastFeeds() { + iTunes.invoke("UpdatePodcastFeeds"); + } + + /** + * Creates a new folder in the main library. + * If folderName is empty, the folder will be created with a + * default name. + * @param folderName The name of the new folder (may be empty). + * @return Returns an ITPlaylist object corresponding to the new folder. + */ + public ITUserPlaylist createFolder(String folderName) { + Dispatch folder = Dispatch.call(iTunes, "CreateFolder", folderName).toDispatch(); + return new ITUserPlaylist(folder); + } + + /** + * Creates a new folder in an existing source. + * You may not be able to create a folder in every source. For example, you + * cannot create a folder in an audio CD source, or in an iPod source if it + * is in auto update mode. + * If folderName is empty, the folder will be created with a + * default name. + * @param folderName The name of the new folder (may be empty) + * @param iSource The source that will contain the new folder. + * @return Returns an ITPlaylist object corresponding to the new folder. + */ + public ITUserPlaylist createFolderInSource(String folderName, ITSource iSource) { + Dispatch folder = Dispatch.call(iTunes, "CreateFolderInSource", folderName, iSource.fetchDispatch()).toDispatch(); + return new ITUserPlaylist(folder); + } + + /** + * Returns a collection of music sources (music library, CD, device, etc.). + * @return Collection of ITSource objects. + */ + public ITSourceCollection getSources() { + Dispatch sources = Dispatch.call(iTunes, "Sources").toDispatch(); + return new ITSourceCollection(sources); + } + + /** + * Sets the sound output volume (0=minimum, 100=maximum). + * @param volume New sound output volume + */ + public void setSoundVolume(int volume) { + iTunes.setProperty("SoundVolume", volume); + } + + /** + * Returns the sound output volume (0=minimum, 100=maximum). + * @return Current sound output volume + */ + public int getSoundVolume() { + return iTunes.getPropertyAsInt("SoundVolume"); + } + + /** + * Sets sound output mute state. + * @param shouldMute If true, sound output will be muted. + */ + public void setMute(boolean shouldMute) { + iTunes.setProperty("Mute", shouldMute); + } + + /** + * Returns true if the sound output is muted. + * @return True if sound output is muted. + */ + public boolean getMute() { + return iTunes.getPropertyAsBoolean("Mute"); + } + + /** + * Toggle the mute state. + */ + public void toggleMute() { + setMute(!getMute()); + } + + /** + * Toggle the shuffle state. + */ + public void toggleShuffle() { + getCurrentPlaylist().toggleShuffle(); + } + + /** + * Returns the current player state. + * @return Returns the current player state. + */ + public ITPlayerState getPlayerState() { + return ITPlayerState.values()[Dispatch.get(iTunes, "PlayerState").getInt()]; + } + + /** + * Sets the player's position within the currently playing track in + * seconds. + * If playerPos specifies a position before the beginning of the track, + * the position will be set to the beginning. If playerPos specifies a + * position after the end of the track, the position will be set to the + * end. + * @param playerPos The player's position within the currently playing + * track in seconds. + */ + public void setPlayerPosition(int playerPos) { + iTunes.setProperty("playerPosition", playerPos); + } + + /** + * Returns the player's position within the currently playing track in + * seconds. + * @return The player's position within the currently playing track in + * seconds. + */ + public int getPlayerPosition() { + return iTunes.getPropertyAsInt("playerPosition"); + } + + /** + * Returns the source that represents the main library. + * You can also find the main library source by iterating over + * iTunes.getSources() and looking for an ITSource + * of kind ITSourceKindLibrary. + * @return Returns the source that represents the main library. + */ + public ITSource getLibrarySource() { + Dispatch lsource = iTunes.getProperty("LibrarySource").toDispatch(); + return new ITSource(lsource); + } + + /** + * Returns the main library playlist in the main library source. + * @return An IITLibraryPlaylist object corresponding to the main library + * playlist. + */ + public ITLibraryPlaylist getLibraryPlaylist() { + Dispatch lplaylist = iTunes.getProperty("LibraryPlaylist").toDispatch(); + return new ITLibraryPlaylist(lplaylist); + } + + /** + * Returns the currently targetd track. + * @return An ITTrack object corresponding to the currently targeted track. + * Will be set to NULL if there is no currently targeted track. + */ + public ITTrack getCurrentTrack() { + Dispatch item = iTunes.getProperty("CurrentTrack").toDispatch(); + ITTrack track = new ITTrack(item); + if (track.getKind()==ITTrackKind.ITTrackKindFile) { + return new ITFileOrCDTrack(item); + } else if (track.getKind()==ITTrackKind.ITTrackKindCD) { + return new ITFileOrCDTrack(item); + } else if (track.getKind()==ITTrackKind.ITTrackKindURL ) { + return new ITURLTrack(item); + } else { + return track; + } + } + + /** + * Returns the playlist containing the currently targeted track. + * @return An ITPlaylist object corresponding to the playlist containing the + * currently targeted track. + * Will be set to NULL if there is no currently targeted playlist. + */ + public ITPlaylist getCurrentPlaylist() { + Dispatch cplaylist = iTunes.getProperty("CurrentPlaylist").toDispatch(); + ITPlaylist playlist = new ITPlaylist(cplaylist); + ITPlaylistKind playlistKind = playlist.getKind(); + if (playlistKind == ITPlaylistKind.ITPlaylistKindCD) + return new ITAudioCDPlaylist(cplaylist); + else if (playlist.getKind() == ITPlaylistKind.ITPlaylistKindLibrary) + return new ITLibraryPlaylist(cplaylist); + else if (playlist.getKind() == ITPlaylistKind.ITPlaylistKindUser) + return new ITUserPlaylist(cplaylist); + else + return playlist; + } + + /** + * Returns a collection containing the currently selected track or tracks. + * The frontmost visible window in iTunes must be a browser or playlist + * window. If there is no frontmost visible window (e.g. iTunes is minimized + * to the system tray), the main browser window is used. + * @return Collection of ITrack objects. + * Will be set to NULL if there is no current selection. + */ + public ITTrackCollection getSelectedTracks() { + Dispatch stracks = iTunes.getProperty("SelectedTracks").toDispatch(); + return new ITTrackCollection(stracks); + } + + /** + * Returns the version of the iTunes application. + * @return + */ + public String getVersion() { + return iTunes.getPropertyAsString("Version"); + } + + /** + * Returns the high 32 bits of the persistent ID of the specified IITObject. + * See the documentation on IITObject for more information on persistent + * IDs. + * + * The object may be a source, playlist, or track. + * @param iObject The object to fetch the High Persistent ID. + * @return The high 32 bits of the 64-bit persistent ID. + */ + public long getITObjectPersistentIDHigh (ITObject iObject) { + Dispatch object = iObject.fetchDispatch(); + return Dispatch.call(object, "GetObjectPersistentIDHigh", object).getLong(); + } + + /** + * Returns the low 32 bits of the persistent ID of the specified IITObject. + * See the documentation on IITObject for more information on persistent + * IDs. + * + * The object may be a source, playlist, or track. + * @param iObject The object to fetch the Low Persistent ID. + * @return The low 32 bits of the 64-bit persistent ID. + */ + public long getITObjectPersistentIDLow (ITObject iObject) { + Dispatch object = iObject.fetchDispatch(); + return Dispatch.call(object, "GetObjectPersistentIDLow", object).getLong(); + } + + public ITObjectPersistentID getObjectPersistentIDs(ITObject iObject){ + return new ITObjectPersistentID(getITObjectPersistentIDHigh(iObject),getITObjectPersistentIDLow(iObject)); + } + + public ITBrowserWindow getBrowserWindow(){ + Dispatch window = iTunes.getProperty("BrowserWindow").toDispatch(); + return new ITBrowserWindow(window); + } + + public void cycleSongRepeat() { + getCurrentPlaylist().cycleSongRepeat(); + } + + public ITPlaylist getPlaylist(String name) { + ITPlaylistCollection playlistCollection = getLibrarySource().getPlaylists(); + ITPlaylist playlist = playlistCollection.ItemByName(name); + try { + playlist.getName(); + } catch (IllegalStateException e) { + playlist = createPlaylist(name); + } + return playlist; + } + + public ITUserPlaylist getUserPlaylist(String name) { + ITPlaylist playlist = getPlaylist(name); + ITUserPlaylist userPlaylist = new ITUserPlaylist(playlist.fetchDispatch()); + return userPlaylist; + } + + public void playlistAddTrack(String name, ITTrack track) { + ITUserPlaylist userPlaylist = getUserPlaylist(name); + if (!userPlaylist.containsTrack(track)) { + userPlaylist.addTrack(track); + } + } + + public void playlistAddCurrentTrack(String name) { + playlistAddTrack(name, getCurrentTrack()); + } + + public void release() { + ComThread.Release(); + } +} diff --git a/java/itunescontroller/src/main/java/com/dt/iTunesController/iTunesEvents.java b/java/itunescontroller/src/main/java/com/dt/iTunesController/iTunesEvents.java new file mode 100644 index 0000000..ddbee23 --- /dev/null +++ b/java/itunescontroller/src/main/java/com/dt/iTunesController/iTunesEvents.java @@ -0,0 +1,62 @@ +package com.dt.iTunesController; +import com.jacob.com.Dispatch; +import com.jacob.com.Variant; + +/** + * This class is used to forward all iTunes COM Events to a class that + * implements iTunesEventsInterface. To receive events, create + * a class that implements the interface, and then use + * iTunes.addEventHandler(). + * + * @author Steve Eyre + * @version 0.2 + */ +public class iTunesEvents { + + private iTunesEventsInterface eventHandler; + + public iTunesEvents (iTunesEventsInterface itef) { + eventHandler = itef; + } + + public void OnDatabaseChangedEvent(Variant[] args) { + // Not currently implemented + } + + public void OnPlayerPlayEvent(Variant[] args) { + ITTrack itt = new ITTrack((Dispatch)args[0].getDispatch()); + eventHandler.onPlayerPlayEvent(itt); + } + + public void OnPlayerStopEvent(Variant[] args) { + ITTrack itt = new ITTrack((Dispatch)args[0].getDispatch()); + eventHandler.onPlayerStopEvent(itt); + } + + public void OnPlayerPlayingTrackChangedEvent(Variant[] args) { + ITTrack itt = new ITTrack((Dispatch)args[0].getDispatch()); + eventHandler.onPlayerPlayingTrackChangedEvent(itt); + } + + public void OnCOMCallsDisabledEvent(Variant[] args) { + ITCOMDisabledReason reason = ITCOMDisabledReason.values()[args[0].getInt()]; + eventHandler.onCOMCallsDisabledEvent(reason); + } + + public void OnCOMCallsEnabledEvent(Variant[] args) { + eventHandler.onCOMCallsEnabledEvent(); + } + + public void OnQuittingEvent(Variant[] args) { + eventHandler.onQuittingEvent(); + } + + public void OnAboutToPromptUserToQuitEvent(Variant[] args) { + eventHandler.onAboutToPromptUserToQuitEvent(); + } + + public void OnSoundVolumeChangedEvent(Variant[] args) { + eventHandler.onSoundVolumeChangedEvent(args[0].getInt()); + } + +} diff --git a/java/itunescontroller/src/main/java/com/dt/iTunesController/iTunesEventsInterface.java b/java/itunescontroller/src/main/java/com/dt/iTunesController/iTunesEventsInterface.java new file mode 100644 index 0000000..3d8f17e --- /dev/null +++ b/java/itunescontroller/src/main/java/com/dt/iTunesController/iTunesEventsInterface.java @@ -0,0 +1,115 @@ +package com.dt.iTunesController; + +/** + * Interface for receiving iTunes events. + * @author Steve Eyre + * @version 0.2 + */ +public interface iTunesEventsInterface { + + /** + * Not currently implemented. + * + * The ITEventDatabaseChanged event is fired when the iTunes database is + * changed. + * + * Each parameter is a two-dimensional array of integers. The first + * dimension is the number of objects. The second dimension is always 4 and + * specifies each of the 4 ITObject IDs, where index 0 is the source ID, + * index 1 is the playlist ID, index 2 is the track ID, and index 3 is the + * track database ID. For more information on object IDs, see + * ITObject. + * + * Note that you can use iTunes.getITObjectByID() to retrieve + * changed ITObject, but not for deleted objects (since they no longer + * exist). + * + * @param deletedObjectIDs + * @param changedObjectIDs + */ + public void onDatabaseChangedEvent(int[][] deletedObjectIDs, int[][] changedObjectIDs); + + /** + * The ITEventPlayerPlay event is fired when a track begins playing. + * @param iTrack An ITTrack object corresponding to the track that has + * started playing. + */ + public void onPlayerPlayEvent (ITTrack iTrack); + + /** + * The ITEventPlayerStop event is fired when a track stops playing. + * @param iTrack An ITTrack object corresponding to the track that has + * stopped playing. + */ + public void onPlayerStopEvent (ITTrack iTrack); + + /** + * The ITEventPlayerPlayingTrackChanged event is fired when information + * about the currently playing track has changed. + * This event is fired when the user changes information about the currently + * playing track (e.g. the name of the track). + * This event is also fired when iTunes plays the next joined CD track in a + * CD playlist, since joined CD tracks are treated as a single track. + * @param iTrack An ITTrack object corresponding to the track that is now + * playing. + */ + public void onPlayerPlayingTrackChangedEvent(ITTrack iTrack); + + /** + * The ITEventCOMCallsDisabled event is fired when calls to the iTunes COM + * interface will be deferred. + * Typically, iTunes will defer COM calls when any modal dialog is being + * displayed. When the user dismisses the last modal dialog, COM calls will + * be enabled again, and any deferred COM calls will be executed. You can + * use this event to avoid making a COM call which will be deferred. + * @param reason The reason the COM interface is being disabled. This is + * typically ITCOMDisabledReasonDialog. + */ + public void onCOMCallsDisabledEvent(ITCOMDisabledReason reason); + + /** + * The ITEventCOMCallsEnabled event is fired when calls to the iTunes COM + * interface will no longer be deferred. + * Typically, iTunes will defer COM calls when any modal dialog is being + * displayed. When the user dismisses the last modal dialog, COM calls will + * be enabled again, and any deferred COM calls will be executed. + */ + public void onCOMCallsEnabledEvent(); + + /** + * The ITEventQuitting event is fired when iTunes is about to quit. + * If the user attempts to quit iTunes while a client still has outstanding + * iTunes COM objects instantiated, iTunes will display a warning dialog. + * The user can still choose to quit iTunes anyway, in which case this event + * will be fired. After this event is fired, any existing iTunes COM objects + * will no longer be valid. + * This event is only used to notify clients that iTunes is quitting, + * clients cannot prevent this from happening. + */ + public void onQuittingEvent(); + + /** + * The ITEventAboutToPromptUserToQuit event is fired when iTunes is about + * prompt the user to quit. + * This event gives clients the opportunity to prevent the warning dialog + * prompt from occurring. + * If the user attempts to quit iTunes while a client still has outstanding + * iTunes COM objects instantiated, iTunes will display a warning dialog. + * This event is fired just before the warning dialog is shown. iTunes will + * then wait up to 5 seconds for clients to release any outstanding iTunes + * COM objects. If all objects are released during this time, the warning + * dialog will not be shown and iTunes will quit immediately. + * Otherwise, the warning dialog will be shown. If the user chooses to quit + * iTunes anyway, the ITEventQuitting event is fired. See + * iTunesEventsInterface.onQuittingEvent() for more details. + */ + public void onAboutToPromptUserToQuitEvent(); + + /** + * The ITEventSoundVolumeChanged event is fired when the sound output volume + * has changed. + * @param newVolume The new sound output volume (0 = minimum, 100 = maximum). + */ + public void onSoundVolumeChangedEvent(int newVolume); + +} diff --git a/java/mimis/.classpath b/java/mimis/.classpath new file mode 100644 index 0000000..c80843f --- /dev/null +++ b/java/mimis/.classpath @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/java/mimis/.project b/java/mimis/.project new file mode 100644 index 0000000..e30efa6 --- /dev/null +++ b/java/mimis/.project @@ -0,0 +1,18 @@ + + + mimis + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.springsource.ide.eclipse.gradle.core.nature + org.eclipse.jdt.core.javanature + + diff --git a/java/mimis/DelcomDLL.dll b/java/mimis/DelcomDLL.dll new file mode 100644 index 0000000..ecfa470 Binary files /dev/null and b/java/mimis/DelcomDLL.dll differ diff --git a/java/mimis/WiiPair.exe b/java/mimis/WiiPair.exe new file mode 100644 index 0000000..f16c97d Binary files /dev/null and b/java/mimis/WiiPair.exe differ diff --git a/java/mimis/build.gradle b/java/mimis/build.gradle new file mode 100644 index 0000000..427e0f1 --- /dev/null +++ b/java/mimis/build.gradle @@ -0,0 +1,35 @@ +import java.util.jar.JarEntry; + +apply plugin: 'java' +apply plugin: 'eclipse' +apply plugin: 'cpp-lib' + +version = '0.1' + +sourceCompatibility = 1.6 +targetCompatibility = 1.6 + +def mainClass = 'mimis.Main' + +repositories { + mavenCentral() +} + +dependencies { + compile project(':itunescontroller') + compile project(':wiiusej') + compile project(':wiigee') + + compile 'commons-collections:commons-collections:3.+' + compile 'commons-logging:commons-logging:1.+' + compile 'log4j:log4j:1.2.17' + compile 'com.melloware:jintellitype:1.3.7' + + compile fileTree(dir: 'lib', include: '*.jar') +} + +jar { + manifest { + attributes 'Main-Class': mainClass + } +} \ No newline at end of file diff --git a/java/mimis/build.xml b/java/mimis/build.xml new file mode 100644 index 0000000..4d47af4 --- /dev/null +++ b/java/mimis/build.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/java/mimis/client.jar b/java/mimis/client.jar new file mode 100644 index 0000000..a16b1bd Binary files /dev/null and b/java/mimis/client.jar differ diff --git a/java/mimis/irtoy.exe b/java/mimis/irtoy.exe new file mode 100644 index 0000000..0dc97e5 Binary files /dev/null and b/java/mimis/irtoy.exe differ diff --git a/java/mimis/jacob-1.15-M3-x86.dll b/java/mimis/jacob-1.15-M3-x86.dll new file mode 100644 index 0000000..34876a0 Binary files /dev/null and b/java/mimis/jacob-1.15-M3-x86.dll differ diff --git a/java/mimis/jintellitype.dll b/java/mimis/jintellitype.dll new file mode 100644 index 0000000..839236b Binary files /dev/null and b/java/mimis/jintellitype.dll differ diff --git a/java/mimis/jxinput.dll b/java/mimis/jxinput.dll new file mode 100644 index 0000000..720b9bb Binary files /dev/null and b/java/mimis/jxinput.dll differ diff --git a/java/mimis/launch4j.xml b/java/mimis/launch4j.xml new file mode 100644 index 0000000..d3043f1 --- /dev/null +++ b/java/mimis/launch4j.xml @@ -0,0 +1,22 @@ + + false + gui + main.jar + mimis.exe + Mimis + + + normal + http://java.com/download + + true + false + + resource\M.ico + + + 1.6.0 + + preferJre + + \ No newline at end of file diff --git a/java/mimis/lib/jxinput.jar b/java/mimis/lib/jxinput.jar new file mode 100644 index 0000000..dbb035a Binary files /dev/null and b/java/mimis/lib/jxinput.jar differ diff --git a/java/mimis/main.jar b/java/mimis/main.jar new file mode 100644 index 0000000..ba79a74 Binary files /dev/null and b/java/mimis/main.jar differ diff --git a/java/mimis/mimis.dll b/java/mimis/mimis.dll new file mode 100644 index 0000000..25ef12a Binary files /dev/null and b/java/mimis/mimis.dll differ diff --git a/java/mimis/mimis.exe b/java/mimis/mimis.exe new file mode 100644 index 0000000..93a6acf Binary files /dev/null and b/java/mimis/mimis.exe differ diff --git a/java/mimis/src/main/java/mimis/Client.java b/java/mimis/src/main/java/mimis/Client.java new file mode 100644 index 0000000..c784918 --- /dev/null +++ b/java/mimis/src/main/java/mimis/Client.java @@ -0,0 +1,25 @@ +package mimis; + +import mimis.exception.worker.ActivateException; +import mimis.router.GlobalRouter; +import mimis.util.swing.Dialog; + +public class Client extends Main { + public static final String IP = "127.0.0.1"; + public static final int PORT = 6789; + + public Client(String ip, int port) { + super(); + router = new GlobalRouter(ip, port); + } + + public void activate() throws ActivateException { + super.activate(); + } + + public static void main(String[] args) { + String ip = Dialog.question("Server IP:", IP); + int port = Integer.valueOf(Dialog.question("Server Port:", PORT)); + new Client(ip, port).start(); + } +} \ No newline at end of file diff --git a/java/mimis/src/main/java/mimis/Gui.java b/java/mimis/src/main/java/mimis/Gui.java new file mode 100644 index 0000000..193ecea --- /dev/null +++ b/java/mimis/src/main/java/mimis/Gui.java @@ -0,0 +1,98 @@ +package mimis; + +import java.awt.GridLayout; +import java.awt.TextArea; +import java.awt.event.WindowEvent; + +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.WindowConstants; + +import mimis.exception.worker.ActivateException; +import mimis.input.Feedback; +import mimis.input.Input; +import mimis.manager.ButtonManager; +import mimis.util.Swing; +import mimis.worker.Component; + +public class Gui extends Component { + public static final String ICON = "M.png"; + public static final String TITLE = "MIMIS Manager"; + + protected JFrame frame; + protected Component component; + protected TextArea textArea; + + public Gui(final Component component, ButtonManager... buttonManagerArray) { + frame = new JFrame(TITLE) { + protected static final long serialVersionUID = 1L; + protected void processWindowEvent(WindowEvent event) { + if (event.getID() == WindowEvent.WINDOW_CLOSING) { + log.debug("Window closing"); + component.exit(); + } + } + }; + this.component = component; + frame.setIconImage(Swing.getImage(ICON)); + createFrame(buttonManagerArray); + } + + protected void activate() throws ActivateException { + listen(Feedback.class); + super.activate(); + } + + public void exit() { + super.exit(); + frame.dispose(); + } + + protected void createFrame(ButtonManager... buttonManagerArray) { + frame.setLayout(new GridLayout(0, 1)); + JPanel controlPanel = createControlPanel(buttonManagerArray); + frame.add(controlPanel); + JPanel feedbackPanel = createTextPanel(); + frame.add(feedbackPanel); + frame.setResizable(false); + frame.setVisible(true); + frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); + frame.pack(); + } + + protected JPanel createControlPanel(ButtonManager... buttonManagerArray) { + JPanel controlPanel = new JPanel(new GridLayout(1, 0)); + for (ButtonManager buttonManager : buttonManagerArray) { + if (buttonManager.count() > 0) { + controlPanel.add(buttonManager.createPanel()); + } + } + return controlPanel; + } + + protected JPanel createTextPanel() { + JPanel textPanel = new JPanel(); + textArea = new TextArea(); + textArea.setEditable(false); + textPanel.add(textArea); + return textPanel; + } + + public void input(Input input) { + if (input instanceof Feedback) { + writeLine(((Feedback) input).getText()); + } + } + + public void write(String string) { + textArea.append(string); + } + + public void writeLine(String string) { + write(string + "\n"); + } + + public void clear() { + textArea.setText(null); + } +} diff --git a/java/mimis/src/main/java/mimis/Main.java b/java/mimis/src/main/java/mimis/Main.java new file mode 100644 index 0000000..fa2d92f --- /dev/null +++ b/java/mimis/src/main/java/mimis/Main.java @@ -0,0 +1,102 @@ +package mimis; + +import java.util.ArrayList; +import java.util.ServiceLoader; + +import javax.swing.UIManager; + +import mimis.exception.worker.ActivateException; +import mimis.exception.worker.DeactivateException; +import mimis.input.Task; +import mimis.manager.ButtonManager; +import mimis.manager.CurrentButtonManager; +import mimis.value.Action; +import mimis.worker.Component; + +public class Main extends Mimis { + protected CurrentButtonManager applicationManager; + protected ButtonManager deviceManager; + protected Gui gui; + + static { + try { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + } catch (Exception e) {} + + } + + public static Component[] getApplications() { + return getComponents(mimis.application.Application.class); + } + + public static Component[] getDevices() { + return getComponents(mimis.device.Device.class); + } + + public static Component[] getComponents(Class clazz) { + ArrayList componentList = new ArrayList(); + for (Object object : ServiceLoader.load(clazz)) { + if (object instanceof Component) { + componentList.add((Component) object); + } + } + return componentList.toArray(new Component[]{}); + } + + public Main() { + super(getApplications()); + + /* Create gui from application and device managers */ + applicationManager = new CurrentButtonManager(router, componentCycle, "Applications", currentArray); + deviceManager = new ButtonManager("Devices", initialize(false, getDevices())); + gui = new Gui(this, applicationManager, deviceManager); + manager.add(initialize(false, gui)); + } + + public void activate() throws ActivateException { + super.activate(); + listen(Task.class); + + /* Start managers */ + applicationManager.start(); + deviceManager.start(); + + /* Force display of current component when gui started */ + gui.start(); + while (!gui.active()); + end(Action.CURRENT); + } + + protected void deactivate() throws DeactivateException { + super.deactivate(); + + log.debug("Stop managers"); + applicationManager.stop(); + deviceManager.stop(); + } + + public void exit() { + super.exit(); + + log.debug("Exit managers"); + applicationManager.exit(); + deviceManager.exit(); + } + + public void end(Action action) { + super.end(action); + switch (action) { + case CURRENT: + case NEXT: + case PREVIOUS: + applicationManager.currentChanged(); + break; + default: + break; + } + } + + public static void main(String[] args) { + new Main().start(false); + } +} diff --git a/java/mimis/src/main/java/mimis/Mimis.java b/java/mimis/src/main/java/mimis/Mimis.java new file mode 100644 index 0000000..3185c4f --- /dev/null +++ b/java/mimis/src/main/java/mimis/Mimis.java @@ -0,0 +1,81 @@ +package mimis; + +import mimis.exception.worker.ActivateException; +import mimis.exception.worker.DeactivateException; +import mimis.input.Feedback; +import mimis.input.Task; +import mimis.manager.Manager; +import mimis.parser.Parser; +import mimis.router.Router; +import mimis.util.ArrayCycle; +import mimis.value.Action; +import mimis.value.Target; +import mimis.worker.Component; + +public abstract class Mimis extends Component { + protected Component[] currentArray; + protected Manager manager; + + protected ArrayCycle componentCycle; + + public Mimis(Component... currentArray) { + this.currentArray = initialize(false, currentArray); + componentCycle = new ArrayCycle(currentArray); + router = new Router(); + manager = new Manager(initialize(true, router, new Parser())); + } + + public void activate() throws ActivateException { + manager.start(); + super.activate(); + } + + protected void deactivate() throws DeactivateException { + super.deactivate(); + manager.stop(); + } + + public void exit() { + super.exit(); + manager.exit(); + } + + public Component[] initialize(boolean start, Component... componentArray) { + for (Component component : componentArray) { + component.setRouter(router); + if (start) { + component.start(); + } + } + return componentArray; + } + + public void task(Task task) { + if (task.getTarget().equals(Target.CURRENT)) { + componentCycle.current().add(task); + } else { + super.task(task); + } + } + + public void end(Action action) { + switch (action) { + case CURRENT: + route(new Feedback("Current component: " + componentCycle.current().getTitle())); + break; + case NEXT: + log.debug("Next component"); + route(new Feedback("Next component: " + componentCycle.next().getTitle())); + break; + case PREVIOUS: + log.debug("Previous component"); + route(new Feedback("Previous component: " + componentCycle.previous().getTitle())); + break; + case EXIT: + exit(); + break; + default: + break; + } + } +} \ No newline at end of file diff --git a/java/mimis/src/main/java/mimis/application/Application.java b/java/mimis/src/main/java/mimis/application/Application.java new file mode 100644 index 0000000..8dc6e15 --- /dev/null +++ b/java/mimis/src/main/java/mimis/application/Application.java @@ -0,0 +1,6 @@ +package mimis.application; + + +public interface Application { + +} diff --git a/java/mimis/src/main/java/mimis/application/cmd/CMDApplication.java b/java/mimis/src/main/java/mimis/application/cmd/CMDApplication.java new file mode 100644 index 0000000..bd518f3 --- /dev/null +++ b/java/mimis/src/main/java/mimis/application/cmd/CMDApplication.java @@ -0,0 +1,80 @@ +package mimis.application.cmd; + +import java.io.IOException; +import java.util.Map; + +import mimis.application.Application; +import mimis.exception.worker.ActivateException; +import mimis.exception.worker.DeactivateException; +import mimis.util.Native; +import mimis.value.Registry; +import mimis.worker.Component; + +public abstract class CMDApplication extends Component implements Application { + protected final static Registry REGISTRY = Registry.LOCAL_MACHINE; + protected final static String KEY = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths"; + + protected String program; + protected String title; + protected Process process; + protected boolean detect, running; + + public CMDApplication(String program, String title) { + super(title); + this.program = program; + this.title = title; + detect = true; + } + + protected void activate() throws ActivateException { + detect = true; + if (!running) { + String path = getPath(); + if (path == null) { + throw new ActivateException(); + } + try { + String command = path.startsWith("\"") ? path : String.format("\"%s\"", path); + command = replaceVariables(command); + process = Runtime.getRuntime().exec(command); + } catch (IOException e) { + log.error(e); + throw new ActivateException(); + } + } + super.activate(); + } + + public boolean active() { + if (detect) { + running = Native.isRunning(program); + if (!active && running) { + active = true; + start(); + } + } + return active; + } + + protected synchronized void deactivate() throws DeactivateException { + detect = false; + super.deactivate(); + if (process != null) { + process.destroy(); + } + } + + public String getPath() { + String key = String.format("%s\\%s", KEY, program); + System.out.println(Native.getValue(REGISTRY, key)); + return Native.getValue(REGISTRY, key); + } + + public static String replaceVariables(String string) { + Map env = System.getenv(); + for (String key : env.keySet()) { + string = string.replace(String.format("%%%s%%", key), env.get(key)); + } + return string; + } +} diff --git a/java/mimis/src/main/java/mimis/application/cmd/windows/WindowsApplication.java b/java/mimis/src/main/java/mimis/application/cmd/windows/WindowsApplication.java new file mode 100644 index 0000000..673f396 --- /dev/null +++ b/java/mimis/src/main/java/mimis/application/cmd/windows/WindowsApplication.java @@ -0,0 +1,100 @@ +package mimis.application.cmd.windows; + +import mimis.application.cmd.CMDApplication; +import mimis.exception.worker.ActivateException; +import mimis.exception.worker.DeactivateException; +import mimis.util.Native; +import mimis.value.Command; +import mimis.value.Key; +import mimis.value.Type; +import mimis.value.Windows; + +public abstract class WindowsApplication extends CMDApplication { + protected final static int TERMINATE_SLEEP = 500; + protected final static int START_SLEEP = 500; + + protected String window; + protected int handle; + + public WindowsApplication(String title, String window) { + this(null, title, window); + } + + public WindowsApplication(String program, String title, String window) { + super(program, title); + this.window = window; + handle = 0; + } + + protected void activate() throws ActivateException { + if (program != null) { + super.activate(); + } + handle = Native.getHandle(window); + if (handle < 1) { + sleep(START_SLEEP); + handle = Native.getHandle(window); + } + active = handle > 0; + if (!active) { + throw new ActivateException(); + } + } + + public boolean active() { + if (!active || program == null) { + handle = Native.getHandle(window); + if (handle > 0 && program == null) { + start(); + } + } + return program == null ? handle > 0 : super.active(); + } + + protected void deactivate() throws DeactivateException { + if (process == null) { + active = false; + } else { + super.deactivate(); + } + close(); + } + + protected void close() { + Native.sendMessage(handle, Windows.WM_CLOSE, 0, 0); + } + + protected void command(Command command) { + Native.sendMessage(handle, Windows.WM_APPCOMMAND, handle, command.getCode() << 16); + } + + protected void command(int command) { + Native.sendMessage(handle, Windows.WM_COMMAND, command, 0); + } + + protected int user(int wParam, int lParam) { + return Native.sendMessage(handle, Windows.WM_USER, wParam, lParam); + } + + protected void system(Command.System system) { + system(system, 0); + } + + protected void system(Command.System system, int lParam) { + Native.sendMessage(handle, Windows.WM_SYSCOMMAND, system.getCode(), lParam); + } + + protected void key(Type type, int code) { + int scanCode = Native.mapVirtualKey(code, Windows.MAPVK_VK_TO_VSC); + Native.postMessage(handle, type.getCode(), code, 1 | (scanCode << 16) | 1 << 30); + sleep(200); + } + + protected void key(Type type, char character) { + key(type, (int) Character.toUpperCase(character)); + } + + protected void key(Type key, Key virtualKey) { + key(key, virtualKey.getCode()); + } +} diff --git a/java/mimis/src/main/java/mimis/application/cmd/windows/gomplayer/GomPlayerApplication.java b/java/mimis/src/main/java/mimis/application/cmd/windows/gomplayer/GomPlayerApplication.java new file mode 100644 index 0000000..0ea28e0 --- /dev/null +++ b/java/mimis/src/main/java/mimis/application/cmd/windows/gomplayer/GomPlayerApplication.java @@ -0,0 +1,127 @@ +package mimis.application.cmd.windows.gomplayer; + +import mimis.application.cmd.windows.WindowsApplication; +import mimis.exception.worker.ActivateException; +import mimis.exception.worker.DeactivateException; +import mimis.value.Action; +import mimis.value.Amount; +import mimis.worker.Worker; + +public class GomPlayerApplication extends WindowsApplication { + protected final static String PROGRAM = "GOM.exe"; + protected final static String TITLE = "GOM Player"; + protected final static String WINDOW = "GomPlayer1.x"; + + protected static final int VOLUME_SLEEP = 100; + protected static final int SEEK_SLEEP = 100; + + protected VolumeWorker volumeWorker; + protected SeekWorker seekWorker; + + public GomPlayerApplication() { + super(PROGRAM, TITLE, WINDOW); + volumeWorker = new VolumeWorker(); + seekWorker = new SeekWorker(); + } + + protected void deactivate() throws DeactivateException { + super.deactivate(); + volumeWorker.stop(); + seekWorker.stop(); + } + + public void exit() { + super.exit(); + volumeWorker.exit(); + seekWorker.exit(); + } + + public void begin(Action action) { + log.trace("GomPlayerApplication begin: " + action); + switch (action) { + case VOLUME_UP: + volumeWorker.start(); + break; + case VOLUME_DOWN: + volumeWorker.start(); + break; + case FORWARD: + seekWorker.start(Amount.SMALL, 1); + break; + case REWIND: + seekWorker.start(Amount.SMALL, -1); + break; + case NEXT: + seekWorker.start(Amount.MEDIUM, 1); + break; + case PREVIOUS: + seekWorker.start(Amount.MEDIUM, -1); + break; + } + } + + public void end(Action action) { + log.trace("GomPlayerApplication end: " + action); + switch (action) { + case PLAY: + command(0x800C); + break; + case MUTE: + command(0x8016); + break; + case FORWARD: + case REWIND: + case NEXT: + case PREVIOUS: + seekWorker.stop(); + break; + case VOLUME_UP: + case VOLUME_DOWN: + volumeWorker.stop(); + break; + case FULLSCREEN: + command(0x8154); + break; + } + } + + protected class VolumeWorker extends Worker { + protected int volumeChangeSign; + + public void start(int volumeChangeSign) throws ActivateException { + super.start(); + this.volumeChangeSign = volumeChangeSign; + } + + public void work() { + command(volumeChangeSign > 0 ? 0x8014 : 0x8013); + sleep(VOLUME_SLEEP); + } + }; + + protected class SeekWorker extends Worker { + protected Amount amount; + protected int seekDirection; + + public void start(Amount amount, int seekDirection) { + super.start(); + this.amount = amount; + this.seekDirection = seekDirection; + } + + public void work() { + switch (amount) { + case SMALL: + command(seekDirection > 0 ? 0x8009 : 0x8008); + break; + case MEDIUM: + command(seekDirection > 0 ? 0x800B : 0x800A); + break; + case LARGE: + command(seekDirection > 0 ? 0x8012 : 0x8011); + break; + } + sleep(SEEK_SLEEP); + } + }; +} diff --git a/java/mimis/src/main/java/mimis/application/cmd/windows/photoviewer/PhotoViewerApplication.java b/java/mimis/src/main/java/mimis/application/cmd/windows/photoviewer/PhotoViewerApplication.java new file mode 100644 index 0000000..d59bd9c --- /dev/null +++ b/java/mimis/src/main/java/mimis/application/cmd/windows/photoviewer/PhotoViewerApplication.java @@ -0,0 +1,110 @@ +package mimis.application.cmd.windows.photoviewer; + +import mimis.application.cmd.windows.WindowsApplication; +import mimis.exception.worker.DeactivateException; +import mimis.value.Action; +import mimis.value.Key; +import mimis.value.Type; +import mimis.worker.Worker; + +public class PhotoViewerApplication extends WindowsApplication { + protected final static String TITLE = "Photo Viewer"; + protected final static String WINDOW = "Photo_Lightweight_Viewer"; + + protected static final int ZOOM_SLEEP = 100; + protected static final int DELETE_SLEEP = 2000; + + protected ZoomWorker zoomWorker; + protected boolean fullscreen; + + public PhotoViewerApplication() { + super(TITLE, WINDOW); + zoomWorker = new ZoomWorker(); + fullscreen = false; + } + + protected void deactivate() throws DeactivateException { + super.deactivate(); + zoomWorker.stop(); + } + + public void exit() { + super.exit(); + zoomWorker.exit(); + } + + public void begin(Action action) { + switch (action) { + case VOLUME_UP: + zoomWorker.start(1); + break; + case VOLUME_DOWN: + zoomWorker.start(-1); + break; + } + } + + public void end(Action action) { + log.trace("PhotoViewerApplication end: " + action); + switch (action) { + case VOLUME_UP: + case VOLUME_DOWN: + zoomWorker.stop(); + break; + case NEXT: + key(Type.DOWN, Key.RIGHT); + break; + case PREVIOUS: + key(Type.DOWN, Key.LEFT); + break; + case FORWARD: + key(Type.DOWN, Key.CONTROL); + //key(Type.DOWN, '.'); + //key(Type.DOWN, Key.DECIMAL); + key(Type.DOWN, Key.OEM_PERIOD); + //key(Type.UP, Key.OEM_PERIOD); + //key(Type.UP, Key.CONTROL); + break; + case MUTE: + key(Type.DOWN, Key.CONTROL); + key(Type.DOWN, Key.NUMPAD0); + //press(Key.CONTROL); + //press(Key.NUMPAD0); + //release(Key.CONTROL); + break; + case FULLSCREEN: + key(Type.DOWN, fullscreen ? Key.ESCAPE : Key.F11); + fullscreen = !fullscreen; + break; + case DISLIKE: + /*boolean restore = false; + if (fullscreen) { + end(Action.FULLSCREEN); + sleep(DELETE_SLEEP); + restore = true; + } + key(Type.DOWN, Key.F16); + key(Type.DOWN, 'Y'); + if (restore) { + sleep(DELETE_SLEEP); + end(Action.FULLSCREEN); + }*/ + break; + } + } + + protected class ZoomWorker extends Worker { + protected int zoomDirection; + + public void start(int zoomDirection) { + super.start(); + this.zoomDirection = zoomDirection; + } + + public void work() { + Key key = zoomDirection > 0 ? Key.ADD : Key.SUBTRACT; + key(Type.DOWN, key); + sleep(ZOOM_SLEEP); + } + } +} diff --git a/java/mimis/src/main/java/mimis/application/cmd/windows/winamp/WinampApplication.java b/java/mimis/src/main/java/mimis/application/cmd/windows/winamp/WinampApplication.java new file mode 100644 index 0000000..975c352 --- /dev/null +++ b/java/mimis/src/main/java/mimis/application/cmd/windows/winamp/WinampApplication.java @@ -0,0 +1,181 @@ +package mimis.application.cmd.windows.winamp; + +import mimis.application.cmd.windows.WindowsApplication; +import mimis.exception.worker.DeactivateException; +import mimis.value.Action; +import mimis.value.Command; +import mimis.worker.Worker; + +public class WinampApplication extends WindowsApplication { + protected final static String PROGRAM = "winamp.exe"; + protected final static String TITLE = "Winamp"; + protected final static String WINDOW = "Winamp v1.x"; + + protected final static int STATUS_PLAYING = 1; + protected final static int STATUS_PAUSED = 3; + protected final static int STATUS_STOPPED = 0; + + protected final static int IPC_ISPLAYING = 104; + protected final static int IPC_GETOUTPUTTIME = 105; + protected final static int IPC_SETVOLUME = 122; + + protected final static int WINAMP_FILE_QUIT = 40001; + protected final static int WINAMP_FILE_REPEAT = 40022; + protected final static int WINAMP_FILE_SHUFFLE = 40023; + protected final static int WINAMP_BUTTON1 = 40044; + protected final static int WINAMP_BUTTON2 = 40045; + protected final static int WINAMP_BUTTON3 = 40046; + protected final static int WINAMP_BUTTON5 = 40048; + protected final static int WINAMP_VOLUMEUP = 40058; + protected final static int WINAMP_VOLUMEDOWN = 40059; + protected final static int WINAMP_FFWD5S = 40060; + protected final static int WINAMP_REW5S = 40061; + protected final static int WINAMP_BUTTON4_SHIFT = 40147; + protected final static int WINAMP_VISPLUGIN = 40192; + + protected static final int VOLUME_SLEEP = 50; + protected static final int SEEK_SLEEP = 100; + + protected VolumeWorker volumeWorker; + protected SeekWorker seekWorker; + protected double volume; + protected boolean muted; + + public WinampApplication() { + super(PROGRAM, TITLE, WINDOW); + volume = getVolume(); + muted = volume == 0; + volumeWorker = new VolumeWorker(); + seekWorker = new SeekWorker(); + } + + public void deactivate() throws DeactivateException { + super.deactivate(); + volumeWorker.stop(); + seekWorker.stop(); + } + + public void exit() { + super.exit(); + volumeWorker.exit(); + seekWorker.exit(); + } + + public void begin(Action action) { + log.trace("WinampApplication begin: " + action); + switch (action) { + case VOLUME_UP: + volumeWorker.start(1); + break; + case VOLUME_DOWN: + volumeWorker.start(-1); + break; + case FORWARD: + seekWorker.start(1); + break; + case REWIND: + seekWorker.start(-1); + break; + } + } + + public void end(Action action) { + log.trace("WinampApplication end: " + action); + switch (action) { + case PLAY: + log.debug("play"); + switch (user(0, IPC_ISPLAYING)) { + case STATUS_STOPPED: + command(WINAMP_BUTTON2); + break; + default: + command(WINAMP_BUTTON3); + break; + } + break; + case NEXT: + command(WINAMP_BUTTON5); + break; + case PREVIOUS: + command(WINAMP_BUTTON1); + break; + case FORWARD: + case REWIND: + seekWorker.stop(); + break; + case MUTE: + if (muted) { + setVolume(volume); + } else { + volume = getVolume(); + setVolume(0); + } + muted = !muted; + break; + case VOLUME_UP: + case VOLUME_DOWN: + volumeWorker.stop(); + break; + case SHUFFLE: + command(WINAMP_FILE_SHUFFLE); + break; + case REPEAT: + command(WINAMP_FILE_REPEAT); + break; + case FADEOUT: + command(WINAMP_BUTTON4_SHIFT); + break; + case QUIT: + command(WINAMP_FILE_QUIT); + break; + case VISUALISER: + system(Command.System.MAXIMIZE); + command(WINAMP_VISPLUGIN); + break; + } + } + + public double getVolume() { + return user(-666, IPC_SETVOLUME) / 255f; + } + + public void setVolume(double volume) { + user((int) Math.ceil(volume * 255), IPC_SETVOLUME); + } + + public int getDuration() { + return user(1, IPC_GETOUTPUTTIME); + } + + public int getElapsed() { + return user(0, IPC_GETOUTPUTTIME) / 1000; + } + + protected class VolumeWorker extends Worker { + protected int volumeChangeSign; + + public void start(int volumeChangeSign) { + super.start(); + this.volumeChangeSign = volumeChangeSign; + } + + public void work() { + command(volumeChangeSign > 0 ? WINAMP_VOLUMEUP : WINAMP_VOLUMEDOWN); + sleep(VOLUME_SLEEP); + } + }; + + protected class SeekWorker extends Worker { + protected int seekDirection; + + public void start(int seekDirection) { + super.start(); + this.seekDirection = seekDirection; + } + + public void work() { + command(seekDirection > 0 ? WINAMP_FFWD5S : WINAMP_REW5S); + sleep(SEEK_SLEEP); + } + }; +} diff --git a/java/mimis/src/main/java/mimis/application/cmd/windows/wmp/WMPApplication.java b/java/mimis/src/main/java/mimis/application/cmd/windows/wmp/WMPApplication.java new file mode 100644 index 0000000..484d830 --- /dev/null +++ b/java/mimis/src/main/java/mimis/application/cmd/windows/wmp/WMPApplication.java @@ -0,0 +1,86 @@ +package mimis.application.cmd.windows.wmp; + +import mimis.application.cmd.windows.WindowsApplication; +import mimis.value.Action; +import mimis.worker.Worker; + +public class WMPApplication extends WindowsApplication { + protected final static String PROGRAM = "wmplayer.exe"; + protected final static String TITLE = "Windows Media Player"; + protected final static String WINDOW = "WMPlayerApp"; + + protected static final int VOLUME_SLEEP = 120; + + protected VolumeWorker volumeWorker; + + public WMPApplication() { + super(PROGRAM, TITLE, WINDOW); + volumeWorker = new VolumeWorker(); + } + + public void begin(Action action) { + log.trace("WMPApplication begin: " + action); + switch (action) { + case PLAY: + command(18808); + break; + case NEXT: + command(18811); + break; + case PREVIOUS: + command(18810); + break; + case FORWARD: + command(18813); + break; + case REWIND: + command(18812); + break; + case MUTE: + command(18817); + break; + case VOLUME_UP: + volumeWorker.start(1); + break; + case VOLUME_DOWN: + volumeWorker.start(-1); + break; + case SHUFFLE: + command(18842); + break; + case REPEAT: + command(18843); + break; + } + } + + public void end(Action action) { + log.trace("WMPApplication end: " + action); + switch (action) { + case FORWARD: + command(18813); + break; + case REWIND: + command(18812); + break; + case VOLUME_UP: + case VOLUME_DOWN: + volumeWorker.stop(); + break; + } + } + + protected class VolumeWorker extends Worker { + protected int volumeChangeSign; + + public void start(int volumeChangeSign) { + super.start(); + this.volumeChangeSign = volumeChangeSign; + } + + public void work() { + command (volumeChangeSign > 0 ? 18815 : 18816); + sleep(VOLUME_SLEEP); + } + }; +} diff --git a/java/mimis/src/main/java/mimis/application/itunes/iTunesApplication.java b/java/mimis/src/main/java/mimis/application/itunes/iTunesApplication.java new file mode 100644 index 0000000..3b3de7f --- /dev/null +++ b/java/mimis/src/main/java/mimis/application/itunes/iTunesApplication.java @@ -0,0 +1,177 @@ +package mimis.application.itunes; + +import mimis.application.Application; +import mimis.exception.worker.ActivateException; +import mimis.exception.worker.DeactivateException; +import mimis.value.Action; +import mimis.worker.Component; +import mimis.worker.Worker; + +import com.dt.iTunesController.ITCOMDisabledReason; +import com.dt.iTunesController.ITTrack; +import com.dt.iTunesController.iTunes; +import com.dt.iTunesController.iTunesEventsInterface; + +public class iTunesApplication extends Component implements Application, iTunesEventsInterface { + protected static final String TITLE = "iTunes"; + protected static final boolean EVENTS = false; + + protected static final int VOLUME_CHANGE_RATE = 5; + protected static final int VOLUME_SLEEP = 100; + protected static final String PLAYLIST_LIKE = "Like"; + protected static final String PLAYLIST_DISLIKE = "Dislike"; + + protected iTunes iTunes; + protected VolumeWorker volumeWorker; + protected boolean events; + + public iTunesApplication() { + this(EVENTS); + } + + public iTunesApplication(boolean events) { + super(TITLE); + this.events = events; + volumeWorker = new VolumeWorker(); + } + + protected synchronized void activate() throws ActivateException { + iTunes = new iTunes(); + iTunes.connect(); + if (events) { + iTunes.addEventHandler(this); + } + super.activate(); + } + + public synchronized boolean active() { + try { + iTunes.getMute(); + active = true; + } catch (Exception e) { + active = false; + } + return active; + } + + protected synchronized void deactivate() throws DeactivateException { + if (events) { + exit(); + } else { + super.deactivate(); + volumeWorker.stop(); + try { + iTunes.release(); + } catch (Exception e) { + log.error(e); + throw new DeactivateException(); + } + } + } + + public synchronized void exit() { + try { + iTunes.quit(); + } catch (Exception e) {} + volumeWorker.exit(); + super.exit(); + } + + protected void begin(Action action) { + log.trace("iTunesApplication begin: " + action); + if (!active) return; + switch (action) { + case FORWARD: + iTunes.fastForward(); + break; + case REWIND: + iTunes.rewind(); + break; + case VOLUME_UP: + volumeWorker.start(VOLUME_CHANGE_RATE); + break; + case VOLUME_DOWN: + volumeWorker.start(-VOLUME_CHANGE_RATE); + break; + } + } + + protected void end(Action action) { + log.trace("iTunesApplication end: " + action); + if (!active) return; + switch (action) { + case PLAY: + iTunes.playPause(); + break; + case NEXT: + iTunes.nextTrack(); + break; + case PREVIOUS: + iTunes.previousTrack(); + break; + case FORWARD: + iTunes.resume(); + break; + case REWIND: + iTunes.resume(); + break; + case MUTE: + iTunes.toggleMute(); + break; + case VOLUME_UP: + case VOLUME_DOWN: + volumeWorker.stop(); + break; + case SHUFFLE: + iTunes.toggleShuffle(); + break; + case REPEAT: + iTunes.cycleSongRepeat(); + break; + case LIKE: + iTunes.playlistAddCurrentTrack(PLAYLIST_LIKE); + break; + case DISLIKE: + iTunes.playlistAddCurrentTrack(PLAYLIST_DISLIKE); + break; + } + } + + protected int getVolume() { + return iTunes.getSoundVolume(); + } + + public void onDatabaseChangedEvent(int[][] deletedObjectIDs, int[][] changedObjectIDs) {} + public void onPlayerPlayEvent(ITTrack iTrack) { + if (active) { + log.trace("iTunesEvent: play"); + } + } + + public void onPlayerStopEvent(ITTrack iTrack) { + if (active) { + log.trace("iTunesEvent: stop"); + } + } + + public void onPlayerPlayingTrackChangedEvent(ITTrack iTrack) {} + public void onCOMCallsDisabledEvent(ITCOMDisabledReason reason) {} + public void onCOMCallsEnabledEvent() {} + public void onQuittingEvent() {} + public void onAboutToPromptUserToQuitEvent() {} + public void onSoundVolumeChangedEvent(int newVolume) {} + + protected class VolumeWorker extends Worker { + protected int volumeChangeRate; + + public void start(int volumeChangeRate) { + super.start(); + this.volumeChangeRate = volumeChangeRate; + } + + public void work() { + iTunes.setSoundVolume(getVolume() + volumeChangeRate); + sleep(VOLUME_SLEEP); + } + }; +} \ No newline at end of file diff --git a/java/mimis/src/main/java/mimis/application/lirc/LircApplication.java b/java/mimis/src/main/java/mimis/application/lirc/LircApplication.java new file mode 100644 index 0000000..dd4d45e --- /dev/null +++ b/java/mimis/src/main/java/mimis/application/lirc/LircApplication.java @@ -0,0 +1,42 @@ +package mimis.application.lirc; + +import mimis.application.Application; +import mimis.device.lirc.LircButton; +import mimis.device.lirc.LircService; +import mimis.device.lirc.remote.WC02IPOButton; +import mimis.exception.worker.ActivateException; +import mimis.exception.worker.DeactivateException; +import mimis.worker.Component; + +public class LircApplication extends Component implements Application { + protected LircService lircService; + + public LircApplication(String title) { + super(title); + lircService = new LircService(); + lircService.put(WC02IPOButton.NAME, WC02IPOButton.values()); + } + + public void activate() throws ActivateException { + lircService.activate(); + super.activate(); + } + + public boolean active() { + return active = lircService.active(); + } + + protected void deactivate() throws DeactivateException { + super.deactivate(); + lircService.stop(); + } + + public void exit() { + super.exit(); + lircService.exit(); + } + + public void send(LircButton button) { + lircService.send(button); + } +} diff --git a/java/mimis/src/main/java/mimis/application/lirc/ipod/iPodApplication.java b/java/mimis/src/main/java/mimis/application/lirc/ipod/iPodApplication.java new file mode 100644 index 0000000..58b758f --- /dev/null +++ b/java/mimis/src/main/java/mimis/application/lirc/ipod/iPodApplication.java @@ -0,0 +1,86 @@ +package mimis.application.lirc.ipod; + +import mimis.application.lirc.LircApplication; +import mimis.device.lirc.remote.WC02IPOButton; +import mimis.exception.worker.ActivateException; +import mimis.exception.worker.DeactivateException; +import mimis.value.Action; +import mimis.worker.Worker; + +public class iPodApplication extends LircApplication { + protected static final String TITLE = "iPod"; + protected static final int VOLUME_SLEEP = 100; + + protected VolumeWorker volumeWorker; + + public iPodApplication() { + super(TITLE); + volumeWorker = new VolumeWorker(); + } + + protected void deactivate() throws DeactivateException { + super.deactivate(); + volumeWorker.stop(); + } + + public void exit() { + super.exit(); + volumeWorker.exit(); + } + + protected void begin(Action action) { + log.trace("iPodApplication begin: " + action); + if (!active) return; + switch (action) { + case VOLUME_UP: + try { + volumeWorker.activate(1); + } catch (ActivateException e) { + log.error(e); + } + break; + case VOLUME_DOWN: + try { + volumeWorker.activate(-1); + } catch (ActivateException e) { + log.error(e); + } + break; + } + } + + protected void end(Action action) { + log.trace("iPodApplication end: " + action); + if (!active) return; + switch (action) { + case PLAY: + send(WC02IPOButton.PLAY); + break; + case NEXT: + send(WC02IPOButton.NEXT); + break; + case PREVIOUS: + send(WC02IPOButton.PREVIOUS); + break; + case VOLUME_UP: + case VOLUME_DOWN: + volumeWorker.stop(); + break; + } + } + + protected class VolumeWorker extends Worker { + protected int volumeChangeRate; + + public void activate(int volumeChangeRate) throws ActivateException { + super.activate(); + this.volumeChangeRate = volumeChangeRate; + send(volumeChangeRate > 0 ? WC02IPOButton.PLUS : WC02IPOButton.MINUS); + } + + public void work() { + lircService.send(WC02IPOButton.HOLD); + sleep(VOLUME_SLEEP); + } + }; +} \ No newline at end of file diff --git a/java/mimis/src/main/java/mimis/application/mpc/MPCApplication.java b/java/mimis/src/main/java/mimis/application/mpc/MPCApplication.java new file mode 100644 index 0000000..be2b3c8 --- /dev/null +++ b/java/mimis/src/main/java/mimis/application/mpc/MPCApplication.java @@ -0,0 +1,102 @@ +package mimis.application.mpc; + +import mimis.application.cmd.windows.WindowsApplication; +import mimis.value.Action; +import mimis.worker.Worker; + +public class MPCApplication extends WindowsApplication { + protected final static String PROGRAM = "mpc-hc.exe"; + protected final static String TITLE = "Media Player Classic"; + protected final static String WINDOW = "MediaPlayerClassicW"; + + protected static final int VOLUME_SLEEP = 50; + protected static final int SEEK_SLEEP = 50; + + protected VolumeWorker volumeWorker; + protected SeekWorker seekWorker; + + public MPCApplication() { + super(PROGRAM, TITLE, WINDOW); + volumeWorker = new VolumeWorker(); + seekWorker = new SeekWorker(); + } + + public void begin(Action action) { + log.trace("MPCApplication: " + action); + switch (action) { + case FORWARD: + seekWorker.start(1); + break; + case REWIND: + seekWorker.start(-1); + break; + case VOLUME_UP: + volumeWorker.start(1); + break; + case VOLUME_DOWN: + volumeWorker.start(-1); + break; + } + } + + public void end(Action action) { + log.trace("MPCApplication: " + action); + switch (action) { + case PLAY: + command(889); + break; + case NEXT: + command(921); + break; + case PREVIOUS: + command(920); + break; + case FORWARD: + case REWIND: + seekWorker.stop(); + break; + case MUTE: + command(909); + break; + case VOLUME_UP: + case VOLUME_DOWN: + volumeWorker.stop(); + break; + case FULLSCREEN: + command(830); + break; + } + } + + public String getTitle() { + return TITLE; + } + + protected class VolumeWorker extends Worker { + protected int volumeChangeSign; + + public void start(int volumeChangeSign) { + super.start(); + this.volumeChangeSign = volumeChangeSign; + } + + public void work() { + command(volumeChangeSign > 0 ? 907 : 908); + sleep(VOLUME_SLEEP); + } + }; + + protected class SeekWorker extends Worker { + protected int seekDirection; + + public void start(int seekDirection) { + super.start(); + this.seekDirection = seekDirection; + } + + public void work() { + command(seekDirection > 0 ? 900 : 889); + sleep(SEEK_SLEEP); + } + }; +} diff --git a/java/mimis/src/main/java/mimis/application/robot/RobotApplication.java b/java/mimis/src/main/java/mimis/application/robot/RobotApplication.java new file mode 100644 index 0000000..5fa456b --- /dev/null +++ b/java/mimis/src/main/java/mimis/application/robot/RobotApplication.java @@ -0,0 +1,35 @@ +package mimis.application.robot; + +import java.awt.AWTException; +import java.awt.Robot; + +import mimis.exception.worker.ActivateException; +import mimis.value.Key; +import mimis.worker.Component; + +public class RobotApplication extends Component { + protected Robot robot; + + public void activate() throws ActivateException { + try { + robot = new Robot(); + robot.setAutoWaitForIdle(true); + } catch (AWTException e) { + log.error(e); + throw new ActivateException(); + } + super.activate(); + } + + public void press(Key key) { + robot.keyPress(key.getCode()); + } + + public void press(char key) { + robot.keyPress(key); + } + + public void release(Key key) { + robot.keyRelease(key.getCode()); + } +} diff --git a/java/mimis/src/main/java/mimis/application/vlc/VLCApplication.java b/java/mimis/src/main/java/mimis/application/vlc/VLCApplication.java new file mode 100644 index 0000000..e04c096 --- /dev/null +++ b/java/mimis/src/main/java/mimis/application/vlc/VLCApplication.java @@ -0,0 +1,198 @@ +package mimis.application.vlc; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import mimis.application.cmd.CMDApplication; +import mimis.exception.worker.ActivateException; +import mimis.exception.worker.DeactivateException; +import mimis.util.Native; +import mimis.value.Action; +import mimis.value.Amount; +import mimis.value.Registry; +import mimis.worker.Worker; + +public class VLCApplication extends CMDApplication { + protected final static Registry REGISTRY = Registry.CLASSES_ROOT; + protected final static String KEY = "Applications\\vlc.exe\\shell\\Open\\command"; + protected final static String PROGRAM = "vlc.exe"; + protected final static String TITLE = "VLC media player"; + + protected static final int POSTION_CHANGE_RATE = 1; + protected static final int VOLUME_CHANGE_RATE = 20; + + protected static final String HOST = "localhost"; + protected static final int PORT = 8080; + + protected static final int VOLUME_SLEEP = 100; + protected static final int SEEK_SLEEP = 100; + + protected VolumeWorker volumeWorker; + protected SeekWorker seekWorker; + + protected int volume = 255; + protected boolean muted = false; + + public VLCApplication() { + super(PROGRAM, TITLE); + volumeWorker = new VolumeWorker(); + seekWorker = new SeekWorker(); + } + + public String getPath() { + Pattern pattern = Pattern.compile("\"([^\"]+)\""); + Matcher matcher = pattern.matcher(Native.getValue(REGISTRY, KEY)); + return matcher.find() ? matcher.group(1) : null; + } + + public void command(String command) { + String request = String.format("http://%s:%d/requests/status.xml?command=%s", HOST, PORT, command); + try { + URL url = new URL(request); + HttpURLConnection httpUrlConnection = (HttpURLConnection) url.openConnection(); + int response = httpUrlConnection.getResponseCode(); + log.trace("Response: " + response); + } catch (MalformedURLException e) { + log.error(e); + } catch (IOException e) { + log.error(e); + } + } + + protected void deactivate() throws DeactivateException { + super.deactivate(); + volumeWorker.stop(); + seekWorker.stop(); + Native.terminate(program); + } + + public void exit() { + super.exit(); + volumeWorker.exit(); + seekWorker.exit(); + } + + public void begin(Action action) { + log.trace("VLCApplication begin: " + action); + try { + switch (action) { + case VOLUME_UP: + volumeWorker.activate("+"); + break; + case VOLUME_DOWN: + volumeWorker.activate("-"); + break; + case FORWARD: + seekWorker.start(Amount.SMALL, "+"); + break; + case REWIND: + seekWorker.start(Amount.SMALL, "-"); + break; + } + } catch (ActivateException e) { + log.error(e); + } + } + + public void end(Action action) { + log.trace("VLCApplication end: " + action); + switch (action) { + case PLAY: + command("pl_pause"); + break; + case PAUSE: + command("pl_pause"); + break; + case NEXT: + command("pl_next"); + break; + case PREVIOUS: + command("pl_previous"); + break; + case FORWARD: + case REWIND: + seekWorker.stop(); + break; + case MUTE: + command("volume&val=" + toggleMute()); + break; + case VOLUME_UP: + case VOLUME_DOWN: + volumeWorker.stop(); + break; + case SHUFFLE: + command("command=pl_random"); + break; + case REPEAT: + command("command=pl_repeat"); + break; + } + } + + protected void volumeUp() { + if (!muted) { + volume += VOLUME_CHANGE_RATE; + command("volume&val=+" + VOLUME_CHANGE_RATE); + } + } + + protected void volumeDown() { + if (!muted) { + volume -= VOLUME_CHANGE_RATE; + command("volume&val=-" + VOLUME_CHANGE_RATE); + } + } + + protected int toggleMute() { + return (muted = !muted) ? 0 : volume; + } + + public String getTitle() { + return TITLE; + } + + protected class VolumeWorker extends Worker { + protected String volumeChangeSign; + + public void activate(String volumeChangeSign) throws ActivateException { + super.activate(); + this.volumeChangeSign = volumeChangeSign; + } + + public void work() { + volume += VOLUME_CHANGE_RATE; + command("volume&val=" + volumeChangeSign + VOLUME_CHANGE_RATE); + sleep(VOLUME_SLEEP); + } + }; + + protected class SeekWorker extends Worker { + protected Amount amount; + protected String seekDirection; + + public void start(Amount amount, String seekDirection) { + super.start(); + this.amount = amount; + this.seekDirection = seekDirection; + } + + public void work() { + switch (amount) { + case SMALL: + command("command=seek&val=" + seekDirection + POSTION_CHANGE_RATE); + break; + case MEDIUM: + command("command=seek&val=" + seekDirection + POSTION_CHANGE_RATE * 2); + break; + case LARGE: + command("command=seek&val=" + seekDirection + POSTION_CHANGE_RATE * 3); + break; + } + sleep(SEEK_SLEEP); + } + }; +} diff --git a/java/mimis/src/main/java/mimis/device/Device.java b/java/mimis/src/main/java/mimis/device/Device.java new file mode 100644 index 0000000..4f0cffd --- /dev/null +++ b/java/mimis/src/main/java/mimis/device/Device.java @@ -0,0 +1,5 @@ +package mimis.device; + +public interface Device { + +} diff --git a/java/mimis/src/main/java/mimis/device/javainput/DirectionButton.java b/java/mimis/src/main/java/mimis/device/javainput/DirectionButton.java new file mode 100644 index 0000000..7cf7916 --- /dev/null +++ b/java/mimis/src/main/java/mimis/device/javainput/DirectionButton.java @@ -0,0 +1,39 @@ +package mimis.device.javainput; + +import mimis.input.Button; +import mimis.exception.button.UnknownDirectionException; +import de.hardcode.jxinput.event.JXInputDirectionalEvent; + +public enum DirectionButton implements Button { + NORTH (0), + NORTHEAST (45), + EAST (90), + SOUTHEAST (135), + SOUTH (180), + SOUTHWEST (225), + WEST (270), + NORTHWEST (315); + + protected int code; + + private DirectionButton(int code) { + this.code = code; + } + + public int getCode() { + return code; + } + + public static DirectionButton create(int angle) throws UnknownDirectionException { + for (DirectionButton button : DirectionButton.values()) { + if (button.getCode() == angle) { + return button; + } + } + throw new UnknownDirectionException(); + } + + public static DirectionButton create(JXInputDirectionalEvent event) throws UnknownDirectionException { + return create(event.getDirectional().getDirection() / 100); + } +} diff --git a/java/mimis/src/main/java/mimis/device/javainput/JavaInputDevice.java b/java/mimis/src/main/java/mimis/device/javainput/JavaInputDevice.java new file mode 100644 index 0000000..8798ac8 --- /dev/null +++ b/java/mimis/src/main/java/mimis/device/javainput/JavaInputDevice.java @@ -0,0 +1,85 @@ +package mimis.device.javainput; + +import mimis.device.Device; +import mimis.exception.ButtonException; +import mimis.exception.button.UnknownButtonException; +import mimis.exception.button.UnknownDirectionException; +import mimis.exception.device.DeviceNotFoundException; +import mimis.exception.worker.ActivateException; +import mimis.exception.worker.DeactivateException; +import mimis.input.Button; +import mimis.input.state.Press; +import mimis.input.state.Release; +import mimis.worker.Component; +import de.hardcode.jxinput.JXInputDevice; +import de.hardcode.jxinput.JXInputManager; +import de.hardcode.jxinput.event.JXInputAxisEvent; +import de.hardcode.jxinput.event.JXInputButtonEvent; +import de.hardcode.jxinput.event.JXInputDirectionalEvent; + +public abstract class JavaInputDevice extends Component implements Device { + protected String name; + + public JavaInputDevice(String title, String name) { + super(title); + this.name = name; + } + + protected JavaInputListener javaInputListener; + protected Button previousDirectionalButton; + + protected void activate() throws ActivateException { + super.activate(); + try { + JXInputDevice jxinputDevice = getDevice(name); + log.debug(jxinputDevice); + javaInputListener = new JavaInputListener(this, jxinputDevice); + } catch (DeviceNotFoundException e) { + active = false; + throw new ActivateException(); + } + javaInputListener.start(); + } + + protected void deactivate() throws DeactivateException { + super.deactivate(); + javaInputListener.stop(); + } + + public void processEvent(JXInputAxisEvent event) {} + + public void processEvent(JXInputButtonEvent event) throws ButtonException { + Button button = getButton(event); + if (event.getButton().getState()) { + route(new Press(button)); + } else { + route(new Release(button)); + } + } + + public void processEvent(JXInputDirectionalEvent event) throws UnknownDirectionException { + Button button = getButton(event); + if (event.getDirectional().isCentered()) { + if (previousDirectionalButton != null) { + route(new Release(previousDirectionalButton)); + } + } else { + route(new Press(button)); + previousDirectionalButton = button; + } + } + + protected abstract Button getButton(JXInputButtonEvent event) throws UnknownButtonException; + protected abstract Button getButton(JXInputDirectionalEvent event) throws UnknownDirectionException; + + public static JXInputDevice getDevice(String name) throws DeviceNotFoundException { + int numberOfDevices = JXInputManager.getNumberOfDevices(); + for (int i = 0; i < numberOfDevices; ++i) { + JXInputDevice device = JXInputManager.getJXInputDevice(i); + if (device.getName().startsWith(name)) { + return device; + } + } + throw new DeviceNotFoundException(); + } +} diff --git a/java/mimis/src/main/java/mimis/device/javainput/JavaInputListener.java b/java/mimis/src/main/java/mimis/device/javainput/JavaInputListener.java new file mode 100644 index 0000000..e771cd4 --- /dev/null +++ b/java/mimis/src/main/java/mimis/device/javainput/JavaInputListener.java @@ -0,0 +1,85 @@ +package mimis.device.javainput; + +import java.util.LinkedList; +import java.util.Queue; + +import mimis.exception.ButtonException; +import mimis.worker.Worker; +import de.hardcode.jxinput.Button; +import de.hardcode.jxinput.Directional; +import de.hardcode.jxinput.JXInputDevice; +import de.hardcode.jxinput.JXInputManager; +import de.hardcode.jxinput.event.JXInputAxisEvent; +import de.hardcode.jxinput.event.JXInputAxisEventListener; +import de.hardcode.jxinput.event.JXInputButtonEvent; +import de.hardcode.jxinput.event.JXInputButtonEventListener; +import de.hardcode.jxinput.event.JXInputDirectionalEvent; +import de.hardcode.jxinput.event.JXInputDirectionalEventListener; +import de.hardcode.jxinput.event.JXInputEventManager; + +public class JavaInputListener extends Worker implements Runnable, JXInputAxisEventListener, JXInputButtonEventListener, JXInputDirectionalEventListener { + protected JavaInputDevice javaInputDevice; + protected JXInputDevice jxinputDevice; + protected Queue axisEventQueue; + protected Queue buttonEventQueue; + protected Queue directionalEventQueue; + + public JavaInputListener(JavaInputDevice javaInputDevice, JXInputDevice jxinputDevice) { + this.javaInputDevice = javaInputDevice; + this.jxinputDevice = jxinputDevice; + axisEventQueue = new LinkedList(); + buttonEventQueue = new LinkedList(); + directionalEventQueue = new LinkedList(); + addListeners(); + } + + protected void addListeners() { + /*for (int i = 0; i < jxinputDevice.getMaxNumberOfAxes(); ++i) { + Axis axis = jxinputDevice.getAxis(i); + if (axis != null) { + JXInputEventManager.addListener(this, axis); + } + }*/ + for (int i = 0; i < jxinputDevice.getMaxNumberOfButtons(); ++i) { + Button button = jxinputDevice.getButton(i); + if (button != null) { + JXInputEventManager.addListener(this, button); + } + } + for (int i = 0; i < jxinputDevice.getMaxNumberOfDirectionals(); ++i) { + Directional directional = jxinputDevice.getDirectional(i); + if (directional != null) { + JXInputEventManager.addListener(this, directional); + } + } + } + + public void changed(JXInputAxisEvent event) { + axisEventQueue.add(event); + } + + public void changed(JXInputButtonEvent event) { + buttonEventQueue.add(event); + } + + public void changed(JXInputDirectionalEvent event) { + directionalEventQueue.add(event); + } + + public void work() { + JXInputManager.updateFeatures(); + if (!axisEventQueue.isEmpty()) { + javaInputDevice.processEvent(axisEventQueue.poll()); + } else if (!buttonEventQueue.isEmpty()) { + try { + javaInputDevice.processEvent(buttonEventQueue.poll()); + } catch (ButtonException e) {} + } else if (!directionalEventQueue.isEmpty()) { + try { + javaInputDevice.processEvent(directionalEventQueue.poll()); + } catch (ButtonException e) {} + } else { + sleep(); + } + } +} diff --git a/java/mimis/src/main/java/mimis/device/javainput/extreme3d/Extreme3DButton.java b/java/mimis/src/main/java/mimis/device/javainput/extreme3d/Extreme3DButton.java new file mode 100644 index 0000000..90a5d7f --- /dev/null +++ b/java/mimis/src/main/java/mimis/device/javainput/extreme3d/Extreme3DButton.java @@ -0,0 +1,43 @@ +package mimis.device.javainput.extreme3d; + +import mimis.exception.button.UnknownButtonException; +import mimis.input.Button; +import de.hardcode.jxinput.event.JXInputButtonEvent; + +public enum Extreme3DButton implements Button { + ONE ("Button 0"), + TWO ("Button 1"), + THREE ("Button 2"), + FOUR ("Button 3"), + FIVE ("Button 4"), + SIX ("Button 5"), + SEVEN ("Button 6"), + EIGHT ("Button 7"), + NINE ("Button 8"), + TEN ("Button 9"), + ELEVEN ("Button 10"), + TWELVE ("Button 11"); + + protected String code; + + private Extreme3DButton(String code) { + this.code = code; + } + + public String getCode() { + return code; + } + + public static Extreme3DButton create(String code) throws UnknownButtonException { + for (Extreme3DButton button : Extreme3DButton.values()) { + if (button.getCode().equals(code)) { + return button; + } + } + throw new UnknownButtonException(); + } + + public static Extreme3DButton create(JXInputButtonEvent event) throws UnknownButtonException { + return create(event.getButton().getName()); + } +} \ No newline at end of file diff --git a/java/mimis/src/main/java/mimis/device/javainput/extreme3d/Extreme3DDevice.java b/java/mimis/src/main/java/mimis/device/javainput/extreme3d/Extreme3DDevice.java new file mode 100644 index 0000000..d0654a4 --- /dev/null +++ b/java/mimis/src/main/java/mimis/device/javainput/extreme3d/Extreme3DDevice.java @@ -0,0 +1,38 @@ +package mimis.device.javainput.extreme3d; + +import mimis.device.javainput.DirectionButton; +import mimis.device.javainput.JavaInputDevice; +import mimis.exception.button.UnknownButtonException; +import mimis.exception.button.UnknownDirectionException; +import mimis.exception.worker.ActivateException; +import mimis.input.Button; +import mimis.value.Action; +import de.hardcode.jxinput.event.JXInputButtonEvent; +import de.hardcode.jxinput.event.JXInputDirectionalEvent; + +public class Extreme3DDevice extends JavaInputDevice { + protected static final String TITLE = "Extreme 3D"; + protected static final String NAME = "Logitech Extreme 3D"; + + protected static Extreme3DTaskMapCycle taskMapCycle; + + public Extreme3DDevice() { + super(TITLE, NAME); + taskMapCycle = new Extreme3DTaskMapCycle(); + } + + protected void activate() throws ActivateException { + super.activate(); + parser(Action.ADD, taskMapCycle.mimis); + parser(Action.ADD, taskMapCycle.player); + parser(Action.ADD, taskMapCycle.like); + } + + protected Button getButton(JXInputButtonEvent event) throws UnknownButtonException { + return Extreme3DButton.create(event); + } + + protected Button getButton(JXInputDirectionalEvent event) throws UnknownDirectionException { + return DirectionButton.create(event); + } +} diff --git a/java/mimis/src/main/java/mimis/device/javainput/extreme3d/Extreme3DTaskMapCycle.java b/java/mimis/src/main/java/mimis/device/javainput/extreme3d/Extreme3DTaskMapCycle.java new file mode 100644 index 0000000..8e0eb54 --- /dev/null +++ b/java/mimis/src/main/java/mimis/device/javainput/extreme3d/Extreme3DTaskMapCycle.java @@ -0,0 +1,70 @@ +package mimis.device.javainput.extreme3d; + +import mimis.device.javainput.DirectionButton; +import mimis.input.Task; +import mimis.input.state.Press; +import mimis.state.TaskMap; +import mimis.state.TaskMapCycle; +import mimis.value.Action; +import mimis.value.Target; + +public class Extreme3DTaskMapCycle extends TaskMapCycle { + protected static final long serialVersionUID = 1L; + + public TaskMap mimis, player, like; + + public Extreme3DTaskMapCycle() { + /* Mimis */ + mimis = new TaskMap(); + mimis.add( + new Press(Extreme3DButton.SEVEN), + new Task(Action.PREVIOUS, Target.MAIN)); + mimis.add( + new Press(Extreme3DButton.EIGHT), + new Task(Action.NEXT, Target.MAIN)); + add(mimis); + + /* Player */ + player = new TaskMap(); + player.add( + new Press(Extreme3DButton.ONE), + new Task(Action.PLAY, Target.CURRENT)); + player.add( + new Press(Extreme3DButton.TWO), + new Task(Action.MUTE, Target.CURRENT)); + player.add( + new Press(Extreme3DButton.NINE), + new Task(Action.SHUFFLE, Target.CURRENT)); + player.add( + new Press(Extreme3DButton.TEN), + new Task(Action.REPEAT, Target.CURRENT)); + player.add( + new Press(Extreme3DButton.SIX), + new Task(Action.NEXT, Target.CURRENT)); + player.add( + new Press(Extreme3DButton.FOUR), + new Task(Action.PREVIOUS, Target.CURRENT)); + player.add( + new Press(Extreme3DButton.FIVE), + new Task(Action.FORWARD, Target.CURRENT)); + player.add( + new Press(Extreme3DButton.THREE), + new Task(Action.REWIND, Target.CURRENT)); + player.add( + new Press(DirectionButton.SOUTH), + new Task(Action.VOLUME_DOWN, Target.CURRENT)); + player.add( + new Press(DirectionButton.NORTH), + new Task(Action.VOLUME_UP, Target.CURRENT)); + add(player); + + like = new TaskMap(); + like.add( + new Press(Extreme3DButton.ELEVEN), + new Task(Action.LIKE, Target.CURRENT)); + like.add( + new Press(Extreme3DButton.TWELVE), + new Task(Action.DISLIKE, Target.CURRENT)); + add(like); + } +} diff --git a/java/mimis/src/main/java/mimis/device/javainput/rumblepad/RumblepadButton.java b/java/mimis/src/main/java/mimis/device/javainput/rumblepad/RumblepadButton.java new file mode 100644 index 0000000..65d8851 --- /dev/null +++ b/java/mimis/src/main/java/mimis/device/javainput/rumblepad/RumblepadButton.java @@ -0,0 +1,41 @@ +package mimis.device.javainput.rumblepad; + +import mimis.exception.button.UnknownButtonException; +import mimis.input.Button; +import de.hardcode.jxinput.event.JXInputButtonEvent; + +public enum RumblepadButton implements Button { + ONE ("Button 0"), + TWO ("Button 1"), + THREE ("Button 2"), + FOUR ("Button 3"), + FIVE ("Button 4"), + SIX ("Button 5"), + SEVEN ("Button 6"), + EIGHT ("Button 7"), + NINE ("Button 8"), + TEN ("Button 9"); + + protected String code; + + private RumblepadButton(String code) { + this.code = code; + } + + public String getCode() { + return code; + } + + public static RumblepadButton create(String code) throws UnknownButtonException { + for (RumblepadButton button : RumblepadButton.values()) { + if (button.getCode().equals(code)) { + return button; + } + } + throw new UnknownButtonException(); + } + + public static RumblepadButton create(JXInputButtonEvent event) throws UnknownButtonException { + return create(event.getButton().getName()); + } +} \ No newline at end of file diff --git a/java/mimis/src/main/java/mimis/device/javainput/rumblepad/RumblepadDevice.java b/java/mimis/src/main/java/mimis/device/javainput/rumblepad/RumblepadDevice.java new file mode 100644 index 0000000..5d03046 --- /dev/null +++ b/java/mimis/src/main/java/mimis/device/javainput/rumblepad/RumblepadDevice.java @@ -0,0 +1,38 @@ +package mimis.device.javainput.rumblepad; + +import mimis.device.javainput.DirectionButton; +import mimis.device.javainput.JavaInputDevice; +import mimis.exception.button.UnknownButtonException; +import mimis.exception.button.UnknownDirectionException; +import mimis.exception.worker.ActivateException; +import mimis.input.Button; +import mimis.value.Action; +import de.hardcode.jxinput.event.JXInputButtonEvent; +import de.hardcode.jxinput.event.JXInputDirectionalEvent; + +public class RumblepadDevice extends JavaInputDevice { + protected static final String TITLE = "RumblePad"; + protected static final String NAME = "Logitech RumblePad 2 USB"; + + protected static RumblepadTaskMapCycle taskMapCycle; + + public RumblepadDevice() { + super(TITLE, NAME); + taskMapCycle = new RumblepadTaskMapCycle(); + } + + protected void activate() throws ActivateException { + super.activate(); + parser(Action.ADD, taskMapCycle.mimis); + parser(Action.ADD, taskMapCycle.player); + parser(Action.ADD, taskMapCycle.like); + } + + protected Button getButton(JXInputButtonEvent event) throws UnknownButtonException { + return RumblepadButton.create(event); + } + + protected Button getButton(JXInputDirectionalEvent event) throws UnknownDirectionException { + return DirectionButton.create(event); + } +} diff --git a/java/mimis/src/main/java/mimis/device/javainput/rumblepad/RumblepadTaskMapCycle.java b/java/mimis/src/main/java/mimis/device/javainput/rumblepad/RumblepadTaskMapCycle.java new file mode 100644 index 0000000..a66f244 --- /dev/null +++ b/java/mimis/src/main/java/mimis/device/javainput/rumblepad/RumblepadTaskMapCycle.java @@ -0,0 +1,70 @@ +package mimis.device.javainput.rumblepad; + +import mimis.device.javainput.DirectionButton; +import mimis.input.Task; +import mimis.input.state.Press; +import mimis.state.TaskMap; +import mimis.state.TaskMapCycle; +import mimis.value.Action; +import mimis.value.Target; + +public class RumblepadTaskMapCycle extends TaskMapCycle { + protected static final long serialVersionUID = 1L; + + public TaskMap mimis, player, like; + + public RumblepadTaskMapCycle() { + /* Mimis */ + mimis = new TaskMap(); + mimis.add( + new Press(RumblepadButton.ONE), + new Task(Action.PREVIOUS, Target.MAIN)); + mimis.add( + new Press(RumblepadButton.THREE), + new Task(Action.NEXT, Target.MAIN)); + add(mimis); + + /* Player */ + player = new TaskMap(); + player.add( + new Press(DirectionButton.WEST), + new Task(Action.PLAY, Target.CURRENT)); + player.add( + new Press(DirectionButton.EAST), + new Task(Action.MUTE, Target.CURRENT)); + player.add( + new Press(RumblepadButton.NINE), + new Task(Action.SHUFFLE, Target.CURRENT)); + player.add( + new Press(RumblepadButton.TEN), + new Task(Action.REPEAT, Target.CURRENT)); + player.add( + new Press(RumblepadButton.EIGHT), + new Task(Action.NEXT, Target.CURRENT)); + player.add( + new Press(RumblepadButton.SIX), + new Task(Action.PREVIOUS, Target.CURRENT)); + player.add( + new Press(RumblepadButton.SEVEN), + new Task(Action.FORWARD, Target.CURRENT)); + player.add( + new Press(RumblepadButton.FIVE), + new Task(Action.REWIND, Target.CURRENT)); + player.add( + new Press(DirectionButton.SOUTH), + new Task(Action.VOLUME_DOWN, Target.CURRENT)); + player.add( + new Press(DirectionButton.NORTH), + new Task(Action.VOLUME_UP, Target.CURRENT)); + add(player); + + like = new TaskMap(); + like.add( + new Press(RumblepadButton.FOUR), + new Task(Action.LIKE, Target.CURRENT)); + like.add( + new Press(RumblepadButton.TWO), + new Task(Action.DISLIKE, Target.CURRENT)); + add(like); + } +} diff --git a/java/mimis/src/main/java/mimis/device/jintellitype/CommandButton.java b/java/mimis/src/main/java/mimis/device/jintellitype/CommandButton.java new file mode 100644 index 0000000..734de34 --- /dev/null +++ b/java/mimis/src/main/java/mimis/device/jintellitype/CommandButton.java @@ -0,0 +1,74 @@ +package mimis.device.jintellitype; + +import mimis.exception.button.UnknownButtonException; +import mimis.input.Button; + +import com.melloware.jintellitype.JIntellitype; + + +public enum CommandButton implements Button { + BROWSER_BACKWARD (JIntellitype.APPCOMMAND_BROWSER_BACKWARD), + BROWSER_FORWARD (JIntellitype.APPCOMMAND_BROWSER_FORWARD), + BROWSER_REFRESH (JIntellitype.APPCOMMAND_BROWSER_REFRESH), + BROWSER_STOP (JIntellitype.APPCOMMAND_BROWSER_STOP), + BROWSER_SEARCH (JIntellitype.APPCOMMAND_BROWSER_SEARCH), + BROWSER_FAVOURITES (JIntellitype.APPCOMMAND_BROWSER_FAVOURITES), + BROWSER_HOME (JIntellitype.APPCOMMAND_BROWSER_HOME), + VOLUME_MUTE (JIntellitype.APPCOMMAND_VOLUME_MUTE), + VOLUME_DOWN (JIntellitype.APPCOMMAND_VOLUME_DOWN), + VOLUME_UP (JIntellitype.APPCOMMAND_VOLUME_UP), + MEDIA_NEXTTRACK (JIntellitype.APPCOMMAND_MEDIA_NEXTTRACK), + MEDIA_PREVIOUSTRACK (JIntellitype.APPCOMMAND_MEDIA_PREVIOUSTRACK), + MEDIA_STOP (JIntellitype.APPCOMMAND_MEDIA_STOP), + MEDIA_PLAY_PAUSE (JIntellitype.APPCOMMAND_MEDIA_PLAY_PAUSE), + LAUNCH_MAIL (JIntellitype.APPCOMMAND_LAUNCH_MAIL), + LAUNCH_MEDIA_SELECT (JIntellitype.APPCOMMAND_LAUNCH_MEDIA_SELECT), + LAUNCH_APP1 (JIntellitype.APPCOMMAND_LAUNCH_APP1), + LAUNCH_APP2 (JIntellitype.APPCOMMAND_LAUNCH_APP2), + BASS_DOWN (JIntellitype.APPCOMMAND_BASS_DOWN), + BASS_BOOST (JIntellitype.APPCOMMAND_BASS_BOOST), + BASS_UP (JIntellitype.APPCOMMAND_BASS_UP), + TREBLE_DOWN (JIntellitype.APPCOMMAND_TREBLE_DOWN), + TREBLE_UP (JIntellitype.APPCOMMAND_TREBLE_UP), + MICROPHONE_VOLUME_MUTE (JIntellitype.APPCOMMAND_MICROPHONE_VOLUME_MUTE), + MICROPHONE_VOLUME_DOWN (JIntellitype.APPCOMMAND_MICROPHONE_VOLUME_DOWN), + MICROPHONE_VOLUME_UP (JIntellitype.APPCOMMAND_MICROPHONE_VOLUME_UP), + HELP (JIntellitype.APPCOMMAND_HELP), + FIND (JIntellitype.APPCOMMAND_FIND), + NEW (JIntellitype.APPCOMMAND_NEW), + OPEN (JIntellitype.APPCOMMAND_OPEN), + CLOSE (JIntellitype.APPCOMMAND_CLOSE), + SAVE (JIntellitype.APPCOMMAND_SAVE), + PRINT (JIntellitype.APPCOMMAND_PRINT), + UNDO (JIntellitype.APPCOMMAND_UNDO), + REDO (JIntellitype.APPCOMMAND_REDO), + COPY (JIntellitype.APPCOMMAND_COPY), + CUT (JIntellitype.APPCOMMAND_CUT), + PASTE (JIntellitype.APPCOMMAND_PASTE), + REPLY_TO_MAIL (JIntellitype.APPCOMMAND_REPLY_TO_MAIL), + FORWARD_MAIL (JIntellitype.APPCOMMAND_FORWARD_MAIL), + SEND_MAIL (JIntellitype.APPCOMMAND_SEND_MAIL), + SPELL_CHECK (JIntellitype.APPCOMMAND_SPELL_CHECK), + DICTATE_OR_COMMAND_CONTROL_TOGGLE (JIntellitype.APPCOMMAND_DICTATE_OR_COMMAND_CONTROL_TOGGLE), + MIC_ON_OFF_TOGGLE (JIntellitype.APPCOMMAND_MIC_ON_OFF_TOGGLE), + CORRECTION_LIST (JIntellitype.APPCOMMAND_CORRECTION_LIST); + + protected int code; + + private CommandButton(int code) { + this.code = code; + } + + public int getCode() { + return code; + } + + public static CommandButton create(int code) throws UnknownButtonException { + for (CommandButton button : CommandButton.values()) { + if (button.getCode() == code) { + return button; + } + } + throw new UnknownButtonException(); + } +} diff --git a/java/mimis/src/main/java/mimis/device/jintellitype/Hotkey.java b/java/mimis/src/main/java/mimis/device/jintellitype/Hotkey.java new file mode 100644 index 0000000..08846c5 --- /dev/null +++ b/java/mimis/src/main/java/mimis/device/jintellitype/Hotkey.java @@ -0,0 +1,46 @@ +package mimis.device.jintellitype; + +import java.util.ArrayList; + +import mimis.input.Button; +import mimis.value.Key; + +import com.melloware.jintellitype.JIntellitype; + +public class Hotkey implements Button { + protected static final long serialVersionUID = 1L; + + protected static ArrayList hotkeyList; + protected static JIntellitype jit; + + public Hotkey(int modifier, int keycode) { + int id = hotkeyList.size(); + jit.registerHotKey(id, modifier, keycode); + hotkeyList.add(this); + } + + public Hotkey(int modifier, char character) { + this(modifier, (int) Character.toUpperCase(character)); + } + + public Hotkey(char character) { + this(0, (int) Character.toUpperCase(character)); + } + + public Hotkey(int keycode) { + this(0, keycode); + } + + public Hotkey(Key key) { + this(key.getCode()); + } + + public Hotkey(int modifier, Key key) { + this(modifier, key.getCode()); + } + + public static void initialise(ArrayList actionList, JIntellitype jit) { + Hotkey.hotkeyList = actionList; + Hotkey.jit = jit; + } +} diff --git a/java/mimis/src/main/java/mimis/device/jintellitype/JIntellitypeDevice.java b/java/mimis/src/main/java/mimis/device/jintellitype/JIntellitypeDevice.java new file mode 100644 index 0000000..92ae185 --- /dev/null +++ b/java/mimis/src/main/java/mimis/device/jintellitype/JIntellitypeDevice.java @@ -0,0 +1,71 @@ +package mimis.device.jintellitype; + +import java.util.ArrayList; + +import mimis.device.Device; +import mimis.exception.button.UnknownButtonException; +import mimis.exception.worker.ActivateException; +import mimis.exception.worker.DeactivateException; +import mimis.input.state.Press; +import mimis.input.state.Release; +import mimis.value.Action; +import mimis.worker.Component; + +import com.melloware.jintellitype.HotkeyListener; +import com.melloware.jintellitype.IntellitypeListener; +import com.melloware.jintellitype.JIntellitype; + +public class JIntellitypeDevice extends Component implements Device, HotkeyListener, IntellitypeListener { + protected static final String TITLE = "Keyboard"; + + protected JIntellitypeTaskMapCycle taskMapCycle; + protected ArrayList hotkeyList; + protected JIntellitype jit; + + public JIntellitypeDevice() { + super(TITLE); + hotkeyList = new ArrayList(); + jit = JIntellitype.getInstance(); + Hotkey.initialise(hotkeyList, jit); + taskMapCycle = new JIntellitypeTaskMapCycle(); + } + + protected void activate() throws ActivateException { + super.activate(); + jit.addHotKeyListener(this); + jit.addIntellitypeListener(this); + parser(Action.ADD, taskMapCycle.mimis); + parser(Action.ADD, taskMapCycle.player); + } + + public void onIntellitype(int command) { + if (active) { + try { + CommandButton commandButton = CommandButton.create(command); + route(new Press(commandButton)); + route(new Release(commandButton)); + } catch (UnknownButtonException e) { + log.error(e); + } + } + } + + public void onHotKey(int id) { + if (active) { + Hotkey hotkey = hotkeyList.get(id); + route(new Press(hotkey)); + route(new Release(hotkey)); + } + } + + protected void deactivate() throws DeactivateException { + super.deactivate(); + jit.removeHotKeyListener(this); + jit.removeIntellitypeListener(this); + } + + public void exit() { + super.exit(); + jit.cleanUp(); + } +} diff --git a/java/mimis/src/main/java/mimis/device/jintellitype/JIntellitypeTaskMapCycle.java b/java/mimis/src/main/java/mimis/device/jintellitype/JIntellitypeTaskMapCycle.java new file mode 100644 index 0000000..ac30c74 --- /dev/null +++ b/java/mimis/src/main/java/mimis/device/jintellitype/JIntellitypeTaskMapCycle.java @@ -0,0 +1,45 @@ +package mimis.device.jintellitype; + +import mimis.input.Task; +import mimis.state.TaskMap; +import mimis.state.TaskMapCycle; +import mimis.value.Action; +import mimis.value.Key; +import mimis.value.Target; + +public class JIntellitypeTaskMapCycle extends TaskMapCycle { + protected static final long serialVersionUID = 1L; + + public TaskMap mimis, player; + + public JIntellitypeTaskMapCycle() { + /* Mimis */ + mimis = new TaskMap(); + mimis.add( + new Hotkey(Key.PRIOR), + new Task(Action.PREVIOUS, Target.MAIN)); + mimis.add( + new Hotkey(Key.NEXT), + new Task(Action.NEXT, Target.MAIN)); + add(mimis); + + /* Player */ + player = new TaskMap(); + player.add( + CommandButton.VOLUME_DOWN, + new Task(Action.VOLUME_DOWN, Target.APPLICATIONS)); + player.add( + CommandButton.VOLUME_UP, + new Task(Action.VOLUME_UP, Target.APPLICATIONS)); + player.add( + new Hotkey(Modifier.CTRL | Modifier.WIN, 'x'), + new Task(Action.EXIT, Target.MAIN)); + player.add( + new Hotkey(Modifier.CTRL | Modifier.SHIFT | Modifier.WIN, 'n'), + new Task(Action.NEXT, Target.CURRENT)); + player.add( + new Hotkey(Modifier.CTRL | Modifier.SHIFT | Modifier.WIN, 'p'), + new Task(Action.PREVIOUS, Target.CURRENT)); + add(player); + } +} diff --git a/java/mimis/src/main/java/mimis/device/jintellitype/Modifier.java b/java/mimis/src/main/java/mimis/device/jintellitype/Modifier.java new file mode 100644 index 0000000..ca64f51 --- /dev/null +++ b/java/mimis/src/main/java/mimis/device/jintellitype/Modifier.java @@ -0,0 +1,25 @@ +package mimis.device.jintellitype; + +import mimis.input.Button; + +import com.melloware.jintellitype.JIntellitype; + +public class Modifier implements Button { + protected static final long serialVersionUID = 1L; + + public static final int + ALT = JIntellitype.MOD_ALT, + CTRL = JIntellitype.MOD_CONTROL, + SHIFT = JIntellitype.MOD_SHIFT, + WIN = JIntellitype.MOD_WIN; + + protected int code; + + protected Modifier(int code) { + this.code = code; + } + + public int getCode() { + return code; + } +} diff --git a/java/mimis/src/main/java/mimis/device/lirc/LircButton.java b/java/mimis/src/main/java/mimis/device/lirc/LircButton.java new file mode 100644 index 0000000..5e18d4f --- /dev/null +++ b/java/mimis/src/main/java/mimis/device/lirc/LircButton.java @@ -0,0 +1,10 @@ +package mimis.device.lirc; + +import mimis.input.Button; + +public interface LircButton extends Button { + public static final String NAME = null; + + public String getCode(); + public String getName(); +} diff --git a/java/mimis/src/main/java/mimis/device/lirc/LircButtonListener.java b/java/mimis/src/main/java/mimis/device/lirc/LircButtonListener.java new file mode 100644 index 0000000..3927f7e --- /dev/null +++ b/java/mimis/src/main/java/mimis/device/lirc/LircButtonListener.java @@ -0,0 +1,5 @@ +package mimis.device.lirc; + +public interface LircButtonListener { + public void add(LircButton lircButton); +} \ No newline at end of file diff --git a/java/mimis/src/main/java/mimis/device/lirc/LircDevice.java b/java/mimis/src/main/java/mimis/device/lirc/LircDevice.java new file mode 100644 index 0000000..a09cb4e --- /dev/null +++ b/java/mimis/src/main/java/mimis/device/lirc/LircDevice.java @@ -0,0 +1,108 @@ +package mimis.device.lirc; + +import mimis.application.cmd.CMDApplication; +import mimis.device.Device; +import mimis.device.lirc.remote.DenonRC176Button; +import mimis.device.lirc.remote.PhiliphsRCLE011Button; +import mimis.device.lirc.remote.SamsungBN5901015AButton; +import mimis.exception.worker.ActivateException; +import mimis.exception.worker.DeactivateException; +import mimis.input.Button; +import mimis.input.button.ColorButton; +import mimis.input.button.NumberButton; +import mimis.input.state.Press; +import mimis.input.state.Release; +import mimis.util.Multiplexer; +import mimis.util.Native; +import mimis.util.multiplexer.SignalListener; +import mimis.value.Action; +import mimis.value.Signal; + +public class LircDevice extends CMDApplication implements Device, LircButtonListener, SignalListener