summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2009-05-02 01:37:43 -0400
committerJason A. Donenfeld <Jason@zx2c4.com>2009-05-02 01:37:43 -0400
commite90600f2885c322cce0dafa25b526c8fdf88a56f (patch)
tree2b59eb4a46f438fafa5b10493680d944d0c5ba63
downloadZPlayer-e90600f2885c322cce0dafa25b526c8fdf88a56f.tar.xz
ZPlayer-e90600f2885c322cce0dafa25b526c8fdf88a56f.zip
Initial commit.HEADmaster
-rw-r--r--3rdparty/com/strangeberry/rendezvous/DNSCache$IterateAll.classbin0 -> 1084 bytes
-rw-r--r--3rdparty/com/strangeberry/rendezvous/DNSCache$IterateKey.classbin0 -> 1462 bytes
-rw-r--r--3rdparty/com/strangeberry/rendezvous/DNSCache.classbin0 -> 3877 bytes
-rw-r--r--3rdparty/com/strangeberry/rendezvous/DNSConstants.classbin0 -> 1712 bytes
-rw-r--r--3rdparty/com/strangeberry/rendezvous/DNSEntry.classbin0 -> 2093 bytes
-rw-r--r--3rdparty/com/strangeberry/rendezvous/DNSIncoming.classbin0 -> 6802 bytes
-rw-r--r--3rdparty/com/strangeberry/rendezvous/DNSOutgoing.classbin0 -> 4882 bytes
-rw-r--r--3rdparty/com/strangeberry/rendezvous/DNSQuestion.classbin0 -> 938 bytes
-rw-r--r--3rdparty/com/strangeberry/rendezvous/DNSRecord$Address.classbin0 -> 1915 bytes
-rw-r--r--3rdparty/com/strangeberry/rendezvous/DNSRecord$Pointer.classbin0 -> 1326 bytes
-rw-r--r--3rdparty/com/strangeberry/rendezvous/DNSRecord$Service.classbin0 -> 1790 bytes
-rw-r--r--3rdparty/com/strangeberry/rendezvous/DNSRecord$Text.classbin0 -> 1563 bytes
-rw-r--r--3rdparty/com/strangeberry/rendezvous/DNSRecord.classbin0 -> 2987 bytes
-rw-r--r--3rdparty/com/strangeberry/rendezvous/Rendezvous$1.classbin0 -> 1245 bytes
-rw-r--r--3rdparty/com/strangeberry/rendezvous/Rendezvous$2.classbin0 -> 1248 bytes
-rw-r--r--3rdparty/com/strangeberry/rendezvous/Rendezvous$Listener.classbin0 -> 548 bytes
-rw-r--r--3rdparty/com/strangeberry/rendezvous/Rendezvous$RecordReaper.classbin0 -> 1613 bytes
-rw-r--r--3rdparty/com/strangeberry/rendezvous/Rendezvous$ServiceBrowser$Event.classbin0 -> 801 bytes
-rw-r--r--3rdparty/com/strangeberry/rendezvous/Rendezvous$ServiceBrowser.classbin0 -> 5057 bytes
-rw-r--r--3rdparty/com/strangeberry/rendezvous/Rendezvous$ServiceResolver.classbin0 -> 1952 bytes
-rw-r--r--3rdparty/com/strangeberry/rendezvous/Rendezvous$Shutdown.classbin0 -> 736 bytes
-rw-r--r--3rdparty/com/strangeberry/rendezvous/Rendezvous$SocketListener.classbin0 -> 2162 bytes
-rw-r--r--3rdparty/com/strangeberry/rendezvous/Rendezvous.classbin0 -> 13690 bytes
-rw-r--r--3rdparty/com/strangeberry/rendezvous/ServiceInfo.classbin0 -> 11072 bytes
-rw-r--r--3rdparty/com/strangeberry/rendezvous/ServiceListener.classbin0 -> 414 bytes
-rw-r--r--3rdparty/com/strangeberry/rendezvous/tools/Browser$ServiceTableModel.classbin0 -> 1305 bytes
-rw-r--r--3rdparty/com/strangeberry/rendezvous/tools/Browser.classbin0 -> 6678 bytes
-rw-r--r--3rdparty/com/strangeberry/rendezvous/tools/Main$SampleListener.classbin0 -> 1764 bytes
-rw-r--r--3rdparty/com/strangeberry/rendezvous/tools/Main.classbin0 -> 3372 bytes
-rw-r--r--3rdparty/com/strangeberry/rendezvous/tools/Responder.classbin0 -> 2003 bytes
-rw-r--r--3rdparty/javazoom/jl/converter/Converter$PrintWriterProgressListener.classbin0 -> 2717 bytes
-rw-r--r--3rdparty/javazoom/jl/converter/Converter$ProgressListener.classbin0 -> 589 bytes
-rw-r--r--3rdparty/javazoom/jl/converter/Converter.classbin0 -> 3598 bytes
-rw-r--r--3rdparty/javazoom/jl/converter/RiffFile$RiffChunkHeader.classbin0 -> 514 bytes
-rw-r--r--3rdparty/javazoom/jl/converter/RiffFile.classbin0 -> 4753 bytes
-rw-r--r--3rdparty/javazoom/jl/converter/WaveFile$WaveFileSample.classbin0 -> 471 bytes
-rw-r--r--3rdparty/javazoom/jl/converter/WaveFile$WaveFormat_Chunk.classbin0 -> 1332 bytes
-rw-r--r--3rdparty/javazoom/jl/converter/WaveFile$WaveFormat_ChunkData.classbin0 -> 878 bytes
-rw-r--r--3rdparty/javazoom/jl/converter/WaveFile.classbin0 -> 2782 bytes
-rw-r--r--3rdparty/javazoom/jl/converter/WaveFileObuffer.classbin0 -> 1209 bytes
-rw-r--r--3rdparty/javazoom/jl/converter/jlc$jlcArgs.classbin0 -> 2335 bytes
-rw-r--r--3rdparty/javazoom/jl/converter/jlc.classbin0 -> 1727 bytes
-rw-r--r--3rdparty/javazoom/jl/decoder/BitReserve.classbin0 -> 1306 bytes
-rw-r--r--3rdparty/javazoom/jl/decoder/Bitstream.classbin0 -> 4657 bytes
-rw-r--r--3rdparty/javazoom/jl/decoder/BitstreamErrors.classbin0 -> 420 bytes
-rw-r--r--3rdparty/javazoom/jl/decoder/BitstreamException.classbin0 -> 882 bytes
-rw-r--r--3rdparty/javazoom/jl/decoder/Control.classbin0 -> 276 bytes
-rw-r--r--3rdparty/javazoom/jl/decoder/Crc16.classbin0 -> 576 bytes
-rw-r--r--3rdparty/javazoom/jl/decoder/Decoder$Params.classbin0 -> 1416 bytes
-rw-r--r--3rdparty/javazoom/jl/decoder/Decoder.classbin0 -> 3998 bytes
-rw-r--r--3rdparty/javazoom/jl/decoder/DecoderErrors.classbin0 -> 268 bytes
-rw-r--r--3rdparty/javazoom/jl/decoder/DecoderException.classbin0 -> 874 bytes
-rw-r--r--3rdparty/javazoom/jl/decoder/Equalizer$EQFunction.classbin0 -> 359 bytes
-rw-r--r--3rdparty/javazoom/jl/decoder/Equalizer.classbin0 -> 1836 bytes
-rw-r--r--3rdparty/javazoom/jl/decoder/FrameDecoder.classbin0 -> 153 bytes
-rw-r--r--3rdparty/javazoom/jl/decoder/Header.classbin0 -> 8484 bytes
-rw-r--r--3rdparty/javazoom/jl/decoder/InputStreamSource.classbin0 -> 887 bytes
-rw-r--r--3rdparty/javazoom/jl/decoder/JavaLayerError.classbin0 -> 221 bytes
-rw-r--r--3rdparty/javazoom/jl/decoder/JavaLayerErrors.classbin0 -> 227 bytes
-rw-r--r--3rdparty/javazoom/jl/decoder/JavaLayerException.classbin0 -> 839 bytes
-rw-r--r--3rdparty/javazoom/jl/decoder/JavaLayerHook.classbin0 -> 201 bytes
-rw-r--r--3rdparty/javazoom/jl/decoder/JavaLayerUtils.classbin0 -> 3340 bytes
-rw-r--r--3rdparty/javazoom/jl/decoder/LayerIDecoder$Subband.classbin0 -> 1463 bytes
-rw-r--r--3rdparty/javazoom/jl/decoder/LayerIDecoder$SubbandLayer1.classbin0 -> 2061 bytes
-rw-r--r--3rdparty/javazoom/jl/decoder/LayerIDecoder$SubbandLayer1IntensityStereo.classbin0 -> 1582 bytes
-rw-r--r--3rdparty/javazoom/jl/decoder/LayerIDecoder$SubbandLayer1Stereo.classbin0 -> 1990 bytes
-rw-r--r--3rdparty/javazoom/jl/decoder/LayerIDecoder.classbin0 -> 3105 bytes
-rw-r--r--3rdparty/javazoom/jl/decoder/LayerIIDecoder$SubbandLayer2.classbin0 -> 24419 bytes
-rw-r--r--3rdparty/javazoom/jl/decoder/LayerIIDecoder$SubbandLayer2IntensityStereo.classbin0 -> 2607 bytes
-rw-r--r--3rdparty/javazoom/jl/decoder/LayerIIDecoder$SubbandLayer2Stereo.classbin0 -> 3037 bytes
-rw-r--r--3rdparty/javazoom/jl/decoder/LayerIIDecoder.classbin0 -> 1482 bytes
-rw-r--r--3rdparty/javazoom/jl/decoder/LayerIIIDecoder$III_side_info_t.classbin0 -> 624 bytes
-rw-r--r--3rdparty/javazoom/jl/decoder/LayerIIIDecoder$SBI.classbin0 -> 458 bytes
-rw-r--r--3rdparty/javazoom/jl/decoder/LayerIIIDecoder$Sftable.classbin0 -> 639 bytes
-rw-r--r--3rdparty/javazoom/jl/decoder/LayerIIIDecoder$gr_info_s.classbin0 -> 944 bytes
-rw-r--r--3rdparty/javazoom/jl/decoder/LayerIIIDecoder$temporaire.classbin0 -> 562 bytes
-rw-r--r--3rdparty/javazoom/jl/decoder/LayerIIIDecoder$temporaire2.classbin0 -> 411 bytes
-rw-r--r--3rdparty/javazoom/jl/decoder/LayerIIIDecoder.classbin0 -> 29546 bytes
-rw-r--r--3rdparty/javazoom/jl/decoder/Manager.classbin0 -> 401 bytes
-rw-r--r--3rdparty/javazoom/jl/decoder/Obuffer.classbin0 -> 639 bytes
-rw-r--r--3rdparty/javazoom/jl/decoder/OutputChannels.classbin0 -> 1543 bytes
-rw-r--r--3rdparty/javazoom/jl/decoder/SampleBuffer.classbin0 -> 1239 bytes
-rw-r--r--3rdparty/javazoom/jl/decoder/Source.classbin0 -> 359 bytes
-rw-r--r--3rdparty/javazoom/jl/decoder/SynthesisFilter.classbin0 -> 18826 bytes
-rw-r--r--3rdparty/javazoom/jl/decoder/au2lin.serbin0 -> 539 bytes
-rw-r--r--3rdparty/javazoom/jl/decoder/huffcodetab.classbin0 -> 50045 bytes
-rw-r--r--3rdparty/javazoom/jl/decoder/l3reorder.serbin0 -> 13925 bytes
-rw-r--r--3rdparty/javazoom/jl/decoder/lin2au.serbin0 -> 16411 bytes
-rw-r--r--3rdparty/javazoom/jl/decoder/sfd.serbin0 -> 2075 bytes
-rw-r--r--3rdparty/javazoom/jl/player/AudioDevice.classbin0 -> 364 bytes
-rw-r--r--3rdparty/javazoom/jl/player/AudioDeviceBase.classbin0 -> 1313 bytes
-rw-r--r--3rdparty/javazoom/jl/player/AudioDeviceFactory.classbin0 -> 900 bytes
-rw-r--r--3rdparty/javazoom/jl/player/FactoryRegistry.classbin0 -> 2356 bytes
-rw-r--r--3rdparty/javazoom/jl/player/JavaSoundAudioDevice.classbin0 -> 4149 bytes
-rw-r--r--3rdparty/javazoom/jl/player/JavaSoundAudioDeviceFactory.classbin0 -> 1728 bytes
-rw-r--r--3rdparty/javazoom/jl/player/NullAudioDevice.classbin0 -> 301 bytes
-rw-r--r--3rdparty/javazoom/jl/player/Player.classbin0 -> 2549 bytes
-rw-r--r--3rdparty/javazoom/jl/player/PlayerApplet.classbin0 -> 3058 bytes
-rw-r--r--3rdparty/javazoom/jl/player/jlp.classbin0 -> 3070 bytes
-rw-r--r--build.xml37
-rw-r--r--source/FieldPair.java202
-rw-r--r--source/client/Database.java54
-rw-r--r--source/client/MusicProvider.java52
-rw-r--r--source/client/Song.java155
-rw-r--r--source/client/request/ContentCodesRequest.java65
-rw-r--r--source/client/request/DatabasesRequest.java121
-rw-r--r--source/client/request/LoginRequest.java49
-rw-r--r--source/client/request/LogoutRequest.java42
-rw-r--r--source/client/request/NoServerPermissionException.java41
-rw-r--r--source/client/request/Request.java225
-rw-r--r--source/client/request/ServerInfoRequest.java46
-rw-r--r--source/client/request/SingleDatabaseRequest.java76
-rw-r--r--source/client/request/SongRequest.java87
-rw-r--r--source/client/swing/Player.java59
-rw-r--r--source/client/swing/SongTableModel.java103
-rw-r--r--source/client/swing/SwingWorker.java133
-rw-r--r--source/client/swing/TableMap.java70
-rw-r--r--source/client/swing/TableSorter.java432
-rw-r--r--source/client/swing/ZApplet.java46
-rw-r--r--source/client/swing/ZPlayer.java506
-rw-r--r--source/util/Hasher.java109
121 files changed, 2710 insertions, 0 deletions
diff --git a/3rdparty/com/strangeberry/rendezvous/DNSCache$IterateAll.class b/3rdparty/com/strangeberry/rendezvous/DNSCache$IterateAll.class
new file mode 100644
index 0000000..b3a632c
--- /dev/null
+++ b/3rdparty/com/strangeberry/rendezvous/DNSCache$IterateAll.class
Binary files differ
diff --git a/3rdparty/com/strangeberry/rendezvous/DNSCache$IterateKey.class b/3rdparty/com/strangeberry/rendezvous/DNSCache$IterateKey.class
new file mode 100644
index 0000000..f507863
--- /dev/null
+++ b/3rdparty/com/strangeberry/rendezvous/DNSCache$IterateKey.class
Binary files differ
diff --git a/3rdparty/com/strangeberry/rendezvous/DNSCache.class b/3rdparty/com/strangeberry/rendezvous/DNSCache.class
new file mode 100644
index 0000000..db20afe
--- /dev/null
+++ b/3rdparty/com/strangeberry/rendezvous/DNSCache.class
Binary files differ
diff --git a/3rdparty/com/strangeberry/rendezvous/DNSConstants.class b/3rdparty/com/strangeberry/rendezvous/DNSConstants.class
new file mode 100644
index 0000000..ec42bac
--- /dev/null
+++ b/3rdparty/com/strangeberry/rendezvous/DNSConstants.class
Binary files differ
diff --git a/3rdparty/com/strangeberry/rendezvous/DNSEntry.class b/3rdparty/com/strangeberry/rendezvous/DNSEntry.class
new file mode 100644
index 0000000..9f337de
--- /dev/null
+++ b/3rdparty/com/strangeberry/rendezvous/DNSEntry.class
Binary files differ
diff --git a/3rdparty/com/strangeberry/rendezvous/DNSIncoming.class b/3rdparty/com/strangeberry/rendezvous/DNSIncoming.class
new file mode 100644
index 0000000..a8dfe68
--- /dev/null
+++ b/3rdparty/com/strangeberry/rendezvous/DNSIncoming.class
Binary files differ
diff --git a/3rdparty/com/strangeberry/rendezvous/DNSOutgoing.class b/3rdparty/com/strangeberry/rendezvous/DNSOutgoing.class
new file mode 100644
index 0000000..a20efcd
--- /dev/null
+++ b/3rdparty/com/strangeberry/rendezvous/DNSOutgoing.class
Binary files differ
diff --git a/3rdparty/com/strangeberry/rendezvous/DNSQuestion.class b/3rdparty/com/strangeberry/rendezvous/DNSQuestion.class
new file mode 100644
index 0000000..ecdb401
--- /dev/null
+++ b/3rdparty/com/strangeberry/rendezvous/DNSQuestion.class
Binary files differ
diff --git a/3rdparty/com/strangeberry/rendezvous/DNSRecord$Address.class b/3rdparty/com/strangeberry/rendezvous/DNSRecord$Address.class
new file mode 100644
index 0000000..0146225
--- /dev/null
+++ b/3rdparty/com/strangeberry/rendezvous/DNSRecord$Address.class
Binary files differ
diff --git a/3rdparty/com/strangeberry/rendezvous/DNSRecord$Pointer.class b/3rdparty/com/strangeberry/rendezvous/DNSRecord$Pointer.class
new file mode 100644
index 0000000..1511b5c
--- /dev/null
+++ b/3rdparty/com/strangeberry/rendezvous/DNSRecord$Pointer.class
Binary files differ
diff --git a/3rdparty/com/strangeberry/rendezvous/DNSRecord$Service.class b/3rdparty/com/strangeberry/rendezvous/DNSRecord$Service.class
new file mode 100644
index 0000000..f071b44
--- /dev/null
+++ b/3rdparty/com/strangeberry/rendezvous/DNSRecord$Service.class
Binary files differ
diff --git a/3rdparty/com/strangeberry/rendezvous/DNSRecord$Text.class b/3rdparty/com/strangeberry/rendezvous/DNSRecord$Text.class
new file mode 100644
index 0000000..340d7b3
--- /dev/null
+++ b/3rdparty/com/strangeberry/rendezvous/DNSRecord$Text.class
Binary files differ
diff --git a/3rdparty/com/strangeberry/rendezvous/DNSRecord.class b/3rdparty/com/strangeberry/rendezvous/DNSRecord.class
new file mode 100644
index 0000000..41f0e22
--- /dev/null
+++ b/3rdparty/com/strangeberry/rendezvous/DNSRecord.class
Binary files differ
diff --git a/3rdparty/com/strangeberry/rendezvous/Rendezvous$1.class b/3rdparty/com/strangeberry/rendezvous/Rendezvous$1.class
new file mode 100644
index 0000000..803e6da
--- /dev/null
+++ b/3rdparty/com/strangeberry/rendezvous/Rendezvous$1.class
Binary files differ
diff --git a/3rdparty/com/strangeberry/rendezvous/Rendezvous$2.class b/3rdparty/com/strangeberry/rendezvous/Rendezvous$2.class
new file mode 100644
index 0000000..4373b7f
--- /dev/null
+++ b/3rdparty/com/strangeberry/rendezvous/Rendezvous$2.class
Binary files differ
diff --git a/3rdparty/com/strangeberry/rendezvous/Rendezvous$Listener.class b/3rdparty/com/strangeberry/rendezvous/Rendezvous$Listener.class
new file mode 100644
index 0000000..5e5f2a3
--- /dev/null
+++ b/3rdparty/com/strangeberry/rendezvous/Rendezvous$Listener.class
Binary files differ
diff --git a/3rdparty/com/strangeberry/rendezvous/Rendezvous$RecordReaper.class b/3rdparty/com/strangeberry/rendezvous/Rendezvous$RecordReaper.class
new file mode 100644
index 0000000..9b8147a
--- /dev/null
+++ b/3rdparty/com/strangeberry/rendezvous/Rendezvous$RecordReaper.class
Binary files differ
diff --git a/3rdparty/com/strangeberry/rendezvous/Rendezvous$ServiceBrowser$Event.class b/3rdparty/com/strangeberry/rendezvous/Rendezvous$ServiceBrowser$Event.class
new file mode 100644
index 0000000..3cf5923
--- /dev/null
+++ b/3rdparty/com/strangeberry/rendezvous/Rendezvous$ServiceBrowser$Event.class
Binary files differ
diff --git a/3rdparty/com/strangeberry/rendezvous/Rendezvous$ServiceBrowser.class b/3rdparty/com/strangeberry/rendezvous/Rendezvous$ServiceBrowser.class
new file mode 100644
index 0000000..b8cf98d
--- /dev/null
+++ b/3rdparty/com/strangeberry/rendezvous/Rendezvous$ServiceBrowser.class
Binary files differ
diff --git a/3rdparty/com/strangeberry/rendezvous/Rendezvous$ServiceResolver.class b/3rdparty/com/strangeberry/rendezvous/Rendezvous$ServiceResolver.class
new file mode 100644
index 0000000..6dae8bb
--- /dev/null
+++ b/3rdparty/com/strangeberry/rendezvous/Rendezvous$ServiceResolver.class
Binary files differ
diff --git a/3rdparty/com/strangeberry/rendezvous/Rendezvous$Shutdown.class b/3rdparty/com/strangeberry/rendezvous/Rendezvous$Shutdown.class
new file mode 100644
index 0000000..0988db9
--- /dev/null
+++ b/3rdparty/com/strangeberry/rendezvous/Rendezvous$Shutdown.class
Binary files differ
diff --git a/3rdparty/com/strangeberry/rendezvous/Rendezvous$SocketListener.class b/3rdparty/com/strangeberry/rendezvous/Rendezvous$SocketListener.class
new file mode 100644
index 0000000..c8d7213
--- /dev/null
+++ b/3rdparty/com/strangeberry/rendezvous/Rendezvous$SocketListener.class
Binary files differ
diff --git a/3rdparty/com/strangeberry/rendezvous/Rendezvous.class b/3rdparty/com/strangeberry/rendezvous/Rendezvous.class
new file mode 100644
index 0000000..c1df920
--- /dev/null
+++ b/3rdparty/com/strangeberry/rendezvous/Rendezvous.class
Binary files differ
diff --git a/3rdparty/com/strangeberry/rendezvous/ServiceInfo.class b/3rdparty/com/strangeberry/rendezvous/ServiceInfo.class
new file mode 100644
index 0000000..fbdbbe6
--- /dev/null
+++ b/3rdparty/com/strangeberry/rendezvous/ServiceInfo.class
Binary files differ
diff --git a/3rdparty/com/strangeberry/rendezvous/ServiceListener.class b/3rdparty/com/strangeberry/rendezvous/ServiceListener.class
new file mode 100644
index 0000000..816c0c2
--- /dev/null
+++ b/3rdparty/com/strangeberry/rendezvous/ServiceListener.class
Binary files differ
diff --git a/3rdparty/com/strangeberry/rendezvous/tools/Browser$ServiceTableModel.class b/3rdparty/com/strangeberry/rendezvous/tools/Browser$ServiceTableModel.class
new file mode 100644
index 0000000..fc89d49
--- /dev/null
+++ b/3rdparty/com/strangeberry/rendezvous/tools/Browser$ServiceTableModel.class
Binary files differ
diff --git a/3rdparty/com/strangeberry/rendezvous/tools/Browser.class b/3rdparty/com/strangeberry/rendezvous/tools/Browser.class
new file mode 100644
index 0000000..e5e9990
--- /dev/null
+++ b/3rdparty/com/strangeberry/rendezvous/tools/Browser.class
Binary files differ
diff --git a/3rdparty/com/strangeberry/rendezvous/tools/Main$SampleListener.class b/3rdparty/com/strangeberry/rendezvous/tools/Main$SampleListener.class
new file mode 100644
index 0000000..8907a75
--- /dev/null
+++ b/3rdparty/com/strangeberry/rendezvous/tools/Main$SampleListener.class
Binary files differ
diff --git a/3rdparty/com/strangeberry/rendezvous/tools/Main.class b/3rdparty/com/strangeberry/rendezvous/tools/Main.class
new file mode 100644
index 0000000..e12863f
--- /dev/null
+++ b/3rdparty/com/strangeberry/rendezvous/tools/Main.class
Binary files differ
diff --git a/3rdparty/com/strangeberry/rendezvous/tools/Responder.class b/3rdparty/com/strangeberry/rendezvous/tools/Responder.class
new file mode 100644
index 0000000..bc09965
--- /dev/null
+++ b/3rdparty/com/strangeberry/rendezvous/tools/Responder.class
Binary files differ
diff --git a/3rdparty/javazoom/jl/converter/Converter$PrintWriterProgressListener.class b/3rdparty/javazoom/jl/converter/Converter$PrintWriterProgressListener.class
new file mode 100644
index 0000000..9fab444
--- /dev/null
+++ b/3rdparty/javazoom/jl/converter/Converter$PrintWriterProgressListener.class
Binary files differ
diff --git a/3rdparty/javazoom/jl/converter/Converter$ProgressListener.class b/3rdparty/javazoom/jl/converter/Converter$ProgressListener.class
new file mode 100644
index 0000000..50ddf16
--- /dev/null
+++ b/3rdparty/javazoom/jl/converter/Converter$ProgressListener.class
Binary files differ
diff --git a/3rdparty/javazoom/jl/converter/Converter.class b/3rdparty/javazoom/jl/converter/Converter.class
new file mode 100644
index 0000000..61231f1
--- /dev/null
+++ b/3rdparty/javazoom/jl/converter/Converter.class
Binary files differ
diff --git a/3rdparty/javazoom/jl/converter/RiffFile$RiffChunkHeader.class b/3rdparty/javazoom/jl/converter/RiffFile$RiffChunkHeader.class
new file mode 100644
index 0000000..70f8765
--- /dev/null
+++ b/3rdparty/javazoom/jl/converter/RiffFile$RiffChunkHeader.class
Binary files differ
diff --git a/3rdparty/javazoom/jl/converter/RiffFile.class b/3rdparty/javazoom/jl/converter/RiffFile.class
new file mode 100644
index 0000000..c25e4d0
--- /dev/null
+++ b/3rdparty/javazoom/jl/converter/RiffFile.class
Binary files differ
diff --git a/3rdparty/javazoom/jl/converter/WaveFile$WaveFileSample.class b/3rdparty/javazoom/jl/converter/WaveFile$WaveFileSample.class
new file mode 100644
index 0000000..85f9ecd
--- /dev/null
+++ b/3rdparty/javazoom/jl/converter/WaveFile$WaveFileSample.class
Binary files differ
diff --git a/3rdparty/javazoom/jl/converter/WaveFile$WaveFormat_Chunk.class b/3rdparty/javazoom/jl/converter/WaveFile$WaveFormat_Chunk.class
new file mode 100644
index 0000000..094a9c8
--- /dev/null
+++ b/3rdparty/javazoom/jl/converter/WaveFile$WaveFormat_Chunk.class
Binary files differ
diff --git a/3rdparty/javazoom/jl/converter/WaveFile$WaveFormat_ChunkData.class b/3rdparty/javazoom/jl/converter/WaveFile$WaveFormat_ChunkData.class
new file mode 100644
index 0000000..7ab001b
--- /dev/null
+++ b/3rdparty/javazoom/jl/converter/WaveFile$WaveFormat_ChunkData.class
Binary files differ
diff --git a/3rdparty/javazoom/jl/converter/WaveFile.class b/3rdparty/javazoom/jl/converter/WaveFile.class
new file mode 100644
index 0000000..54d816a
--- /dev/null
+++ b/3rdparty/javazoom/jl/converter/WaveFile.class
Binary files differ
diff --git a/3rdparty/javazoom/jl/converter/WaveFileObuffer.class b/3rdparty/javazoom/jl/converter/WaveFileObuffer.class
new file mode 100644
index 0000000..18a320b
--- /dev/null
+++ b/3rdparty/javazoom/jl/converter/WaveFileObuffer.class
Binary files differ
diff --git a/3rdparty/javazoom/jl/converter/jlc$jlcArgs.class b/3rdparty/javazoom/jl/converter/jlc$jlcArgs.class
new file mode 100644
index 0000000..a635bb0
--- /dev/null
+++ b/3rdparty/javazoom/jl/converter/jlc$jlcArgs.class
Binary files differ
diff --git a/3rdparty/javazoom/jl/converter/jlc.class b/3rdparty/javazoom/jl/converter/jlc.class
new file mode 100644
index 0000000..bd4258c
--- /dev/null
+++ b/3rdparty/javazoom/jl/converter/jlc.class
Binary files differ
diff --git a/3rdparty/javazoom/jl/decoder/BitReserve.class b/3rdparty/javazoom/jl/decoder/BitReserve.class
new file mode 100644
index 0000000..caa1c78
--- /dev/null
+++ b/3rdparty/javazoom/jl/decoder/BitReserve.class
Binary files differ
diff --git a/3rdparty/javazoom/jl/decoder/Bitstream.class b/3rdparty/javazoom/jl/decoder/Bitstream.class
new file mode 100644
index 0000000..5012360
--- /dev/null
+++ b/3rdparty/javazoom/jl/decoder/Bitstream.class
Binary files differ
diff --git a/3rdparty/javazoom/jl/decoder/BitstreamErrors.class b/3rdparty/javazoom/jl/decoder/BitstreamErrors.class
new file mode 100644
index 0000000..ec721f1
--- /dev/null
+++ b/3rdparty/javazoom/jl/decoder/BitstreamErrors.class
Binary files differ
diff --git a/3rdparty/javazoom/jl/decoder/BitstreamException.class b/3rdparty/javazoom/jl/decoder/BitstreamException.class
new file mode 100644
index 0000000..391130a
--- /dev/null
+++ b/3rdparty/javazoom/jl/decoder/BitstreamException.class
Binary files differ
diff --git a/3rdparty/javazoom/jl/decoder/Control.class b/3rdparty/javazoom/jl/decoder/Control.class
new file mode 100644
index 0000000..025996a
--- /dev/null
+++ b/3rdparty/javazoom/jl/decoder/Control.class
Binary files differ
diff --git a/3rdparty/javazoom/jl/decoder/Crc16.class b/3rdparty/javazoom/jl/decoder/Crc16.class
new file mode 100644
index 0000000..73a013c
--- /dev/null
+++ b/3rdparty/javazoom/jl/decoder/Crc16.class
Binary files differ
diff --git a/3rdparty/javazoom/jl/decoder/Decoder$Params.class b/3rdparty/javazoom/jl/decoder/Decoder$Params.class
new file mode 100644
index 0000000..945b3d6
--- /dev/null
+++ b/3rdparty/javazoom/jl/decoder/Decoder$Params.class
Binary files differ
diff --git a/3rdparty/javazoom/jl/decoder/Decoder.class b/3rdparty/javazoom/jl/decoder/Decoder.class
new file mode 100644
index 0000000..0f5ce6f
--- /dev/null
+++ b/3rdparty/javazoom/jl/decoder/Decoder.class
Binary files differ
diff --git a/3rdparty/javazoom/jl/decoder/DecoderErrors.class b/3rdparty/javazoom/jl/decoder/DecoderErrors.class
new file mode 100644
index 0000000..680ed20
--- /dev/null
+++ b/3rdparty/javazoom/jl/decoder/DecoderErrors.class
Binary files differ
diff --git a/3rdparty/javazoom/jl/decoder/DecoderException.class b/3rdparty/javazoom/jl/decoder/DecoderException.class
new file mode 100644
index 0000000..123eb22
--- /dev/null
+++ b/3rdparty/javazoom/jl/decoder/DecoderException.class
Binary files differ
diff --git a/3rdparty/javazoom/jl/decoder/Equalizer$EQFunction.class b/3rdparty/javazoom/jl/decoder/Equalizer$EQFunction.class
new file mode 100644
index 0000000..779f401
--- /dev/null
+++ b/3rdparty/javazoom/jl/decoder/Equalizer$EQFunction.class
Binary files differ
diff --git a/3rdparty/javazoom/jl/decoder/Equalizer.class b/3rdparty/javazoom/jl/decoder/Equalizer.class
new file mode 100644
index 0000000..1ebe778
--- /dev/null
+++ b/3rdparty/javazoom/jl/decoder/Equalizer.class
Binary files differ
diff --git a/3rdparty/javazoom/jl/decoder/FrameDecoder.class b/3rdparty/javazoom/jl/decoder/FrameDecoder.class
new file mode 100644
index 0000000..57b999d
--- /dev/null
+++ b/3rdparty/javazoom/jl/decoder/FrameDecoder.class
Binary files differ
diff --git a/3rdparty/javazoom/jl/decoder/Header.class b/3rdparty/javazoom/jl/decoder/Header.class
new file mode 100644
index 0000000..b1feaff
--- /dev/null
+++ b/3rdparty/javazoom/jl/decoder/Header.class
Binary files differ
diff --git a/3rdparty/javazoom/jl/decoder/InputStreamSource.class b/3rdparty/javazoom/jl/decoder/InputStreamSource.class
new file mode 100644
index 0000000..77d8732
--- /dev/null
+++ b/3rdparty/javazoom/jl/decoder/InputStreamSource.class
Binary files differ
diff --git a/3rdparty/javazoom/jl/decoder/JavaLayerError.class b/3rdparty/javazoom/jl/decoder/JavaLayerError.class
new file mode 100644
index 0000000..a07e85c
--- /dev/null
+++ b/3rdparty/javazoom/jl/decoder/JavaLayerError.class
Binary files differ
diff --git a/3rdparty/javazoom/jl/decoder/JavaLayerErrors.class b/3rdparty/javazoom/jl/decoder/JavaLayerErrors.class
new file mode 100644
index 0000000..afb7e31
--- /dev/null
+++ b/3rdparty/javazoom/jl/decoder/JavaLayerErrors.class
Binary files differ
diff --git a/3rdparty/javazoom/jl/decoder/JavaLayerException.class b/3rdparty/javazoom/jl/decoder/JavaLayerException.class
new file mode 100644
index 0000000..49e4d2a
--- /dev/null
+++ b/3rdparty/javazoom/jl/decoder/JavaLayerException.class
Binary files differ
diff --git a/3rdparty/javazoom/jl/decoder/JavaLayerHook.class b/3rdparty/javazoom/jl/decoder/JavaLayerHook.class
new file mode 100644
index 0000000..3441e7d
--- /dev/null
+++ b/3rdparty/javazoom/jl/decoder/JavaLayerHook.class
Binary files differ
diff --git a/3rdparty/javazoom/jl/decoder/JavaLayerUtils.class b/3rdparty/javazoom/jl/decoder/JavaLayerUtils.class
new file mode 100644
index 0000000..40c1d07
--- /dev/null
+++ b/3rdparty/javazoom/jl/decoder/JavaLayerUtils.class
Binary files differ
diff --git a/3rdparty/javazoom/jl/decoder/LayerIDecoder$Subband.class b/3rdparty/javazoom/jl/decoder/LayerIDecoder$Subband.class
new file mode 100644
index 0000000..c143450
--- /dev/null
+++ b/3rdparty/javazoom/jl/decoder/LayerIDecoder$Subband.class
Binary files differ
diff --git a/3rdparty/javazoom/jl/decoder/LayerIDecoder$SubbandLayer1.class b/3rdparty/javazoom/jl/decoder/LayerIDecoder$SubbandLayer1.class
new file mode 100644
index 0000000..206e47f
--- /dev/null
+++ b/3rdparty/javazoom/jl/decoder/LayerIDecoder$SubbandLayer1.class
Binary files differ
diff --git a/3rdparty/javazoom/jl/decoder/LayerIDecoder$SubbandLayer1IntensityStereo.class b/3rdparty/javazoom/jl/decoder/LayerIDecoder$SubbandLayer1IntensityStereo.class
new file mode 100644
index 0000000..3dec876
--- /dev/null
+++ b/3rdparty/javazoom/jl/decoder/LayerIDecoder$SubbandLayer1IntensityStereo.class
Binary files differ
diff --git a/3rdparty/javazoom/jl/decoder/LayerIDecoder$SubbandLayer1Stereo.class b/3rdparty/javazoom/jl/decoder/LayerIDecoder$SubbandLayer1Stereo.class
new file mode 100644
index 0000000..b40fa91
--- /dev/null
+++ b/3rdparty/javazoom/jl/decoder/LayerIDecoder$SubbandLayer1Stereo.class
Binary files differ
diff --git a/3rdparty/javazoom/jl/decoder/LayerIDecoder.class b/3rdparty/javazoom/jl/decoder/LayerIDecoder.class
new file mode 100644
index 0000000..b98a3e0
--- /dev/null
+++ b/3rdparty/javazoom/jl/decoder/LayerIDecoder.class
Binary files differ
diff --git a/3rdparty/javazoom/jl/decoder/LayerIIDecoder$SubbandLayer2.class b/3rdparty/javazoom/jl/decoder/LayerIIDecoder$SubbandLayer2.class
new file mode 100644
index 0000000..75074e0
--- /dev/null
+++ b/3rdparty/javazoom/jl/decoder/LayerIIDecoder$SubbandLayer2.class
Binary files differ
diff --git a/3rdparty/javazoom/jl/decoder/LayerIIDecoder$SubbandLayer2IntensityStereo.class b/3rdparty/javazoom/jl/decoder/LayerIIDecoder$SubbandLayer2IntensityStereo.class
new file mode 100644
index 0000000..feec2cc
--- /dev/null
+++ b/3rdparty/javazoom/jl/decoder/LayerIIDecoder$SubbandLayer2IntensityStereo.class
Binary files differ
diff --git a/3rdparty/javazoom/jl/decoder/LayerIIDecoder$SubbandLayer2Stereo.class b/3rdparty/javazoom/jl/decoder/LayerIIDecoder$SubbandLayer2Stereo.class
new file mode 100644
index 0000000..a08348e
--- /dev/null
+++ b/3rdparty/javazoom/jl/decoder/LayerIIDecoder$SubbandLayer2Stereo.class
Binary files differ
diff --git a/3rdparty/javazoom/jl/decoder/LayerIIDecoder.class b/3rdparty/javazoom/jl/decoder/LayerIIDecoder.class
new file mode 100644
index 0000000..c7f198b
--- /dev/null
+++ b/3rdparty/javazoom/jl/decoder/LayerIIDecoder.class
Binary files differ
diff --git a/3rdparty/javazoom/jl/decoder/LayerIIIDecoder$III_side_info_t.class b/3rdparty/javazoom/jl/decoder/LayerIIIDecoder$III_side_info_t.class
new file mode 100644
index 0000000..a47bee8
--- /dev/null
+++ b/3rdparty/javazoom/jl/decoder/LayerIIIDecoder$III_side_info_t.class
Binary files differ
diff --git a/3rdparty/javazoom/jl/decoder/LayerIIIDecoder$SBI.class b/3rdparty/javazoom/jl/decoder/LayerIIIDecoder$SBI.class
new file mode 100644
index 0000000..87b6815
--- /dev/null
+++ b/3rdparty/javazoom/jl/decoder/LayerIIIDecoder$SBI.class
Binary files differ
diff --git a/3rdparty/javazoom/jl/decoder/LayerIIIDecoder$Sftable.class b/3rdparty/javazoom/jl/decoder/LayerIIIDecoder$Sftable.class
new file mode 100644
index 0000000..df83727
--- /dev/null
+++ b/3rdparty/javazoom/jl/decoder/LayerIIIDecoder$Sftable.class
Binary files differ
diff --git a/3rdparty/javazoom/jl/decoder/LayerIIIDecoder$gr_info_s.class b/3rdparty/javazoom/jl/decoder/LayerIIIDecoder$gr_info_s.class
new file mode 100644
index 0000000..54494de
--- /dev/null
+++ b/3rdparty/javazoom/jl/decoder/LayerIIIDecoder$gr_info_s.class
Binary files differ
diff --git a/3rdparty/javazoom/jl/decoder/LayerIIIDecoder$temporaire.class b/3rdparty/javazoom/jl/decoder/LayerIIIDecoder$temporaire.class
new file mode 100644
index 0000000..9a7765a
--- /dev/null
+++ b/3rdparty/javazoom/jl/decoder/LayerIIIDecoder$temporaire.class
Binary files differ
diff --git a/3rdparty/javazoom/jl/decoder/LayerIIIDecoder$temporaire2.class b/3rdparty/javazoom/jl/decoder/LayerIIIDecoder$temporaire2.class
new file mode 100644
index 0000000..9c32b5d
--- /dev/null
+++ b/3rdparty/javazoom/jl/decoder/LayerIIIDecoder$temporaire2.class
Binary files differ
diff --git a/3rdparty/javazoom/jl/decoder/LayerIIIDecoder.class b/3rdparty/javazoom/jl/decoder/LayerIIIDecoder.class
new file mode 100644
index 0000000..8921642
--- /dev/null
+++ b/3rdparty/javazoom/jl/decoder/LayerIIIDecoder.class
Binary files differ
diff --git a/3rdparty/javazoom/jl/decoder/Manager.class b/3rdparty/javazoom/jl/decoder/Manager.class
new file mode 100644
index 0000000..8dfa550
--- /dev/null
+++ b/3rdparty/javazoom/jl/decoder/Manager.class
Binary files differ
diff --git a/3rdparty/javazoom/jl/decoder/Obuffer.class b/3rdparty/javazoom/jl/decoder/Obuffer.class
new file mode 100644
index 0000000..1f9683a
--- /dev/null
+++ b/3rdparty/javazoom/jl/decoder/Obuffer.class
Binary files differ
diff --git a/3rdparty/javazoom/jl/decoder/OutputChannels.class b/3rdparty/javazoom/jl/decoder/OutputChannels.class
new file mode 100644
index 0000000..e5e67f9
--- /dev/null
+++ b/3rdparty/javazoom/jl/decoder/OutputChannels.class
Binary files differ
diff --git a/3rdparty/javazoom/jl/decoder/SampleBuffer.class b/3rdparty/javazoom/jl/decoder/SampleBuffer.class
new file mode 100644
index 0000000..d451dfc
--- /dev/null
+++ b/3rdparty/javazoom/jl/decoder/SampleBuffer.class
Binary files differ
diff --git a/3rdparty/javazoom/jl/decoder/Source.class b/3rdparty/javazoom/jl/decoder/Source.class
new file mode 100644
index 0000000..b7c2ea2
--- /dev/null
+++ b/3rdparty/javazoom/jl/decoder/Source.class
Binary files differ
diff --git a/3rdparty/javazoom/jl/decoder/SynthesisFilter.class b/3rdparty/javazoom/jl/decoder/SynthesisFilter.class
new file mode 100644
index 0000000..be0ee70
--- /dev/null
+++ b/3rdparty/javazoom/jl/decoder/SynthesisFilter.class
Binary files differ
diff --git a/3rdparty/javazoom/jl/decoder/au2lin.ser b/3rdparty/javazoom/jl/decoder/au2lin.ser
new file mode 100644
index 0000000..0b20bc8
--- /dev/null
+++ b/3rdparty/javazoom/jl/decoder/au2lin.ser
Binary files differ
diff --git a/3rdparty/javazoom/jl/decoder/huffcodetab.class b/3rdparty/javazoom/jl/decoder/huffcodetab.class
new file mode 100644
index 0000000..308029e
--- /dev/null
+++ b/3rdparty/javazoom/jl/decoder/huffcodetab.class
Binary files differ
diff --git a/3rdparty/javazoom/jl/decoder/l3reorder.ser b/3rdparty/javazoom/jl/decoder/l3reorder.ser
new file mode 100644
index 0000000..da216fc
--- /dev/null
+++ b/3rdparty/javazoom/jl/decoder/l3reorder.ser
Binary files differ
diff --git a/3rdparty/javazoom/jl/decoder/lin2au.ser b/3rdparty/javazoom/jl/decoder/lin2au.ser
new file mode 100644
index 0000000..ec1c83d
--- /dev/null
+++ b/3rdparty/javazoom/jl/decoder/lin2au.ser
Binary files differ
diff --git a/3rdparty/javazoom/jl/decoder/sfd.ser b/3rdparty/javazoom/jl/decoder/sfd.ser
new file mode 100644
index 0000000..440c7c6
--- /dev/null
+++ b/3rdparty/javazoom/jl/decoder/sfd.ser
Binary files differ
diff --git a/3rdparty/javazoom/jl/player/AudioDevice.class b/3rdparty/javazoom/jl/player/AudioDevice.class
new file mode 100644
index 0000000..acd1c56
--- /dev/null
+++ b/3rdparty/javazoom/jl/player/AudioDevice.class
Binary files differ
diff --git a/3rdparty/javazoom/jl/player/AudioDeviceBase.class b/3rdparty/javazoom/jl/player/AudioDeviceBase.class
new file mode 100644
index 0000000..0eeb0d1
--- /dev/null
+++ b/3rdparty/javazoom/jl/player/AudioDeviceBase.class
Binary files differ
diff --git a/3rdparty/javazoom/jl/player/AudioDeviceFactory.class b/3rdparty/javazoom/jl/player/AudioDeviceFactory.class
new file mode 100644
index 0000000..91e27fa
--- /dev/null
+++ b/3rdparty/javazoom/jl/player/AudioDeviceFactory.class
Binary files differ
diff --git a/3rdparty/javazoom/jl/player/FactoryRegistry.class b/3rdparty/javazoom/jl/player/FactoryRegistry.class
new file mode 100644
index 0000000..19a1496
--- /dev/null
+++ b/3rdparty/javazoom/jl/player/FactoryRegistry.class
Binary files differ
diff --git a/3rdparty/javazoom/jl/player/JavaSoundAudioDevice.class b/3rdparty/javazoom/jl/player/JavaSoundAudioDevice.class
new file mode 100644
index 0000000..c6a3b31
--- /dev/null
+++ b/3rdparty/javazoom/jl/player/JavaSoundAudioDevice.class
Binary files differ
diff --git a/3rdparty/javazoom/jl/player/JavaSoundAudioDeviceFactory.class b/3rdparty/javazoom/jl/player/JavaSoundAudioDeviceFactory.class
new file mode 100644
index 0000000..8905d7a
--- /dev/null
+++ b/3rdparty/javazoom/jl/player/JavaSoundAudioDeviceFactory.class
Binary files differ
diff --git a/3rdparty/javazoom/jl/player/NullAudioDevice.class b/3rdparty/javazoom/jl/player/NullAudioDevice.class
new file mode 100644
index 0000000..802f188
--- /dev/null
+++ b/3rdparty/javazoom/jl/player/NullAudioDevice.class
Binary files differ
diff --git a/3rdparty/javazoom/jl/player/Player.class b/3rdparty/javazoom/jl/player/Player.class
new file mode 100644
index 0000000..b934630
--- /dev/null
+++ b/3rdparty/javazoom/jl/player/Player.class
Binary files differ
diff --git a/3rdparty/javazoom/jl/player/PlayerApplet.class b/3rdparty/javazoom/jl/player/PlayerApplet.class
new file mode 100644
index 0000000..d123801
--- /dev/null
+++ b/3rdparty/javazoom/jl/player/PlayerApplet.class
Binary files differ
diff --git a/3rdparty/javazoom/jl/player/jlp.class b/3rdparty/javazoom/jl/player/jlp.class
new file mode 100644
index 0000000..ae1bcbc
--- /dev/null
+++ b/3rdparty/javazoom/jl/player/jlp.class
Binary files differ
diff --git a/build.xml b/build.xml
new file mode 100644
index 0000000..bdc7b91
--- /dev/null
+++ b/build.xml
@@ -0,0 +1,37 @@
+<project name="ZPlayer" default="dist" basedir=".">
+ <!-- set global properties for this build -->
+ <property name="src" location="source" />
+ <property name="build" location="build" />
+ <property name="dist" location="dist" />
+ <property name="external" location="3rdparty" />
+
+ <target name="init">
+ <!-- Create the time stamp -->
+ <!-- <tstamp /> -->
+ <!-- Create the build directory structure used by compile -->
+ <mkdir dir="${build}" />
+ </target>
+
+ <target name="compile" depends="init" description="compile the source ">
+ <!-- Compile the java code from ${src} into ${build} -->
+ <javac source="1.5" target="1.5" srcdir="${src}" destdir="${build}" classpath="${external}"/>
+ </target>
+
+ <target name="dist" depends="compile" description="generate the distribution">
+ <!-- Create the distribution directory -->
+ <mkdir dir="${dist}" />
+ <jar jarfile="${dist}/ZPlayer.jar" basedir="${build}">
+ <fileset dir="${external}" />
+ <manifest>
+ <attribute name="Main-Class" value="itunes.client.swing.ZPlayer" />
+ </manifest>
+ </jar>
+ <!-- <signjar jar="${dist}/ZPlayer.jar" alias="key" storepass="XXXX"/> -->
+ </target>
+
+ <target name="clean" description="clean up">
+ <!-- Delete the ${build} and ${dist} directory trees -->
+ <delete dir="${build}" />
+ <delete dir="${dist}" />
+ </target>
+</project>
diff --git a/source/FieldPair.java b/source/FieldPair.java
new file mode 100644
index 0000000..d3804c6
--- /dev/null
+++ b/source/FieldPair.java
@@ -0,0 +1,202 @@
+/*
+ * Created on May 6, 2003
+ *
+ * To change the template for this generated file go to
+ * Window>Preferences>Java>Code Generation>Code and Comments
+Copyright 2003 Joseph Barnett
+
+This File is part of "one 2 oh my god"
+
+"one 2 oh my god" is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+Free Software Foundation; either version 2 of the License, or
+your option) any later version.
+
+"one 2 oh my god" is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with "one 2 oh my god"; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ */
+package itunes;
+import java.io.*;
+import java.util.ArrayList;
+
+import itunes.client.request.Request;
+import itunes.client.Song;
+/**
+ * @author jbarnett
+ *
+ * To change the template for this generated type comment go to
+ * Window>Preferences>Java>Code Generation>Code and Comments
+ */
+public class FieldPair {
+ public String name;
+ public byte[] value;
+ public byte[] transmission;
+
+ public FieldPair(String name, int value) {
+ byte[] bytes = new byte[4];
+ enterInt(bytes, value, 0);
+ init(name,bytes,0,bytes.length);
+ }
+
+ public FieldPair(String name, Song s, String meta) {
+ String[] extraTags = meta.split(",");
+ FieldPair miid = new FieldPair("miid", s.id);
+ FieldPair minm = new FieldPair("minm", s.getName());
+ ArrayList songPairs = new ArrayList();
+ songPairs.add(miid); songPairs.add(minm);
+ for (int i = 0; i < extraTags.length; i++) {
+ // add FieldPairs for each meta tag
+ if (!extraTags[i].equals("dmap.itemid") && !extraTags[i].equals("dmap.itemname")) { //already do these
+ FieldPair newPair=new FieldPair(lookup(extraTags[i]), lookup(extraTags[i], s));
+ if (!newPair.name.equals("null"))
+ songPairs.add(newPair);
+ }
+ }
+ FieldPair[] array = new FieldPair[songPairs.size()];
+ System.arraycopy(songPairs.toArray(), 0, array, 0, array.length);
+ byte[] bytes = embed(array);
+ init(name,bytes,0,bytes.length);
+ }
+
+ public FieldPair(String name, FieldPair[] fields) {
+ byte[] bytes = embed(fields);
+ init(name,bytes,0,bytes.length);
+ }
+
+ public FieldPair(String name, byte[] value) {
+ init(name,value,0,value.length);
+ }
+
+ public FieldPair(String name, byte value) {
+ byte[] bytes = {value};
+ init(name,bytes,0,bytes.length);
+ }
+ public FieldPair(String name, byte[] value,int offset, int size) {
+ init(name,value,offset,size);
+ }
+ public FieldPair (String name, String value) {
+ init(name, value.getBytes(), 0, value.getBytes().length);
+ }
+
+ public void init(String name, byte[] value, int offset ,int size) {
+ this.name = name;
+ this.value = new byte[size];
+ try {
+ ByteArrayInputStream b = new ByteArrayInputStream(value,offset,size);
+ DataInputStream d = new DataInputStream(b);
+ d.readFully(this.value);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ transmission = getDaapBytes();
+ }
+
+ public String toString() {
+ String ret = name + " ";
+ for (int i = 0; i < value.length;i++) {
+ ret+= Integer.toHexString(0xFF&value[i]) + " ";
+ }
+ ret += "("+ Request.readString(value,0,value.length)+")";
+
+ return ret;
+ }
+
+ private byte[] getDaapBytes() {
+ byte[] bytes = new byte[4+value.length+name.length()];
+ System.arraycopy(name.getBytes(), 0, bytes, 0, name.length());
+ int length = value.length;
+ byte[] lengthBytes = new byte[4];
+ lengthBytes[3] = (byte)(length % 256);
+ length = length / 256;
+ lengthBytes[2] = (byte)(length % 256);
+ length = length / 256;
+ lengthBytes[1] = (byte)(length % 256);
+ length = length / 256;
+ lengthBytes[0] = (byte)(length % 256);
+ System.arraycopy(lengthBytes,0,bytes, name.length(), 4);
+ System.arraycopy(value, 0, bytes, name.length() + 4, value.length);
+ return bytes;
+ }
+
+ public boolean equals(Object o) {
+ if (FieldPair.class.isInstance(o)) {
+ return (((FieldPair)o).name.equals(this.name));
+ } else if (String.class.isInstance(o)) {
+ return ((String)o).equals(this.name);
+ } else return false;
+ }
+
+ public static void enterInt(byte[] data, int value, int offset) {
+ int temp = value;
+ for (int i = offset; i < offset + 4; i++) {
+ data[offset + 3 - i] = (byte)( temp % 256);
+ temp = temp / 256;
+ }
+ }
+
+ private static byte[] embed(FieldPair[] fields) {
+ int offset = 0;
+ int length = 0;
+ for (int i = 0; i < fields.length; i++) {
+ length += fields[i].transmission.length;
+ }
+ byte[] data = new byte[length];
+ for (int i = 0; i < fields.length; i++) {
+ System.arraycopy(fields[i].transmission, 0, data, offset, fields[i].transmission.length);
+ offset += fields[i].transmission.length;
+ }
+ return data;
+ }
+
+ private static String lookup(String meta) {
+ if (meta.equals("daap.songalbum")) {
+ return "asal";
+ } else if (meta.equals("daap.songartist")) {
+ return "asar";
+ } else if (meta.equals("daap.songtracknumber")) {
+ return "astn";
+ } else if (meta.equals("daap.songuserrating")) {
+ return "asur";
+ } else if (meta.equals("daap.songgenre")) {
+ return "asgn";
+ } else if (meta.equals("daap.songformat")) {
+ return "asfm";
+ } else if (meta.equals("daap.songtime")) {
+ return "astm";
+ }
+ return "null";
+ }
+
+ private static byte[] lookup(String meta, Song s) {
+ if (meta.equals("daap.songalbum")) {
+ return s.getAlbum().getBytes();
+ } else if (meta.equals("daap.songartist")) {
+ return s.getArtist().getBytes();
+ } else if (meta.equals("daap.songtracknumber")) {
+ byte[] intBytes = new byte[2];
+ intBytes[0] = (byte)(s.getTrack() / 256);
+ intBytes[1] = (byte)(s.getTrack() % 256);
+ return intBytes;
+ } else if (meta.equals("daap.songuserrating")) {
+ byte[] bytes = {(byte)0};
+ return bytes;
+ }else if (meta.equals("daap.songgenre")) {
+ return s.getGenre().getBytes();
+ } else if (meta.equals("daap.songformat")) {
+ return "mp3".getBytes();
+ } else if (meta.equals("daap.songtime")) {
+ byte[] intBytes = new byte[4];
+ enterInt(intBytes, s.getTime(), 0);
+ return intBytes;
+ }
+ return new byte[0];
+ }
+}
+
diff --git a/source/client/Database.java b/source/client/Database.java
new file mode 100644
index 0000000..630760b
--- /dev/null
+++ b/source/client/Database.java
@@ -0,0 +1,54 @@
+/*
+ * Created on May 8, 2003
+ *
+ * To change the template for this generated file go to
+ * Window>Preferences>Java>Code Generation>Code and Comments
+Copyright 2003 Joseph Barnett
+
+This File is part of "one 2 oh my god"
+
+"one 2 oh my god" is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+Free Software Foundation; either version 2 of the License, or
+your option) any later version.
+
+"one 2 oh my god" is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with "one 2 oh my god"; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ */
+package itunes.client;
+
+
+/**
+ * @author jbarnett
+ *
+ * To change the template for this generated type comment go to
+ * Window>Preferences>Java>Code Generation>Code and Comments
+ */
+public class Database implements Comparable {
+ public String name;
+ public int id;
+
+
+ public Database() {
+ name="";
+ id=0;
+ }
+
+ public int compareTo(Object o) {
+ if (Song.class.isInstance(o)) {
+ return this.toString().compareTo(((Song)o).toString());
+ } else throw new ClassCastException();
+ }
+
+ public String toString() {
+ return name;
+ }
+}
+
diff --git a/source/client/MusicProvider.java b/source/client/MusicProvider.java
new file mode 100644
index 0000000..4f12164
--- /dev/null
+++ b/source/client/MusicProvider.java
@@ -0,0 +1,52 @@
+/*
+ * Created on May 8, 2003
+ *
+ * To change the template for this generated file go to
+ * Window>Preferences>Java>Code Generation>Code and Comments
+Copyright 2003 Joseph Barnett
+
+This File is part of "one 2 oh my god"
+
+"one 2 oh my god" is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+Free Software Foundation; either version 2 of the License, or
+your option) any later version.
+
+"one 2 oh my god" is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with "one 2 oh my god"; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ */
+package itunes.client;
+
+/**
+ * @author jbarnett
+ *
+ * To change the template for this generated type comment go to
+ * Window>Preferences>Java>Code Generation>Code and Comments
+ */
+public class MusicProvider {
+
+ public String address;
+ public String name;
+
+ public MusicProvider(String address, String name) {
+ this.address = address;
+ this.name = name;
+ }
+
+ public String toString() {
+ return name;
+ }
+
+ public boolean equals(Object o) {
+ return name.equals(((MusicProvider)o).name);
+ }
+
+}
+
diff --git a/source/client/Song.java b/source/client/Song.java
new file mode 100644
index 0000000..1abe18a
--- /dev/null
+++ b/source/client/Song.java
@@ -0,0 +1,155 @@
+/*
+ * Created on May 7, 2003
+ *
+ * To change the template for this generated file go to
+ * Window>Preferences>Java>Code Generation>Code and Comments
+Copyright 2003 Joseph Barnett
+
+This File is part of "one 2 oh my god"
+
+"one 2 oh my god" is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+Free Software Foundation; either version 2 of the License, or
+your option) any later version.
+
+"one 2 oh my god" is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with "one 2 oh my god"; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ */
+package itunes.client;
+
+/**
+ * @author jbarnett
+ *
+ * To change the template for this generated type comment go to
+ * Window>Preferences>Java>Code Generation>Code and Comments
+ */
+public class Song implements Comparable{
+ public String name;
+ public int id;
+ public int time;
+ public String album;
+ public String artist;
+ public int track;
+ public String genre;
+ public int rating;
+ public String format;
+
+ public Song() {
+ name="";
+ id=0;
+ album = "";
+ artist = "";
+ track = 0;
+ genre = "";
+ rating = 0;
+ format = "";
+ }
+
+ public int compareTo(Object o) {
+ if (Song.class.isInstance(o)) {
+ if (this.artist.compareTo(((Song)o).artist) != 0) {
+ if (this.artist.matches(" *"))
+ return 1;
+ else if (((Song)o).artist.matches(" *"))
+ return -1;
+ return this.artist.compareTo(((Song)o).artist);
+ }else if (this.album.compareTo(((Song)o).album) != 0) {
+ if (this.album.matches(" *"))
+ return 1;
+ else if (((Song)o).album.matches(" *"))
+ return -1;
+ return this.album.compareTo(((Song)o).album);
+ }
+ else if (new Integer(this.track).compareTo(new Integer(((Song)o).track)) != 0)
+ return (new Integer(this.track).compareTo(new Integer(((Song)o).track)));
+ else
+ return this.name.compareTo(((Song)o).name);
+ } else throw new ClassCastException();
+ }
+
+ public String toString() {
+ String ret=artist + (artist.length()>0?" - ":"") + album+(album.length()>0?" ":"")+(track>0?" (Track":"")+(track>0?Integer.toString(track):"")+(track>0?") - ":"")+name +(genre.length()>0?" [":"")+genre+(genre.length()>0?"]":"");
+ for (int i = 0; i < rating/20; i++) {
+ ret += " *";
+ }
+ return ret;
+ }
+ /**
+ * @return
+ */
+ public String getAlbum() {
+ return album;
+ }
+
+ /**
+ * @return
+ */
+ public String getArtist() {
+ return artist;
+ }
+
+ /**
+ * @return
+ */
+ public String getFormat() {
+ return format;
+ }
+
+ /**
+ * @return
+ */
+ public String getGenre() {
+ return genre;
+ }
+
+ /**
+ * @return
+ */
+ public int getId() {
+ return id;
+ }
+
+ /**
+ * @return
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * @return
+ */
+ public int getRating() {
+ return rating;
+ }
+
+ /**
+ * @return
+ */
+ public int getTrack() {
+ return track;
+ }
+
+ /**
+ * @return
+ */
+ public int getTime() {
+ return time;
+ }
+
+ /**
+ * @param i
+ */
+ public void setTime(int i) {
+ time = i;
+ }
+
+}
+
diff --git a/source/client/request/ContentCodesRequest.java b/source/client/request/ContentCodesRequest.java
new file mode 100644
index 0000000..316900d
--- /dev/null
+++ b/source/client/request/ContentCodesRequest.java
@@ -0,0 +1,65 @@
+/*
+ * Created on May 7, 2003
+ *
+ * To change the template for this generated file go to
+ * Window>Preferences>Java>Code Generation>Code and Comments
+Copyright 2003 Joseph Barnett
+
+This File is part of "one 2 oh my god"
+
+"one 2 oh my god" is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+Free Software Foundation; either version 2 of the License, or
+your option) any later version.
+
+"one 2 oh my god" is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with "one 2 oh my god"; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ */
+package itunes.client.request;
+import itunes.*;
+
+import java.util.ArrayList;
+/**
+ * @author jbarnett
+ *
+ * To change the template for this generated type comment go to
+ * Window>Preferences>Java>Code Generation>Code and Comments
+ */
+public class ContentCodesRequest extends Request {
+ protected ArrayList mdclDataFields;
+
+ public ContentCodesRequest(String server, int port) throws NoServerPermissionException {
+ super(server, port, "content-codes");
+ }
+ protected void Process() throws NoServerPermissionException{
+ super.Process();
+ parseMDCL();
+ }
+
+ protected void parseMDCL() {
+ mdclDataFields = new ArrayList();
+ for (int i = 0; i < mdclIndexes.size(); i++) {
+ byte[] mdclData = ((FieldPair)fieldPairs.get(((Integer)mdclIndexes.get(i)).intValue())).value;
+ mdclDataFields.add(processDataFields(mdclData,0));
+ }
+ }
+
+ public String toString() {
+ String ret = super.toString();
+ for (int i=0; i < mdclDataFields.size();i++) {
+ ArrayList fps = ((ArrayList)mdclDataFields.get(i));
+ for (int j = 0; j < fps.size();j++) {
+ ret += ((FieldPair)fps.get(j)).toString() + "\n";
+ }
+ }
+ return ret;
+ }
+}
+
diff --git a/source/client/request/DatabasesRequest.java b/source/client/request/DatabasesRequest.java
new file mode 100644
index 0000000..965a97a
--- /dev/null
+++ b/source/client/request/DatabasesRequest.java
@@ -0,0 +1,121 @@
+/*
+ * Created on May 6, 2003
+ *
+ * To change the template for this generated file go to
+ * Window>Preferences>Java>Code Generation>Code and Comments
+Copyright 2003 Joseph Barnett
+
+This File is part of "one 2 oh my god"
+
+"one 2 oh my god" is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+Free Software Foundation; either version 2 of the License, or
+your option) any later version.
+
+"one 2 oh my god" is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with "one 2 oh my god"; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+ */
+package itunes.client.request;
+import itunes.*;
+import itunes.client.*;
+
+import java.util.ArrayList;
+/**
+ * @author jbarnett
+ *
+ * To change the template for this generated type comment go to
+ * Window>Preferences>Java>Code Generation>Code and Comments
+ */
+public class DatabasesRequest extends Request {
+
+ protected ArrayList mlclDataFields;
+ protected ArrayList mlitDataFields;
+
+ public DatabasesRequest(String server, int port, int sessionId) throws NoServerPermissionException{
+ super(server, port, "databases?session-id="+sessionId);
+ }
+
+ public DatabasesRequest(String server, int port, String rs) throws NoServerPermissionException{
+ super(server, port, rs);
+ }
+ protected void Process() throws NoServerPermissionException {
+ super.Process();
+ parseMLCL();
+ }
+
+ protected void parseMLCL() {
+ for (int i = 0; i < mlclIndexes.size(); i++) {
+ byte[] mlclData = ((FieldPair)fieldPairs.get(((Integer)mlclIndexes.get(i)).intValue())).value;
+ mlclDataFields = this.processDataFields(mlclData,0);
+ }
+ parseMLIT();
+ }
+
+ protected void parseMLIT() {
+ mlitDataFields = new ArrayList();
+ for (int i = 0; i < mlitIndexes.size(); i++) {
+ byte[] mlitData = ((FieldPair)mlclDataFields.get(((Integer)mlitIndexes.get(i)).intValue())).value;
+ mlitDataFields.add(processDataFields(mlitData,0));
+ }
+ }
+
+ public int getLibraryCount() {
+ return mlclDataFields.size();
+ }
+
+ public int getDbId(int i) {
+ ArrayList currMlitDataFields = ((ArrayList)mlitDataFields.get(i));
+ int index = currMlitDataFields.indexOf(new FieldPair("miid",null,0,0));
+ FieldPair fp = (FieldPair)currMlitDataFields.get(index);
+ return Request.readInt(fp.value,0);
+ }
+
+ public int getSongCount(int i) {
+ ArrayList currMlitDataFields = ((ArrayList)mlitDataFields.get(i));
+ int index = currMlitDataFields.indexOf(new FieldPair("mimc",null,0,0));
+ FieldPair fp = (FieldPair)currMlitDataFields.get(index);
+ return Request.readInt(fp.value,0);
+ }
+
+ public ArrayList getDbs() {
+ ArrayList dbs = new ArrayList();
+ for (int i = 0; i < mlitDataFields.size();i++) {
+ ArrayList fps = ((ArrayList)mlitDataFields.get(i));
+ String name=null;
+ int id=0;
+ Database d = new Database();
+ for (int j = 0; j < fps.size();j++) {
+ FieldPair fp =((FieldPair)fps.get(j));
+ if (fp.name.equals("miid")) {
+ d.id = Request.readInt(fp.value,0);
+ } else if (fp.name.equals("minm")) {
+ d.name = Request.readString(fp.value,0,fp.value.length);
+ }
+ }
+ dbs.add(d);
+ }
+ return dbs;
+ }
+
+ public String toString() {
+ String ret = super.toString();
+ for (int i = 0; i < mlclDataFields.size();i++) {
+ ret += ((FieldPair)mlclDataFields.get(i)).toString() + "\n";
+ }
+ for (int i=0; i < mlitDataFields.size();i++) {
+ ArrayList fps = ((ArrayList)mlitDataFields.get(i));
+ for (int j = 0; j < fps.size();j++) {
+ ret += ((FieldPair)fps.get(j)).toString() + "\n";
+ }
+ }
+ return ret;
+ }
+}
diff --git a/source/client/request/LoginRequest.java b/source/client/request/LoginRequest.java
new file mode 100644
index 0000000..59b1857
--- /dev/null
+++ b/source/client/request/LoginRequest.java
@@ -0,0 +1,49 @@
+/*
+ * Created on May 6, 2003
+ *
+ * To change the template for this generated file go to
+ * Window>Preferences>Java>Code Generation>Code and Comments
+Copyright 2003 Joseph Barnett
+
+This File is part of "one 2 oh my god"
+
+"one 2 oh my god" is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+Free Software Foundation; either version 2 of the License, or
+your option) any later version.
+
+"one 2 oh my god" is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with "one 2 oh my god"; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+ */
+package itunes.client.request;
+
+import itunes.*;
+
+/**
+ * @author jbarnett
+ *
+ * To change the template for this generated type comment go to
+ * Window>Preferences>Java>Code Generation>Code and Comments
+ */
+public class LoginRequest extends Request {
+
+ public LoginRequest(String server, int port) throws NoServerPermissionException {
+ super(server, port, "login");
+ }
+
+ public int getSessionId() {
+ int index = fieldPairs.indexOf(new FieldPair("mlid",new byte[0],0,0));
+ if (index == -1)
+ return index;
+ FieldPair fp = (FieldPair)fieldPairs.get(index);
+ return readInt(fp.value,0);
+ }
+}
diff --git a/source/client/request/LogoutRequest.java b/source/client/request/LogoutRequest.java
new file mode 100644
index 0000000..c18d9ac
--- /dev/null
+++ b/source/client/request/LogoutRequest.java
@@ -0,0 +1,42 @@
+/*
+ * Created on May 6, 2003
+ *
+ * To change the template for this generated file go to
+ * Window>Preferences>Java>Code Generation>Code and Comments
+Copyright 2003 Joseph Barnett
+
+This File is part of "one 2 oh my god"
+
+"one 2 oh my god" is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+Free Software Foundation; either version 2 of the License, or
+your option) any later version.
+
+"one 2 oh my god" is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with "one 2 oh my god"; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+ */
+package itunes.client.request;
+
+/**
+ * @author jbarnett
+ *
+ * To change the template for this generated type comment go to
+ * Window>Preferences>Java>Code Generation>Code and Comments
+ */
+public class LogoutRequest extends Request {
+
+ protected int sessionId;
+
+ public LogoutRequest(String server, int port, int sid) throws NoServerPermissionException{
+ super(server, port,("logout?session-id="+sid));
+ }
+
+}
diff --git a/source/client/request/NoServerPermissionException.java b/source/client/request/NoServerPermissionException.java
new file mode 100644
index 0000000..b8c179b
--- /dev/null
+++ b/source/client/request/NoServerPermissionException.java
@@ -0,0 +1,41 @@
+/*
+ * Created on May 8, 2003
+ *
+ * To change the template for this generated file go to
+ * Window>Preferences>Java>Code Generation>Code and Comments
+Copyright 2003 Joseph Barnett
+
+This File is part of "one 2 oh my god"
+
+"one 2 oh my god" is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+Free Software Foundation; either version 2 of the License, or
+your option) any later version.
+
+"one 2 oh my god" is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with "one 2 oh my god"; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+ */
+package itunes.client.request;
+
+/**
+ * @author jbarnett
+ *
+ * To change the template for this generated type comment go to
+ * Window>Preferences>Java>Code Generation>Code and Comments
+ */
+public class NoServerPermissionException extends Exception {
+
+
+ public NoServerPermissionException() {
+ super("Error downloading song ");
+ }
+
+}
diff --git a/source/client/request/Request.java b/source/client/request/Request.java
new file mode 100644
index 0000000..2c54972
--- /dev/null
+++ b/source/client/request/Request.java
@@ -0,0 +1,225 @@
+/*
+ * Created on May 6, 2003
+ *
+ * To change the template for this generated file go to
+ * Window>Preferences>Java>Code Generation>Code and Comments
+Copyright 2003 Joseph Barnett
+
+This File is part of "one 2 oh my god"
+
+"one 2 oh my god" is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+Free Software Foundation; either version 2 of the License, or
+your option) any later version.
+
+"one 2 oh my god" is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with "one 2 oh my god"; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ */
+package itunes.client.request;
+
+import itunes.*;
+import itunes.util.Hasher;
+
+import java.net.*;
+import java.io.*;
+import java.util.ArrayList;
+/**
+ * @author jbarnett
+ *
+ * To change the template for this generated type comment go to
+ * Window>Preferences>Java>Code Generation>Code and Comments
+ */
+public abstract class Request {
+ public static final int ITUNES_PORT = 3689;
+ public static boolean debug = false;
+ protected String server;
+ protected int port;
+ public byte[] data;
+ protected int offset;
+ protected int expectedLength;
+ protected String dataType;
+ protected ArrayList fieldPairs;
+ protected ArrayList mlitIndexes;
+ protected ArrayList mlclIndexes;
+ protected ArrayList mdclIndexes;
+ protected String requestString;
+
+
+ public Request(String server, int port, String rs) throws NoServerPermissionException {
+ this.server = server;
+ this.port = port;
+ dataType = "";
+ offset = 0;
+ fieldPairs = new ArrayList();
+ mlitIndexes = new ArrayList();
+ mlclIndexes = new ArrayList();
+ mdclIndexes = new ArrayList();
+ requestString = rs;
+ Query();
+ Process();
+ }
+
+ protected void Query() throws NoServerPermissionException {
+ URL url =null;
+ try {
+ url = new URL("http://"+server+":"+port+"/"+requestString);
+ if (debug)
+ System.out.println("Processing Request: "+ server+":"+port+"/"+requestString);
+ URLConnection urlc = url.openConnection();
+ String hashCode = Hasher.GenerateHash("/" + requestString,1);
+ urlc.addRequestProperty("Client-DAAP-Validation", hashCode);
+ urlc.addRequestProperty("Client-DAAP-Access-Index", "1");
+
+ DataInputStream in = new DataInputStream(urlc.getInputStream());
+ int len = urlc.getContentLength();
+ if (len == -1) {
+ return;
+ }
+ data = new byte[len];
+ in.readFully(data);
+ } catch (MalformedURLException e) {
+ if (debug)
+ System.out.println("Malformed URL");
+ } catch (IOException ioe) {
+ if (debug)
+ System.out.println(ioe.getLocalizedMessage());
+ throw new NoServerPermissionException();
+ }
+ }
+
+ protected static int readSize(String data) {
+ return readSize(data, 4);
+ }
+
+ protected static int readSize(String data, int j) {
+ String elength = "";
+ for (int i = 0; i < j; i++) {
+ elength += ((int)data.charAt(i)>15?"":"0") + Integer.toHexString((int)data.charAt(i));
+ }
+ return Integer.valueOf(elength,16).intValue();
+ }
+
+ protected String dataString(int i) {
+ return readString(data,offset,i);
+ }
+
+ public static String readString(byte[] data, int offset, int i) {
+ String a = "";
+ try {
+ a = new String(data, offset,i,"UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ e.printStackTrace();
+ }
+ return a;
+ }
+
+ protected int dataInt() {
+ return readInt(data, offset,4);
+ }
+
+ protected static int readInt(byte[] data, int offset) {
+ int i = 0;
+ try {
+ ByteArrayInputStream b = new ByteArrayInputStream(data, offset, 4);
+ DataInputStream d = new DataInputStream(b);
+ i = d.readInt();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return i;
+ }
+
+ public static int readInt(byte[] data, int offset, int size) {
+ int i = 0;
+ try {
+ ByteArrayInputStream b = new ByteArrayInputStream(data, offset, size);
+ DataInputStream d = new DataInputStream(b);
+ int pow = size*2 - 1;
+ for (int j = 0;j<size;j++) {
+ int num = (0xFF&d.readByte());
+ int up = ((int)Math.pow(16,pow))*(num/16);
+ pow--;
+ int down= ((int)Math.pow(16,pow))*(num%16);
+ i+= up + down;
+ pow--;
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return i;
+ }
+
+ protected void Process() throws NoServerPermissionException {
+ if (data==null || data.length==0) {
+ return;
+ }
+ dataType= dataString(4);
+ offset += 4;
+ int size = dataInt();
+ offset += 4;
+
+ fieldPairs = processDataFields();
+ }
+
+ protected ArrayList processDataFields(byte[] data, int offset) {
+ ArrayList fieldPairs = new ArrayList();
+ while (offset < data.length) {
+ String name="";
+ name = readString(data,offset,4);
+ offset +=4;
+ int size=readInt(data,offset);
+ offset+=4;
+ FieldPair fp = new FieldPair(name, data, offset, size);
+ offset += size;
+ fieldPairs.add(fp);
+ if (name.equals("mlcl")) {
+ mlclIndexes.add(new Integer(fieldPairs.size()-1));
+ } else if (name.equals("mlit")) {
+ mlitIndexes.add(new Integer(fieldPairs.size()-1));
+ } else if (name.equals("mdcl")) {
+ mdclIndexes.add(new Integer(fieldPairs.size()-1));
+ }
+ }
+ return fieldPairs;
+ }
+
+ protected ArrayList processDataFields() {
+ return processDataFields(data,offset);
+// ArrayList fieldPairs = new ArrayList();
+// while (offset < data.length) {
+// String name="";
+// name = dataString(4);
+// offset +=4;
+// int size=dataInt();
+// offset+=4;
+// FieldPair fp = new FieldPair(name, data, offset, size);
+// offset += size;
+// fieldPairs.add(fp);
+// if (name.equals("mlcl")) {
+// mlclIndexes.add(new Integer(fieldPairs.size()-1));
+// } else if (name.equals("mlit")) {
+// mlitIndexes.add(new Integer(fieldPairs.size()-1));
+// } else if (name.equals("mdcl")) {
+// mdclIndexes.add(new Integer(fieldPairs.size()-1));
+// }
+// }
+// return fieldPairs;
+ }
+
+ public String toString() {
+ String ret = "";
+ for (int i = 0; i < fieldPairs.size();i++) {
+ FieldPair fp = (FieldPair)fieldPairs.get(i);
+ ret += fp.toString()+"\n";
+ }
+ return ret;
+ }
+}
+
diff --git a/source/client/request/ServerInfoRequest.java b/source/client/request/ServerInfoRequest.java
new file mode 100644
index 0000000..048ed91
--- /dev/null
+++ b/source/client/request/ServerInfoRequest.java
@@ -0,0 +1,46 @@
+/*
+ * Created on May 6, 2003
+ *
+ * To change the template for this generated file go to
+ * Window>Preferences>Java>Code Generation>Code and Comments
+Copyright 2003 Joseph Barnett
+
+This File is part of "one 2 oh my god"
+
+"one 2 oh my god" is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+Free Software Foundation; either version 2 of the License, or
+your option) any later version.
+
+"one 2 oh my god" is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with "one 2 oh my god"; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+ */
+package itunes.client.request;
+import itunes.FieldPair;
+/**
+ * @author jbarnett
+ *
+ * To change the template for this generated type comment go to
+ * Window>Preferences>Java>Code Generation>Code and Comments
+ */
+public class ServerInfoRequest extends Request {
+
+ public ServerInfoRequest(String server, int port) throws NoServerPermissionException {
+ super(server,port, "server-info");
+ }
+ public double getServerVersion() {
+ int index = fieldPairs.indexOf(new FieldPair("mpro",new byte[0],0,0));
+ if (index == -1)
+ return index;
+ FieldPair fp = (FieldPair)fieldPairs.get(index);
+ return readInt(fp.value,0,2) + (0.01*readInt(fp.value,2,2));
+ }
+}
diff --git a/source/client/request/SingleDatabaseRequest.java b/source/client/request/SingleDatabaseRequest.java
new file mode 100644
index 0000000..2a82935
--- /dev/null
+++ b/source/client/request/SingleDatabaseRequest.java
@@ -0,0 +1,76 @@
+/*
+ * Created on May 6, 2003
+ *
+ * To change the template for this generated file go to
+ * Window>Preferences>Java>Code Generation>Code and Comments
+Copyright 2003 Joseph Barnett
+
+This File is part of "one 2 oh my god"
+
+"one 2 oh my god" is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+Free Software Foundation; either version 2 of the License, or
+your option) any later version.
+
+"one 2 oh my god" is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with "one 2 oh my god"; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ */
+package itunes.client.request;
+import itunes.*;
+import itunes.client.*;
+
+import java.util.ArrayList;
+/**
+ * @author jbarnett
+ *
+ * To change the template for this generated type comment go to
+ * Window>Preferences>Java>Code Generation>Code and Comments
+ */
+public class SingleDatabaseRequest extends DatabasesRequest {
+
+
+ public SingleDatabaseRequest(String server, int port, int sessionId, int dbId) throws NoServerPermissionException {
+ super(server, port, "databases/"+dbId+"/items?session-id="+sessionId+"&meta=dmap.itemid,dmap.itemname,daap.songalbum,daap.songartist,daap.songtracknumber,daap.songuserrating,daap.songgenre,daap.songformat,daap.songtime");
+ }
+ public ArrayList getSongs() {
+ ArrayList songs = new ArrayList();
+ for (int i = 0; i < mlitDataFields.size();i++) {
+ ArrayList fps = ((ArrayList)mlitDataFields.get(i));
+ String name=null;
+ int id=0;
+ Song s = new Song();
+ for (int j = 0; j < fps.size();j++) {
+ FieldPair fp =((FieldPair)fps.get(j));
+ if (fp.name.equals("miid")) {
+ s.id = Request.readInt(fp.value,0,4);
+ } else if (fp.name.equals("minm")) {
+ s.name = Request.readString(fp.value,0,fp.value.length);
+ } else if (fp.name.equals("asal")) {
+ s.album = Request.readString(fp.value,0,fp.value.length);
+ } else if (fp.name.equals("asar")) {
+ s.artist = Request.readString(fp.value,0,fp.value.length);
+ } else if (fp.name.equals("astn")) {
+ s.track = Request.readInt(fp.value, 0,2);
+ } else if (fp.name.equals("asgn")) {
+ s.genre = Request.readString(fp.value,0,fp.value.length);
+ } else if (fp.name.equals("asur")) {
+ s.rating = Request.readInt(fp.value,0,1);
+ } else if (fp.name.equals("asfm")) {
+ s.format = Request.readString(fp.value,0,fp.value.length);
+ } else if (fp.name.equals("astm")) {
+ s.time = Request.readInt(fp.value,0,4);
+ }
+ }
+ songs.add(s);
+ }
+ return songs;
+ }
+}
+
diff --git a/source/client/request/SongRequest.java b/source/client/request/SongRequest.java
new file mode 100644
index 0000000..9210280
--- /dev/null
+++ b/source/client/request/SongRequest.java
@@ -0,0 +1,87 @@
+/*
+ * Created on May 7, 2003
+ *
+ * To change the template for this generated file go to
+ * Window>Preferences>Java>Code Generation>Code and Comments
+Copyright 2003 Joseph Barnett
+
+This File is part of "one 2 oh my god"
+
+"one 2 oh my god" is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+Free Software Foundation; either version 2 of the License, or
+your option) any later version.
+
+"one 2 oh my god" is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with "one 2 oh my god"; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ */
+package itunes.client.request;
+import itunes.util.Hasher;
+
+import java.io.BufferedInputStream;
+import java.io.DataInputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLConnection;
+
+/**
+ * @author jbarnett
+ *
+ * To change the template for this generated type comment go to
+ * Window>Preferences>Java>Code Generation>Code and Comments
+ */
+public class SongRequest extends Request {
+ protected BufferedInputStream b;
+
+ public SongRequest(String server, int port, int dbId, int songId, String songFmt, int sessionId) throws NoServerPermissionException {
+ super(server, port, "databases/"+dbId+"/items/"+songId+"."+songFmt+"?session-id="+sessionId);
+ }
+
+ protected void Query() throws NoServerPermissionException {
+ URL url =null;
+ try {
+ url = new URL("http://"+server+":"+port+"/"+requestString);
+ if (Request.debug)
+ System.out.println("Processing Request: "+ server+":"+port+"/"+requestString);
+ URLConnection urlc = url.openConnection();
+ String hashCode = Hasher.GenerateHash("/" + requestString,1);
+ urlc.addRequestProperty("Client-DAAP-Validation", hashCode);
+ urlc.addRequestProperty("Client-DAAP-Access-Index", "1");
+ int len = urlc.getContentLength();
+ b = new BufferedInputStream(urlc.getInputStream());
+ if (len == -1) {
+ return;
+ } else if (len == 0) {
+ throw new NoServerPermissionException();
+ }
+ } catch (MalformedURLException e) {
+ if (Request.debug)
+ System.out.println("Malformed URL");
+ } catch (IOException ioe) {
+ if (Request.debug)
+ System.out.println(ioe.getLocalizedMessage());
+ throw new NoServerPermissionException();
+ }
+ }
+
+ protected void Process() throws NoServerPermissionException{
+ return;
+ // if (data.length == 0) {
+ // throw new NoServerPermissionException();
+ // }
+ }
+
+ public InputStream getStream() {
+ return b;
+ }
+}
+
diff --git a/source/client/swing/Player.java b/source/client/swing/Player.java
new file mode 100644
index 0000000..7783544
--- /dev/null
+++ b/source/client/swing/Player.java
@@ -0,0 +1,59 @@
+package itunes.client.swing;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import javax.swing.JOptionPane;
+
+import itunes.client.swing.ZPlayer;
+public class Player extends Thread {
+ private javazoom.jl.player.Player p;
+ private ZPlayer prog;
+
+ public Player(ZPlayer prog, String fileName) {
+ this.prog = prog;
+ FileInputStream f=null;
+ try {
+ f = new FileInputStream(fileName);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ newPlayer(f);
+ }
+
+ private void newPlayer(InputStream f) {
+ if (p != null)
+ this.stopMusic();
+ try{
+ p = new javazoom.jl.player.Player(f);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public Player(ZPlayer prog, InputStream f) {
+ this.prog = prog;
+ newPlayer(f);
+ }
+
+ public void run() {
+ try {
+ p.play();
+ } catch (javazoom.jl.decoder.BitstreamException be) {
+ JOptionPane.showMessageDialog(prog.frame,"Unsupported file format!\n"+be.getLocalizedMessage());
+ prog.stopPlaying();
+ }catch (Exception e) {
+ e.printStackTrace();
+ prog.stopPlaying();
+ }
+ if (p.isComplete()) {
+ prog.playNext(1);
+ }
+ }
+
+ public int getPosition() {
+ return p.getPosition();
+ }
+
+ public void stopMusic() {
+ p.close();
+ }
+}
diff --git a/source/client/swing/SongTableModel.java b/source/client/swing/SongTableModel.java
new file mode 100644
index 0000000..d4bc78c
--- /dev/null
+++ b/source/client/swing/SongTableModel.java
@@ -0,0 +1,103 @@
+/*
+ * Created on May 8, 2003
+ *
+ * To change the template for this generated file go to
+ * Window>Preferences>Java>Code Generation>Code and Comments
+ *
+ * Copyright 2003 Joseph Barnett
+
+This File is part of "one 2 oh my god"
+
+"one 2 oh my god" is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+Free Software Foundation; either version 2 of the License, or
+your option) any later version.
+
+"one 2 oh my god" is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with "one 2 oh my god"; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ */
+package itunes.client.swing;
+
+import itunes.client.*;
+
+import javax.swing.table.AbstractTableModel;
+import java.util.ArrayList;
+
+/**
+ * @author jbarnett
+ *
+ * To change the template for this generated type comment go to
+ * Window>Preferences>Java>Code Generation>Code and Comments
+ */
+public class SongTableModel extends AbstractTableModel {
+ public final String[] columnNames = {"Artist","Album","Title","Track","Time"};
+ public ArrayList data;
+
+ public SongTableModel() {
+ super();
+ data = new ArrayList();
+ }
+
+ public String getColumnName(int col) {
+ return columnNames[col];
+ }
+
+ public void clear() {
+ data = new ArrayList();
+ }
+
+ public void AddRow(Song s) {
+ Object[] a = new Object[7];
+ a[0] = s.artist;
+ a[1] = s.album;
+ a[2] = s.name;
+ a[3] = new Integer(s.track);
+ int totalseconds = s.getTime();
+ if(totalseconds > 999)
+ {
+ totalseconds /= 1000;
+ }
+ int minutes = totalseconds / 60;
+ int seconds = totalseconds - minutes*60;
+ a[4] = (minutes == 0 && seconds == 0) ? "???" : ((minutes<10)?"0":"") + minutes + ":" + ((seconds<10)?"0":"") + seconds;
+ a[5] = Integer.toString(s.id);
+ a[6] = s.format;
+ data.add(a);
+ }
+
+ public int getRowCount() {
+ return data.size();
+ }
+
+ public int getColumnCount() {
+ return columnNames.length;
+ }
+
+ public Class getColumnClass(int c) {
+ return getValueAt(0, c).getClass();
+ }
+
+ public Object getValueAt(int rowIndex, int columnIndex) {
+ return ((Object[])data.get(rowIndex))[columnIndex];
+ }
+ public String getArtistAt(int row) {
+ return (String)getValueAt(row,0);
+ }
+
+ public String getAlbumAt(int row) {
+ return (String)getValueAt(row,1);
+ }
+
+ public String getSongNameAt(int row) {
+ return (String)getValueAt(row,2);
+ }
+
+}
+
diff --git a/source/client/swing/SwingWorker.java b/source/client/swing/SwingWorker.java
new file mode 100644
index 0000000..d52a0e5
--- /dev/null
+++ b/source/client/swing/SwingWorker.java
@@ -0,0 +1,133 @@
+package itunes.client.swing;
+
+import javax.swing.SwingUtilities;
+
+/**
+ * This is the 3rd version of SwingWorker (also known as
+ * SwingWorker 3), an abstract class that you subclass to
+ * perform GUI-related work in a dedicated thread. For
+ * instructions on using this class, see:
+ *
+ * http://java.sun.com/docs/books/tutorial/uiswing/misc/threads.html
+ *
+ * Note that the API changed slightly in the 3rd version:
+ * You must now invoke start() on the SwingWorker after
+ * creating it.
+ */
+public abstract class SwingWorker {
+ private Object value; // see getValue(), setValue()
+ private Thread thread;
+
+ /**
+ * Class to maintain reference to current worker thread
+ * under separate synchronization control.
+ */
+ private static class ThreadVar {
+ private Thread thread;
+ ThreadVar(Thread t) { thread = t; }
+ synchronized Thread get() { return thread; }
+ synchronized void clear() { thread = null; }
+ }
+
+ private ThreadVar threadVar;
+
+ /**
+ * Get the value produced by the worker thread, or null if it
+ * hasn't been constructed yet.
+ */
+ protected synchronized Object getValue() {
+ return value;
+ }
+
+ /**
+ * Set the value produced by worker thread
+ */
+ private synchronized void setValue(Object x) {
+ value = x;
+ }
+
+ /**
+ * Compute the value to be returned by the <code>get</code> method.
+ */
+ public abstract Object construct();
+
+ /**
+ * Called on the event dispatching thread (not on the worker thread)
+ * after the <code>construct</code> method has returned.
+ */
+ public void finished() {
+ }
+
+ /**
+ * A new method that interrupts the worker thread. Call this method
+ * to force the worker to stop what it's doing.
+ */
+ public void interrupt() {
+ Thread t = threadVar.get();
+ if (t != null) {
+ t.interrupt();
+ }
+ threadVar.clear();
+ }
+
+ /**
+ * Return the value created by the <code>construct</code> method.
+ * Returns null if either the constructing thread or the current
+ * thread was interrupted before a value was produced.
+ *
+ * @return the value created by the <code>construct</code> method
+ */
+ public Object get() {
+ while (true) {
+ Thread t = threadVar.get();
+ if (t == null) {
+ return getValue();
+ }
+ try {
+ t.join();
+ }
+ catch (InterruptedException e) {
+ Thread.currentThread().interrupt(); // propagate
+ return null;
+ }
+ }
+ }
+
+
+ /**
+ * Start a thread that will call the <code>construct</code> method
+ * and then exit.
+ */
+ public SwingWorker() {
+ final Runnable doFinished = new Runnable() {
+ public void run() { finished(); }
+ };
+
+ Runnable doConstruct = new Runnable() {
+ public void run() {
+ try {
+ setValue(construct());
+ }
+ finally {
+ threadVar.clear();
+ }
+
+ SwingUtilities.invokeLater(doFinished);
+ }
+ };
+
+ Thread t = new Thread(doConstruct);
+ threadVar = new ThreadVar(t);
+ }
+
+ /**
+ * Start the worker thread.
+ */
+ public void start() {
+ Thread t = threadVar.get();
+ if (t != null) {
+ t.start();
+ }
+ }
+}
+
diff --git a/source/client/swing/TableMap.java b/source/client/swing/TableMap.java
new file mode 100644
index 0000000..fa85aa9
--- /dev/null
+++ b/source/client/swing/TableMap.java
@@ -0,0 +1,70 @@
+package itunes.client.swing;
+
+/**
+ * In a chain of data manipulators some behaviour is common. TableMap
+ * provides most of this behavour and can be subclassed by filters
+ * that only need to override a handful of specific methods. TableMap
+ * implements TableModel by routing all requests to its model, and
+ * TableModelListener by routing all events to its listeners. Inserting
+ * a TableMap which has not been subclassed into a chain of table filters
+ * should have no effect.
+ *
+ * @version 1.4 12/17/97
+ * @author Philip Milne */
+
+import javax.swing.table.*;
+import javax.swing.event.TableModelListener;
+import javax.swing.event.TableModelEvent;
+
+public class TableMap extends AbstractTableModel
+ implements TableModelListener {
+ protected TableModel model;
+
+ public TableModel getModel() {
+ return model;
+ }
+
+ public void setModel(TableModel model) {
+ this.model = model;
+ model.addTableModelListener(this);
+ }
+
+ // By default, implement TableModel by forwarding all messages
+ // to the model.
+
+ public Object getValueAt(int aRow, int aColumn) {
+ return model.getValueAt(aRow, aColumn);
+ }
+
+ public void setValueAt(Object aValue, int aRow, int aColumn) {
+ model.setValueAt(aValue, aRow, aColumn);
+ }
+
+ public int getRowCount() {
+ return (model == null) ? 0 : model.getRowCount();
+ }
+
+ public int getColumnCount() {
+ return (model == null) ? 0 : model.getColumnCount();
+ }
+
+ public String getColumnName(int aColumn) {
+ return model.getColumnName(aColumn);
+ }
+
+ public Class getColumnClass(int aColumn) {
+ return model.getColumnClass(aColumn);
+ }
+
+ public boolean isCellEditable(int row, int column) {
+ return model.isCellEditable(row, column);
+ }
+//
+// Implementation of the TableModelListener interface,
+//
+ // By default forward all events to all the listeners.
+ public void tableChanged(TableModelEvent e) {
+ fireTableChanged(e);
+ }
+}
+
diff --git a/source/client/swing/TableSorter.java b/source/client/swing/TableSorter.java
new file mode 100644
index 0000000..f8b2a40
--- /dev/null
+++ b/source/client/swing/TableSorter.java
@@ -0,0 +1,432 @@
+package itunes.client.swing;
+
+/**
+ * A sorter for TableModels. The sorter has a model (conforming to TableModel)
+ * and itself implements TableModel. TableSorter does not store or copy
+ * the data in the TableModel, instead it maintains an array of
+ * integers which it keeps the same size as the number of rows in its
+ * model. When the model changes it notifies the sorter that something
+ * has changed eg. "rowsAdded" so that its internal array of integers
+ * can be reallocated. As requests are made of the sorter (like
+ * getValueAt(row, col) it redirects them to its model via the mapping
+ * array. That way the TableSorter appears to hold another copy of the table
+ * with the rows in a different order. The sorting algorthm used is stable
+ * which means that it does not move around rows when its comparison
+ * function returns 0 to denote that they are equivalent.
+ *
+ * @version 1.5 12/17/97
+ * @author Philip Milne
+ */
+
+import java.util.*;
+
+import javax.swing.table.TableModel;
+import javax.swing.event.TableModelEvent;
+
+// Imports for picking up mouse events from the JTable.
+
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.event.InputEvent;
+import javax.swing.JTable;
+import javax.swing.JTextField;
+import javax.swing.table.JTableHeader;
+import javax.swing.table.TableColumnModel;
+
+public class TableSorter extends TableMap {
+ int indexes[];
+
+ protected int numElements;
+
+ int fullIndex[];
+ Vector sortingColumns = new Vector();
+ boolean ascending = true;
+ int compares;
+ protected int currColumn;
+ protected boolean currAscending;
+ protected String filter;
+
+ public TableSorter() {
+
+ indexes = new int[0]; // for consistency
+ currColumn = -1;
+ currAscending = true;
+ checkModel();
+ }
+
+ public TableSorter(TableModel model) {
+ setModel(model);
+ currColumn = -1;
+ currAscending = true;
+ }
+
+ public void setModel(TableModel model) {
+ super.setModel(model);
+ filter = "";
+ reallocateIndexes();
+ loadFullIndex();
+ }
+ public void reFilter(JTextField field) {
+ filter = field.getText().toLowerCase();
+ decideFiltering();
+ super.tableChanged(new TableModelEvent(this));
+ }
+ protected void decideFiltering()
+ {
+ if (filter.equals(""))
+ loadFullIndex();
+ else
+ findFilter();
+ }
+ protected boolean presentInRow(String[] tokens, int row)
+ {
+ String artist = getArtistAt(row).toLowerCase();
+ String album = getAlbumAt(row).toLowerCase();
+ String song = getSongAt(row).toLowerCase();
+ for (int i = 0; i < tokens.length; i++){
+ if (artist.indexOf(tokens[i])==-1 && album.indexOf(tokens[i])==-1 && song.indexOf(tokens[i])==-1){
+ return false;
+ }
+ }
+ return true;
+ }
+ public int getFullIndexRow(int filteredRow)
+ {
+ if(filteredRow < 0 || filteredRow >= numElements)
+ {
+ return -1;
+ }
+ return indexes[filteredRow];
+ }
+ public int getFilteredIndexRow(int fullRow)
+ {
+ for(int i = 0; i < numElements; i++)
+ {
+ if(indexes[i] == fullRow)
+ {
+ return i;
+ }
+ }
+ return -1;
+ }
+ public String getArtistAt(int row) {
+ checkModel();
+ return ((SongTableModel)model).getArtistAt(indexes[row]);
+ }
+
+ public String getAlbumAt(int row) {
+ checkModel();
+ return ((SongTableModel)model).getAlbumAt(indexes[row]);
+ }
+
+ public String getSongAt(int row) {
+ checkModel();
+ return ((SongTableModel)model).getSongNameAt(indexes[row]);
+ }
+ protected void findFilter()
+ {
+ indexes = fullIndex;
+ int temp[] = new int[indexes.length];
+ int j = 0;
+
+ String[] tokens = filter.split(" +");
+ for (int i = 0; i < indexes.length; i++){
+ if (presentInRow(tokens, i)){
+ temp[j] = indexes[i];
+ ++j;
+ }
+ }
+ indexes = temp;
+ numElements = j;
+ }
+ public void loadFullIndex()
+ {
+ indexes = fullIndex;
+ numElements = indexes.length;
+ }
+ public int compareRowsByColumn(int row1, int row2, int column) {
+ Class type = model.getColumnClass(column);
+ TableModel data = model;
+
+ // Check for nulls.
+
+ Object o1 = data.getValueAt(row1, column);
+ Object o2 = data.getValueAt(row2, column);
+
+ // If both values are null, return 0.
+ if (o1 == null && o2 == null) {
+ return 0;
+ } else if (o1 == null) { // Define null less than everything.
+ return -1;
+ } else if (o2 == null) {
+ return 1;
+ }
+
+ /*
+ * We copy all returned values from the getValue call in case
+ * an optimised model is reusing one object to return many
+ * values. The Number subclasses in the JDK are immutable and
+ * so will not be used in this way but other subclasses of
+ * Number might want to do this to save space and avoid
+ * unnecessary heap allocation.
+ */
+
+ if (type.getSuperclass() == java.lang.Number.class) {
+ Number n1 = (Number)data.getValueAt(row1, column);
+ double d1 = n1.doubleValue();
+ Number n2 = (Number)data.getValueAt(row2, column);
+ double d2 = n2.doubleValue();
+
+ if (d1 < d2) {
+ return -1;
+ } else if (d1 > d2) {
+ return 1;
+ } else {
+ return 0;
+ }
+ } else if (type == java.util.Date.class) {
+ Date d1 = (Date)data.getValueAt(row1, column);
+ long n1 = d1.getTime();
+ Date d2 = (Date)data.getValueAt(row2, column);
+ long n2 = d2.getTime();
+
+ if (n1 < n2) {
+ return -1;
+ } else if (n1 > n2) {
+ return 1;
+ } else {
+ return 0;
+ }
+ } else if (type == String.class) {
+ String s1 = (String)data.getValueAt(row1, column);
+ String s2 = (String)data.getValueAt(row2, column);
+ int result = s1.compareTo(s2);
+ if (column == 4) { //rating
+ if (s1.length() > s2.length()) {
+ return 1;
+ } else if (s1.length() < s2.length()) {
+ return -1;
+ } else {
+ return 0;
+ }
+ }
+
+ if (s1.matches(" *") && !s2.matches(" *")) {
+ return 1;
+ } else if (s2.matches(" *") && !s1.matches(" *")) {
+ return -1;
+ }
+ if (result < 0) {
+ return -1;
+ } else if (result > 0) {
+ return 1;
+ } else {
+ return 0;
+ }
+ } else if (type == Boolean.class) {
+ Boolean bool1 = (Boolean)data.getValueAt(row1, column);
+ boolean b1 = bool1.booleanValue();
+ Boolean bool2 = (Boolean)data.getValueAt(row2, column);
+ boolean b2 = bool2.booleanValue();
+
+ if (b1 == b2) {
+ return 0;
+ } else if (b1) { // Define false < true
+ return 1;
+ } else {
+ return -1;
+ }
+ } else {
+ Object v1 = data.getValueAt(row1, column);
+ String s1 = v1.toString();
+ Object v2 = data.getValueAt(row2, column);
+ String s2 = v2.toString();
+ int result = s1.compareTo(s2);
+
+ if (result < 0) {
+ return -1;
+ } else if (result > 0) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+ }
+
+ public int compare(int row1, int row2) {
+ compares++;
+ for (int level = 0; level < sortingColumns.size(); level++) {
+ Integer column = (Integer)sortingColumns.elementAt(level);
+ int result = compareRowsByColumn(row1, row2, column.intValue());
+ if (result != 0) {
+ return ascending ? result : -result;
+ }
+ }
+ return 0;
+ }
+public int getRowCount()
+ {
+ return numElements;
+ }
+ public void reallocateIndexes() {
+
+ numElements = model.getRowCount();
+
+ // Set up a new array of indexes with the right number of elements
+ // for the new data model.
+ fullIndex = new int[numElements];
+
+ // Initialise with the identity mapping.
+ for (int row = 0; row < numElements; row++) {
+ fullIndex[row] = row;
+ }
+
+ }
+
+ public void tableChanged(TableModelEvent e) {
+ //System.out.println("Sorter: tableChanged");
+ reallocateIndexes();
+ decideFiltering();
+ super.tableChanged(e);
+ }
+
+ public void checkModel() {
+ if (indexes.length != model.getRowCount()) {
+ System.out.println("Sorter not informed of a change in model.");
+ }
+ }
+
+ public void sort(Object sender) {
+ checkModel();
+
+ compares = 0;
+ // n2sort();
+ // qsort(0, indexes.length-1);
+ shuttlesort((int[])indexes.clone(), indexes, 0, numElements);
+ //System.out.println("Compares: "+compares);
+ }
+
+ public void n2sort() {
+ for (int i = 0; i < getRowCount(); i++) {
+ for (int j = i+1; j < getRowCount(); j++) {
+ if (compare(indexes[i], indexes[j]) == -1) {
+ swap(i, j);
+ }
+ }
+ }
+ }
+
+ // This is a home-grown implementation which we have not had time
+ // to research - it may perform poorly in some circumstances. It
+ // requires twice the space of an in-place algorithm and makes
+ // NlogN assigments shuttling the values between the two
+ // arrays. The number of compares appears to vary between N-1 and
+ // NlogN depending on the initial order but the main reason for
+ // using it here is that, unlike qsort, it is stable.
+ public void shuttlesort(int from[], int to[], int low, int high) {
+ if (high - low < 2) {
+ return;
+ }
+ int middle = (low + high)/2;
+ shuttlesort(to, from, low, middle);
+ shuttlesort(to, from, middle, high);
+
+ int p = low;
+ int q = middle;
+
+ /* This is an optional short-cut; at each recursive call,
+ check to see if the elements in this subset are already
+ ordered. If so, no further comparisons are needed; the
+ sub-array can just be copied. The array must be copied rather
+ than assigned otherwise sister calls in the recursion might
+ get out of sinc. When the number of elements is three they
+ are partitioned so that the first set, [low, mid), has one
+ element and and the second, [mid, high), has two. We skip the
+ optimisation when the number of elements is three or less as
+ the first compare in the normal merge will produce the same
+ sequence of steps. This optimisation seems to be worthwhile
+ for partially ordered lists but some analysis is needed to
+ find out how the performance drops to Nlog(N) as the initial
+ order diminishes - it may drop very quickly. */
+
+ if (high - low >= 4 && compare(from[middle-1], from[middle]) <= 0) {
+ for (int i = low; i < high; i++) {
+ to[i] = from[i];
+ }
+ return;
+ }
+
+ // A normal merge.
+
+ for (int i = low; i < high; i++) {
+ if (q >= high || (p < middle && compare(from[p], from[q]) <= 0)) {
+ to[i] = from[p++];
+ }
+ else {
+ to[i] = from[q++];
+ }
+ }
+ }
+
+ public void swap(int i, int j) {
+ int tmp = indexes[i];
+ indexes[i] = indexes[j];
+ indexes[j] = tmp;
+ }
+
+ // The mapping only affects the contents of the data rows.
+ // Pass all requests to these rows through the mapping array: "indexes".
+
+ public Object getValueAt(int aRow, int aColumn) {
+ checkModel();
+ return model.getValueAt(indexes[aRow], aColumn);
+ }
+
+ public void setValueAt(Object aValue, int aRow, int aColumn) {
+ checkModel();
+ model.setValueAt(aValue, indexes[aRow], aColumn);
+ }
+
+ public void sortByColumn(int column) {
+ sortByColumn(column, true);
+ }
+
+ public void sortByColumn(int column, boolean ascending) {
+ this.ascending = ascending;
+ sortingColumns.removeAllElements();
+ sortingColumns.addElement(new Integer(column));
+ sort(this);super.tableChanged(new TableModelEvent(this, 0, numElements - 1, TableModelEvent.ALL_COLUMNS,
+ TableModelEvent.UPDATE));
+ }
+
+ // There is no-where else to put this.
+ // Add a mouse listener to the Table to trigger a table sort
+ // when a column heading is clicked in the JTable.
+ public void addMouseListenerToHeaderInTable(JTable table) {
+ final TableSorter sorter = this;
+ final JTable tableView = table;
+ tableView.setColumnSelectionAllowed(false);
+ MouseAdapter listMouseListener = new MouseAdapter() {
+ public void mouseClicked(MouseEvent e) {
+ TableColumnModel columnModel = tableView.getColumnModel();
+ int viewColumn = columnModel.getColumnIndexAtX(e.getX());
+ int column = tableView.convertColumnIndexToModel(viewColumn);
+ if (e.getClickCount() == 1 && column != -1) {
+ //System.out.println("Sorting ...");
+ // int shiftPressed = e.getModifiers()&InputEvent.SHIFT_MASK;
+ //boolean ascending = (shiftPressed == 0);
+ if (column == sorter.currColumn) {
+ sorter.currAscending = !sorter.currAscending;
+ } else {
+ sorter.currAscending = true;
+ }
+ sorter.currColumn = column;
+ sorter.sortByColumn(column, sorter.currAscending);
+ }
+ }
+ };
+ JTableHeader th = tableView.getTableHeader();
+ th.addMouseListener(listMouseListener);
+ }
+}
+
diff --git a/source/client/swing/ZApplet.java b/source/client/swing/ZApplet.java
new file mode 100644
index 0000000..0ecd92a
--- /dev/null
+++ b/source/client/swing/ZApplet.java
@@ -0,0 +1,46 @@
+package itunes.client.swing;
+import javax.swing.*;
+import java.awt.event.*;
+public class ZApplet extends JApplet {
+ private ZPlayer app;
+ public void init()
+ {
+ try {
+ UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ JButton jb = new JButton("Launch ZPlayer");
+ jb.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) { createNewPlayer(); }
+ });
+ this.getContentPane().add(jb);
+ }
+ public void createNewPlayer()
+ {
+ if(app == null)
+ {
+ app = new ZPlayer(true);
+ app.frame.addWindowListener(new WindowListener() {
+ public void windowClosed(WindowEvent e) {}
+ public void windowClosing(WindowEvent e) {
+ app = null;
+ }
+ public void windowDeiconified(WindowEvent e) {}
+ public void windowIconified(WindowEvent e) {}
+ public void windowActivated(WindowEvent e) {}
+ public void windowDeactivated(WindowEvent e) {}
+ public void windowOpened(WindowEvent e) {}
+ });
+ app.connectToHost(getParameter("host"));
+ }
+ else
+ {
+ app.frame.toFront();
+ }
+ }
+ public void stop()
+ {
+ app.logOut();
+ }
+} \ No newline at end of file
diff --git a/source/client/swing/ZPlayer.java b/source/client/swing/ZPlayer.java
new file mode 100644
index 0000000..b265641
--- /dev/null
+++ b/source/client/swing/ZPlayer.java
@@ -0,0 +1,506 @@
+/*
+ * Created on May 7, 2003
+ *
+ * To change the template for this generated file go to
+ * Window>Preferences>Java>Code Generation>Code and Comments
+ *
+Copyright 2003 Joseph Barnett
+
+This File is part of "ZPlayer"
+
+"ZPlayer" is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+Free Software Foundation; either version 2 of the License, or
+your option) any later version.
+
+"ZPlayer" is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with "ZPlayer"; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+ */
+package itunes.client.swing;
+import itunes.client.*;
+import itunes.client.request.*;
+import com.strangeberry.rendezvous.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.table.TableColumn;
+import java.awt.*;
+import java.awt.event.*;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
+public class ZPlayer implements ServiceListener {
+ protected String host;
+ protected String connectedHost;
+ public JFrame frame;
+ protected JPanel serverLibrary;
+ protected JPanel pane;
+ protected JComboBox servicesCB;
+ protected JComboBox cb;
+ protected JButton browseLib;
+ protected JButton songDl;
+ protected ArrayList knownIPs;
+ protected int sessionId;
+ protected SongTableModel songModel;
+ protected JTable songTable;
+ protected JScrollPane scroller;
+ protected TableSorter sorter;
+ protected boolean hostConnected;
+ protected boolean librariesQueried;
+ protected boolean browsingLibrary;
+ protected static String iTunesService = "_daap._tcp.local.";
+ protected Rendezvous r;
+ private int fullRowPlaying;
+ protected ProgressMonitor progressMonitor;
+ protected Player p;
+ protected boolean playstop;
+ protected int playingRow;
+ protected int playdb;
+ protected String playhost;
+ protected JTextField searchQuery;
+
+ public void stopPlaying() {
+ if (p != null)
+ p.stopMusic();
+ p = null;
+ frame.setTitle("ZPlayer");
+ if (songDl != null) {
+ songDl.setText("Play Selected");
+ songDl.validate();
+ }
+ playhost = "";
+ playstop = !playstop;
+ }
+
+ public void playNext(int dir) {
+ if (p != null) {
+ p.stopMusic();
+ p = null;
+ }
+ if (playingRow >= 0 && playingRow < songTable.getRowCount()-1 && ((MusicProvider)servicesCB.getSelectedItem()).address.equals(playhost)){
+ playingRow+=dir;
+ fullRowPlaying = sorter.getFullIndexRow(playingRow);
+ SongRequest sr=null;
+ try {
+ sr = new SongRequest(host, Request.ITUNES_PORT,playdb,Integer.parseInt((String)sorter.getValueAt(playingRow,5)),(String)sorter.getValueAt(playingRow,6),sessionId);
+ } catch (NoServerPermissionException e) {
+ e.printStackTrace();
+ }
+ frame.setTitle("ZPlayer: Now Playing \""+(String)sorter.getValueAt(playingRow,2)+"\" by "+(String)sorter.getValueAt(playingRow,0));
+ p = new Player(this,sr.getStream());
+ p.start();
+ songDl.setText("Stop playing");
+ songDl.validate();
+ } else {
+ stopPlaying();
+ }
+ }
+
+ protected void playSong() {
+ final int selection = songTable.getSelectedRow();
+ final int fdb = playdb;
+ if (playstop) {
+ SongRequest sr=null;
+ try {
+ sr = new SongRequest(host, Request.ITUNES_PORT,fdb,Integer.parseInt((String)sorter.getValueAt(selection,5)),(String)sorter.getValueAt(selection,6),sessionId);
+ } catch (NoServerPermissionException e) {
+ e.printStackTrace();
+ JOptionPane.showMessageDialog(frame,"Error streaming song!");
+ stopPlaying();
+ return;
+ }
+ p = new Player(this,sr.getStream());
+ p.start();
+ System.out.println("Selected: "+selection+"\n"+(String)sorter.getValueAt(selection,5)+"\n"+(String)sorter.getValueAt(selection,2));
+ playhost = ((MusicProvider)servicesCB.getSelectedItem()).address;
+ frame.setTitle("ZPlayer: Now Playing \""+(String)sorter.getValueAt(selection,2)+"\" by "+(String)sorter.getValueAt(selection,0));
+ songDl.setText("Stop playing");
+ songDl.validate();
+ playingRow = selection;
+ fullRowPlaying = sorter.getFullIndexRow(playingRow);
+ playstop = !playstop;
+ } else {
+ stopPlaying();
+ playingRow = -1;
+ fullRowPlaying = sorter.getFullIndexRow(playingRow);
+ }
+ }
+
+ public void resolveService(Rendezvous r, String type, String name, ServiceInfo info) {
+ if (info == null) {
+ System.out.println("Service not found");
+ } else {
+ if (name.endsWith("." + type)) {
+ name = name.substring(0, name.length() - (type.length() + 1));
+ }
+ if (!knownIPs.contains(info.getAddress())) {
+ ServerInfoRequest rq=null;
+ try {
+ rq = new ServerInfoRequest(info.getAddress(), Request.ITUNES_PORT);
+ } catch (NoServerPermissionException e) {
+ return;
+ }
+ // if (rq.getServerVersion() >=2) {
+ // System.out.println("Ignoring "+name+ " at address "+ info.getAddress() + ": Unsupported iTunes Version 4.0.1 ("+rq.getServerVersion()+")");
+ // return;
+ // }
+ System.out.println("Discovered "+name+" at address "+info.getAddress() + ": (Server Version "+rq.getServerVersion()+")");
+ knownIPs.add(info.getAddress());
+ MusicProvider m = new MusicProvider(info.getAddress(),name);
+ servicesCB.addItem(m);
+ servicesCB.validate();
+ } else {
+ System.out.println("Ignoring new service " + name + " from already known IP "+info.getAddress());
+ }
+ }
+ }
+
+ public void addService(Rendezvous r, String type, String name) {
+ if (name.endsWith("." + type)) {
+ name = name.substring(0, name.length() - (type.length() + 1));
+ }
+ r.requestServiceInfo(iTunesService,name);
+ }
+
+ public void removeService(Rendezvous r, String type, String name) {
+ if (name.endsWith("." + type)) {
+ name = name.substring(0, name.length() - (type.length() + 1));
+ }
+ knownIPs.remove(r.getServiceInfo(type,name).getAddress());
+ System.out.println(name + " went offline");
+ servicesCB.removeItem(new MusicProvider("",name));
+ servicesCB.validate();
+ }
+ private class MyDocumentListner implements DocumentListener {
+ public void insertUpdate(DocumentEvent e){
+ changeFilter();
+ }
+ public void removeUpdate(DocumentEvent e) {
+ changeFilter();
+ }
+ public void changedUpdate(DocumentEvent e) {
+ }
+ }
+ private void changeFilter()
+ {
+ sorter.reFilter(searchQuery);
+ playingRow = sorter.getFilteredIndexRow(fullRowPlaying);
+ }
+ private JPanel buildSearch()
+ {
+ JPanel row1 = new JPanel();
+
+ searchQuery = new JTextField(20);
+ searchQuery.getDocument().addDocumentListener(new MyDocumentListner());
+ JButton clearSearch = new JButton("Clear Search");
+
+ clearSearch.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e){
+ searchQuery.setText("");
+ }
+ });
+
+ JLabel searchLabel = new JLabel("Search:");
+
+ row1.add(searchLabel);
+ row1.add(searchQuery);
+ row1.add(clearSearch);
+ row1.add(Box.createRigidArea(new Dimension(5,0)));
+ JButton select = new JButton("Select Playing");
+ select.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ if(playingRow == -1 && fullRowPlaying != -1)
+ {
+ searchQuery.setText("");
+ }
+ if(playingRow>-1)
+ {
+ songTable.setRowSelectionInterval(playingRow,playingRow);
+ songTable.scrollRectToVisible(songTable.getCellRect(playingRow, 0, true));
+ }
+ }
+ });
+ row1.add(select);
+ return row1;
+ }
+ protected void createSongChooser() throws NoServerPermissionException {
+ SingleDatabaseRequest sr = new SingleDatabaseRequest(host,Request.ITUNES_PORT,sessionId, playdb);
+ ArrayList songs = sr.getSongs();
+ Collections.sort(songs);
+ if (songModel == null) {
+ songModel = new SongTableModel();
+ } else {
+ songModel.clear();
+ }
+ for (int i = 0; i < songs.size();i++) {
+ Song s = (Song)songs.get(i);
+ songModel.AddRow(s);
+ }
+ if (songTable == null) {
+ pane.remove(pane.getComponentCount()-1);
+ sorter = new TableSorter(songModel);
+ songTable = new JTable(sorter);
+ songTable.addMouseListener(new MouseAdapter() {
+ public void mouseClicked(MouseEvent e) {
+ if (e.getClickCount() == 2) {
+ stopPlaying();
+ playstop = true;
+ playSong();
+ }
+ }
+ });
+ sorter.addMouseListenerToHeaderInTable(songTable);
+ songTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+ songTable.setPreferredScrollableViewportSize(new
+ Dimension(1500, 1600));
+ for (int i = 0; i < 5; i++) {
+ TableColumn column = songTable.getColumnModel().getColumn(i);
+ if (i == 2) {
+ column.setPreferredWidth(300);
+ } else if (i==0||i==1){
+ column.setPreferredWidth(150);
+ } else {
+ column.setPreferredWidth(10);
+ }
+ }
+ scroller = new JScrollPane(songTable);
+ pane.add(buildSearch());
+ pane.add(scroller);
+
+ } else {
+ songTable.validate();
+ songTable.repaint();
+ }
+ if (songDl == null) {
+ JPanel buttonRow = new JPanel();
+ buttonRow.setAlignmentX(Component.CENTER_ALIGNMENT);
+ JButton back = new JButton("Back Track");
+ back.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ playNext(-1);
+ }
+ });
+ buttonRow.add(back);
+ buttonRow.add(Box.createRigidArea(new Dimension(5,0)));
+ songDl = new JButton("Play Selected");
+ back.setAlignmentX(Component.CENTER_ALIGNMENT);
+ songDl.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ playSong();
+ }
+ });
+ buttonRow.add(songDl);
+ buttonRow.add(Box.createRigidArea(new Dimension(5,0)));
+ JButton next = new JButton("Forward Track");
+ next.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ playNext(1);
+ }
+ });
+ buttonRow.add(next);
+ pane.add(buttonRow);
+ }
+ songModel.fireTableDataChanged();
+ pane.validate();
+ scroller.validate();
+ frame.validate();
+ }
+
+ protected void connectToHost() throws NoServerPermissionException{
+ if (sessionId != -1) {
+ try {
+ LogoutRequest lr = new LogoutRequest(connectedHost,Request.ITUNES_PORT, sessionId);
+ } catch (NoServerPermissionException e) {}
+ sessionId = -1;
+ }
+ LoginRequest l=null;
+ l = new LoginRequest(host,Request.ITUNES_PORT);
+ connectedHost = host;
+ sessionId = l.getSessionId();
+ if (sessionId == -1) {
+ JOptionPane.showMessageDialog(frame, "Error connecting to "+host);
+ return;
+ }
+ System.out.println("logged in: session "+ sessionId);
+ JPanel col1 = new JPanel();
+ col1.setLayout(new BoxLayout(col1,BoxLayout.Y_AXIS));
+ DatabasesRequest db = new DatabasesRequest(host, Request.ITUNES_PORT, sessionId);
+ int dbCount = db.getLibraryCount();
+ ArrayList dbs = db.getDbs();
+ if (cb == null) {
+ cb = new JComboBox();
+ cb.setAlignmentX(Component.CENTER_ALIGNMENT);
+ col1.add(cb);
+ } else {
+ cb.removeAllItems();
+ }
+ for (int i = 0; i < dbCount; i++) {
+ cb.addItem(dbs.get(i));
+ }
+ if (browseLib == null) {
+ browseLib = new JButton("Browse Selected Library");
+ browseLib.setAlignmentX(Component.CENTER_ALIGNMENT);
+ browseLib.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ try {
+ playdb = ((Database)cb.getSelectedItem()).id;
+ createSongChooser();
+ } catch (NoServerPermissionException ex) {
+ }
+ }
+ });
+ col1.add(browseLib);
+ }
+ if(col1.getComponentCount() > 0)
+ {
+ serverLibrary.add(Box.createRigidArea(new Dimension(5,0)));
+ serverLibrary.add(col1);
+ serverLibrary.validate();
+ }
+ }
+
+ public Component createComponents() {
+ JButton button = new JButton("Browse Host");
+ button.setAlignmentX(Component.CENTER_ALIGNMENT);
+ button.setMnemonic(KeyEvent.VK_I);
+ button.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ try {
+ MusicProvider m = ((MusicProvider)servicesCB.getSelectedItem());
+ if (m.address.equals("")) {
+ host = JOptionPane.showInputDialog("Enter hostname: ","");
+ } else {
+ host = m.address;
+ }
+
+ try {
+ connectToHost();
+ } catch (NoServerPermissionException e1) {
+ JOptionPane.showMessageDialog(frame,"Need Authorization! (not yet implemented)");
+ return;
+ }
+ playdb = ((Database)cb.getItemAt(0)).id;
+ createSongChooser();
+ } catch (NoServerPermissionException ex) {
+ }
+ }
+ });
+ serverLibrary = new JPanel();
+ serverLibrary.setLayout(new BoxLayout(serverLibrary,BoxLayout.X_AXIS));
+ pane = new JPanel();
+ pane.setBorder(BorderFactory.createEmptyBorder(10,10,10,10));
+ pane.setLayout(new BoxLayout(pane,BoxLayout.Y_AXIS));
+ MusicProvider m = new MusicProvider("","Other...");
+ servicesCB.addItem(m);
+ JPanel col1 = new JPanel();
+ col1.setLayout(new BoxLayout(col1,BoxLayout.Y_AXIS));
+ col1.add(servicesCB);
+ col1.add(button);
+ serverLibrary.add(col1);
+ pane.add(serverLibrary);
+ pane.add(Box.createRigidArea(new Dimension(0,20)));
+ pane.add(Box.createRigidArea(new Dimension(0,400)));
+ return pane;
+ }
+ public void logOut()
+ {
+ if (sessionId != -1) {
+ LogoutRequest lr;
+ try {
+ lr = new LogoutRequest(connectedHost, Request.ITUNES_PORT, sessionId);
+ System.out.println("disconnected from session: " + sessionId);
+ } catch (NoServerPermissionException ex) { }
+ sessionId = -1;
+ }
+ stopPlaying();
+ }
+ public void connectToHost(String initialHost)
+ {
+ if(initialHost != null && !initialHost.equals(""))
+ try
+ {
+ host = initialHost;
+ connectToHost();
+ playdb = ((Database)cb.getItemAt(0)).id;
+ createSongChooser();
+ }
+ catch (NoServerPermissionException ex) {}
+ }
+ public ZPlayer(boolean applet) {
+ playhost = "";
+ playingRow = -1;
+ fullRowPlaying = -1;
+ playstop = true;
+ p = null;
+ servicesCB = null;
+ cb = null;
+ browseLib = null;
+ songDl = null;
+ sessionId = -1;
+ songModel = null;
+ sorter = null;
+ songTable = null;
+ scroller = null;
+ hostConnected = false;
+ librariesQueried = false;
+ browsingLibrary = false;
+ knownIPs = new ArrayList();
+ try {
+ UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ servicesCB = new JComboBox();
+ servicesCB.setAlignmentX(Component.CENTER_ALIGNMENT);
+
+ try {
+ r = new Rendezvous();
+ r.addServiceListener(iTunesService,this);
+ } catch (Exception e) {
+ System.out.println("Died while establishing rendezvous:\n");
+ e.printStackTrace();
+ }
+ //Create the top-level container and add contents to it.
+ frame = new JFrame("ZPlayer");
+ Component contents = createComponents();
+ frame.getContentPane().add(contents, BorderLayout.CENTER);
+
+ if(!applet)
+ {
+ frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ }
+ frame.pack();
+
+ frame.setLocation(100,100);
+ frame.setSize(800,400);
+ frame.addWindowListener(new WindowListener() {
+ public void windowClosed(WindowEvent e) {
+ logOut();
+ }
+ public void windowClosing(WindowEvent e) {
+ logOut();
+ }
+ public void windowDeiconified(WindowEvent e) {}
+ public void windowIconified(WindowEvent e) {}
+ public void windowActivated(WindowEvent e) {}
+ public void windowDeactivated(WindowEvent e) {}
+ public void windowOpened(WindowEvent e) {}
+ });
+ frame.setVisible(true);
+ }
+ public static void main(String[] args) {
+ ZPlayer app = new ZPlayer(false);
+ if(args.length > 0)
+ {
+ app.connectToHost(args[0]);
+ }
+ }
+}
diff --git a/source/util/Hasher.java b/source/util/Hasher.java
new file mode 100644
index 0000000..0458e94
--- /dev/null
+++ b/source/util/Hasher.java
@@ -0,0 +1,109 @@
+/*
+ * Created on Mar 1, 2004
+ * Algorithm:
+ * Copyright (c) 2004 David Hammerton
+ *
+ * port to java:
+ * Copyright (c) 2004 Joseph Barnett
+ */
+package itunes.util;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+/**
+ * @author jbarnett
+ */
+public class Hasher {
+ //taken from calculations in libopendaap
+ //private static String staticHash = "98814088228B81E0AB021433618EC27B";
+ private static String calcHash = "";
+ private static boolean staticCalculated = false;
+
+ private static final String hexchars = "0123456789ABCDEF";
+ private static final String appleCopyright = "Copyright 2003 Apple Computer, Inc.";
+ private static MessageDigest md;
+
+ private static final int HASH_SIZE = 32;
+
+ static {
+ try {
+ md = MessageDigest.getInstance("md5");
+ } catch (NoSuchAlgorithmException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private static String DigestToString(byte[] digest)
+ {
+ String string="";
+ int i;
+ for (i = 0; i < digest.length; i++)
+ {
+ byte tmp = digest[i];
+ string += hexchars.charAt((tmp >> 4) & 0x0f);
+ string += hexchars.charAt(tmp & 0x0f);
+ }
+ return string;
+ }
+
+ private static synchronized void calculateStaticHash() {
+ if (staticCalculated)
+ return;
+ for (int i = 0; i < 256; i++) {
+ if ((i & 0x80) != 0)
+ md.update("Accept-Language".getBytes());
+ else
+ md.update("user-agent".getBytes());
+
+ if ((i & 0x40) != 0)
+ md.update("max-age".getBytes());
+ else
+ md.update("Authorization".getBytes());
+
+ if ((i & 0x20) != 0)
+ md.update("Client-DAAP-Version".getBytes());
+ else
+ md.update("Accept-Encoding".getBytes());
+
+ if ((i & 0x10) != 0)
+ md.update("daap.protocolversion".getBytes());
+ else
+ md.update("daap.songartist".getBytes());
+
+ if ((i & 0x08) != 0)
+ md.update("daap.songcomposer".getBytes());
+ else
+ md.update("daap.songdatemodified".getBytes());
+
+ if ((i & 0x04) != 0)
+ md.update("daap.songdiscnumber".getBytes());
+ else
+ md.update("daap.songdisabled".getBytes());
+
+ if ((i & 0x02) != 0)
+ md.update("playlist-item-spec".getBytes());
+ else
+ md.update("revision-number".getBytes());
+
+ if ((i & 0x01) != 0)
+ md.update("session-id".getBytes());
+ else
+ md.update("content-codes".getBytes());
+
+ String newHash =DigestToString(md.digest());
+ calcHash += newHash;
+ }
+ staticCalculated = true;
+ }
+
+ public static String GenerateHash(String url, int accessIndex) {
+ int start = HASH_SIZE * accessIndex;
+ int end = start + HASH_SIZE;
+ calculateStaticHash();
+ md.update(url.getBytes());
+ md.update(appleCopyright.getBytes());
+ md.update(calcHash.substring(start, end).getBytes());
+ return DigestToString(md.digest());
+ }
+}