├── .classpath
├── .gitignore
├── .project
├── README.md
├── Screenshots
├── kAI-GUI.png
├── kAI-screener.png
└── kaiDJ.png
├── demo
├── Katy Perry - Firework.mp3
└── Katy Perry - Firework.mp3.kai
├── dist
└── karaok-AI.jar
├── karaok-AI.jardesc
├── lib
├── common
│ ├── JID3.jar
│ ├── WhisperTimeSync.jar
│ ├── commons-logging-api.jar
│ ├── hsqldb.jar
│ ├── jakarta-regexp-1.5.jar
│ ├── jid3lib-0.5.4.jar
│ ├── jl1.0.1.jar
│ ├── mp3spi1.9.4.jar
│ ├── myid3.jar
│ ├── tritonus_share.jar
│ ├── ws-commons-util-1.0.2.jar
│ ├── xmlrpc-client-3.1.3.jar
│ └── xmlrpc-common-3.1.3.jar
├── swt-linux.jar
├── swt-mac.jar
└── swt-win.jar
└── src
├── com
└── cubaix
│ ├── kai
│ ├── KaiClient.java
│ ├── KaiEditor.java
│ ├── KaiPlayer.java
│ ├── KaiScreener.java
│ ├── KaiSrt.java
│ ├── KaiViewer.java
│ ├── LogoPanel.java
│ ├── img
│ │ ├── Logo.png
│ │ ├── LogoSmall.png
│ │ ├── LogoSquare.png
│ │ ├── LogoSquareL.png
│ │ └── kAI.svg
│ └── img2
│ │ ├── arrows-fullscreen.svg
│ │ └── fullscreen.png
│ └── kaiDJ
│ ├── CategoryManager.java
│ ├── DJPlayer.java
│ ├── KaiDJ.java
│ ├── LogoPanel.java
│ ├── PlayList.java
│ ├── PlayManager.java
│ ├── SearchManager.java
│ ├── db
│ ├── Db.java
│ ├── Id3Analyzer.java
│ ├── SongDescr.java
│ └── SongGroup.java
│ ├── img
│ ├── Icon.ico
│ ├── Icon.png
│ ├── LogoSmall.png
│ ├── kaiDJ.svg
│ ├── playerBck.png
│ └── playerBck.xcf
│ ├── img2
│ ├── addDbBut.png
│ ├── addDbBut.xcf
│ ├── addGroupBut.png
│ ├── addGroupBut.xcf
│ ├── allButtons.svg
│ ├── bookmarks.svg
│ ├── butBck.png
│ ├── butBck.xcf
│ ├── butBckDark.png
│ ├── butBckDark.xcf
│ ├── butBckMid.png
│ ├── butBckMid.xcf
│ ├── catBut.png
│ ├── catBut.xcf
│ ├── chat-square-text-fill.svg
│ ├── chat-square-text.svg
│ ├── database-add.svg
│ ├── eraseDbBut.png
│ ├── folder2-open.svg
│ ├── globe.svg
│ ├── kaiBut.png
│ ├── kaiIcon.png
│ ├── kaiIcon.svg
│ ├── mixBut.png
│ ├── mixBut.xcf
│ ├── newPLBut.png
│ ├── newPLBut.xcf
│ ├── openCatBut.png
│ ├── openPLBut.png
│ ├── save2.svg
│ ├── saveCatBut.png
│ ├── savePLBut.png
│ ├── search.svg
│ ├── searchKaiBut.png
│ ├── showProfBut.png
│ ├── showProfBut.xcf
│ ├── shuffleBut.png
│ ├── shuffleBut.xcf
│ ├── stars.svg
│ ├── stopAftBut.png
│ ├── stopAftBut.xcf
│ ├── trash3.svg
│ ├── webSiteBut.png
│ └── webSiteBut.xcf
│ ├── swt
│ ├── KaiButton.java
│ ├── KaiScrollBar.java
│ ├── PlayListListener.java
│ └── TimedCanvas.java
│ ├── utils
│ └── FileUtils.java
│ ├── web
│ └── BrowserControl.java
│ └── xml
│ ├── ConfigLoader.java
│ ├── PlayListLoader.java
│ ├── XLoader.java
│ ├── XObject.java
│ ├── XQualifier.java
│ ├── XTag.java
│ └── charEntities.tsv
├── javazoom
└── jlgui
│ └── basicplayer
│ ├── BasicController.java
│ ├── BasicPlayer.java
│ ├── BasicPlayerEvent.java
│ ├── BasicPlayerEventLauncher.java
│ ├── BasicPlayerException.java
│ └── BasicPlayerListener.java
└── kj
├── audio
└── KJAudioDataConsumer.java
├── dsp
├── KJDigitalSignalProcessingAudioDataConsumer.java
├── KJDigitalSignalProcessor.java
├── KJDigitalSignalProcessor1.java
└── KJFFT.java
└── ui
└── dsp
└── KJScopeAndSpectrumAnalyser.java
/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /bin/
2 | /last.jdj
3 | /MP3_v3.hdb.backup
4 | /MP3_v3.hdb.data
5 | /MP3_v3.hdb.log
6 | /MP3_v3.hdb.properties
7 | /MP3_v3.hdb.script
8 |
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | karaok-AI
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.jdt.core.javabuilder
10 |
11 |
12 |
13 |
14 |
15 | org.eclipse.jdt.core.javanature
16 |
17 |
18 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # karaok-AI
2 | **karaok-AI** is a karaoke Player / Editor with automatic clip creation from any song file using vocals and lyrics extraction (Speech-to-Text).
3 |
4 | karaok-AI lyrics and timestamps **editor**:
5 |
6 |
7 |
8 | karaok-AI **screener** with synchronized lyrics:
9 |
10 |
11 |
12 | Lyrics **auto-extract** and **edit** example:
13 |
14 | [](https://karaok-ai.neurospell.com/karaok-AI-DemoLady.mp4)
15 |
16 | Auto-extracted Vocals/Drums/Bass/Other stem **remixing** example:
17 |
18 | [](https://karaok-ai.neurospell.com/karaok-AI-DemoKaty.mp4)
19 |
20 | karaok-AI is using WhisperHallu and WhisperTimeSync to extract vocals and lyrics:
21 | https://github.com/EtienneAb3d/WhisperHallu
22 | https://github.com/EtienneAb3d/WhisperTimeSync
23 |
24 | # Included: kaiDJ
25 |
26 | **kaiDJ** is a minimalist and easy to use, but yet powerful and versatile DJ Party Player.
27 | - multi-sound cards support. Two players with auto-mix between songs, one pre-listen player.
28 | - indexing of thousands of songs in a single efficient database (mp3, wav, etc).
29 | - direct search / selection over all songs in the database. Management of song categories.
30 | - playlist offering the possibility to manage songs by nested groups.
31 | - Open / save m3u and m3u8 playlists keeping groups definitions.
32 |
33 | Read the documentation for the basics.
34 |
35 |
36 |
37 |
38 | This tool is a demonstration of our know-how.
39 | If you are interested in a commercial/industrial AI linguistic project, contact us:
40 | https://cubaix.com
41 |
--------------------------------------------------------------------------------
/Screenshots/kAI-GUI.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EtienneAb3d/karaok-AI/2eaaf4fba6234ad6206e112c59a0d6143540aace/Screenshots/kAI-GUI.png
--------------------------------------------------------------------------------
/Screenshots/kAI-screener.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EtienneAb3d/karaok-AI/2eaaf4fba6234ad6206e112c59a0d6143540aace/Screenshots/kAI-screener.png
--------------------------------------------------------------------------------
/Screenshots/kaiDJ.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EtienneAb3d/karaok-AI/2eaaf4fba6234ad6206e112c59a0d6143540aace/Screenshots/kaiDJ.png
--------------------------------------------------------------------------------
/demo/Katy Perry - Firework.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EtienneAb3d/karaok-AI/2eaaf4fba6234ad6206e112c59a0d6143540aace/demo/Katy Perry - Firework.mp3
--------------------------------------------------------------------------------
/demo/Katy Perry - Firework.mp3.kai:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EtienneAb3d/karaok-AI/2eaaf4fba6234ad6206e112c59a0d6143540aace/demo/Katy Perry - Firework.mp3.kai
--------------------------------------------------------------------------------
/dist/karaok-AI.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EtienneAb3d/karaok-AI/2eaaf4fba6234ad6206e112c59a0d6143540aace/dist/karaok-AI.jar
--------------------------------------------------------------------------------
/karaok-AI.jardesc:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/lib/common/JID3.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EtienneAb3d/karaok-AI/2eaaf4fba6234ad6206e112c59a0d6143540aace/lib/common/JID3.jar
--------------------------------------------------------------------------------
/lib/common/WhisperTimeSync.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EtienneAb3d/karaok-AI/2eaaf4fba6234ad6206e112c59a0d6143540aace/lib/common/WhisperTimeSync.jar
--------------------------------------------------------------------------------
/lib/common/commons-logging-api.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EtienneAb3d/karaok-AI/2eaaf4fba6234ad6206e112c59a0d6143540aace/lib/common/commons-logging-api.jar
--------------------------------------------------------------------------------
/lib/common/hsqldb.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EtienneAb3d/karaok-AI/2eaaf4fba6234ad6206e112c59a0d6143540aace/lib/common/hsqldb.jar
--------------------------------------------------------------------------------
/lib/common/jakarta-regexp-1.5.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EtienneAb3d/karaok-AI/2eaaf4fba6234ad6206e112c59a0d6143540aace/lib/common/jakarta-regexp-1.5.jar
--------------------------------------------------------------------------------
/lib/common/jid3lib-0.5.4.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EtienneAb3d/karaok-AI/2eaaf4fba6234ad6206e112c59a0d6143540aace/lib/common/jid3lib-0.5.4.jar
--------------------------------------------------------------------------------
/lib/common/jl1.0.1.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EtienneAb3d/karaok-AI/2eaaf4fba6234ad6206e112c59a0d6143540aace/lib/common/jl1.0.1.jar
--------------------------------------------------------------------------------
/lib/common/mp3spi1.9.4.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EtienneAb3d/karaok-AI/2eaaf4fba6234ad6206e112c59a0d6143540aace/lib/common/mp3spi1.9.4.jar
--------------------------------------------------------------------------------
/lib/common/myid3.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EtienneAb3d/karaok-AI/2eaaf4fba6234ad6206e112c59a0d6143540aace/lib/common/myid3.jar
--------------------------------------------------------------------------------
/lib/common/tritonus_share.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EtienneAb3d/karaok-AI/2eaaf4fba6234ad6206e112c59a0d6143540aace/lib/common/tritonus_share.jar
--------------------------------------------------------------------------------
/lib/common/ws-commons-util-1.0.2.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EtienneAb3d/karaok-AI/2eaaf4fba6234ad6206e112c59a0d6143540aace/lib/common/ws-commons-util-1.0.2.jar
--------------------------------------------------------------------------------
/lib/common/xmlrpc-client-3.1.3.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EtienneAb3d/karaok-AI/2eaaf4fba6234ad6206e112c59a0d6143540aace/lib/common/xmlrpc-client-3.1.3.jar
--------------------------------------------------------------------------------
/lib/common/xmlrpc-common-3.1.3.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EtienneAb3d/karaok-AI/2eaaf4fba6234ad6206e112c59a0d6143540aace/lib/common/xmlrpc-common-3.1.3.jar
--------------------------------------------------------------------------------
/lib/swt-linux.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EtienneAb3d/karaok-AI/2eaaf4fba6234ad6206e112c59a0d6143540aace/lib/swt-linux.jar
--------------------------------------------------------------------------------
/lib/swt-mac.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EtienneAb3d/karaok-AI/2eaaf4fba6234ad6206e112c59a0d6143540aace/lib/swt-mac.jar
--------------------------------------------------------------------------------
/lib/swt-win.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EtienneAb3d/karaok-AI/2eaaf4fba6234ad6206e112c59a0d6143540aace/lib/swt-win.jar
--------------------------------------------------------------------------------
/src/com/cubaix/kai/KaiClient.java:
--------------------------------------------------------------------------------
1 | package com.cubaix.kai;
2 |
3 | import java.io.ByteArrayOutputStream;
4 | import java.io.File;
5 | import java.io.FileInputStream;
6 | import java.io.FileOutputStream;
7 | import java.io.IOException;
8 | import java.net.URL;
9 | import java.util.zip.ZipEntry;
10 | import java.util.zip.ZipOutputStream;
11 |
12 | import org.apache.xmlrpc.client.XmlRpcClient;
13 | import org.apache.xmlrpc.client.XmlRpcClientConfigImpl;
14 |
15 | import com.cubaix.kaiDJ.KaiDJ;
16 | import com.cubaix.kaiDJ.utils.FileUtils;
17 |
18 | public class KaiClient {
19 | KaiDJ parentKDJ = null;
20 | String path = null;
21 | String taskId = null;
22 |
23 | public KaiClient(KaiDJ aParentKDJ) {
24 | parentKDJ = aParentKDJ;
25 | }
26 |
27 | XmlRpcClient getXmlRcpClient() throws Exception {
28 | XmlRpcClientConfigImpl config = new XmlRpcClientConfigImpl();
29 | config.setServerURL(new URL("http://odyssee.neurospell.com:8991"));
30 | config.setEnabledForExtensions(false);
31 | config.setConnectionTimeout(60 * 1000);//1mn
32 | config.setReplyTimeout(10 * 60 * 60 * 1000);//10h
33 | XmlRpcClient client = new XmlRpcClient();
34 | client.setConfig(config);
35 | return client;
36 | }
37 |
38 | public void getCode() throws Exception {
39 | XmlRpcClient client = getXmlRcpClient();
40 | Object[] params = new Object[] {parentKDJ.userEMail};
41 | System.out.println("GET KAI CODE...");
42 | String aRep = (String)client.execute("Middleware.kaiCode",params);
43 | System.out.println("GetCode reply: "+aRep);
44 | }
45 |
46 | public String extract(String aPath,String aLng) throws Exception {
47 | path = aPath;
48 | XmlRpcClient client = getXmlRcpClient();
49 | File aFile = new File(aPath);
50 | System.out.println("LOADING: "+aFile.getCanonicalPath());
51 | FileInputStream fileInputStream;
52 | byte[] aBuf = null;
53 | try {
54 | fileInputStream = new FileInputStream(aFile);
55 | aBuf = new byte[(int) aFile.length()];
56 | fileInputStream.read(aBuf);
57 | fileInputStream.close();
58 | } catch (IOException e) {
59 | e.printStackTrace(System.err);
60 | }
61 | ByteArrayOutputStream baos = new ByteArrayOutputStream();
62 | try(ZipOutputStream zos = new ZipOutputStream(baos)) {
63 |
64 | /* File is not on the disk, test.txt indicates
65 | only the file name to be put into the zip */
66 | ZipEntry entry = new ZipEntry(aFile.getName());
67 | zos.putNextEntry(entry);
68 | zos.write(aBuf);
69 | zos.closeEntry();
70 | }
71 | catch(IOException ioe) {
72 | ioe.printStackTrace();
73 | }
74 | Object[] params = new Object[] {parentKDJ.userEMail,parentKDJ.userCode,baos.toByteArray(),aLng,parentKDJ.userEMail.replaceAll("[@.]","_")};
75 | System.out.println("UPLOADING...");
76 | String aRes = (String)client.execute("Middleware.kai",params);
77 | System.out.println("Res: "+aRes);
78 | return aRes;
79 | }
80 |
81 | public String state() throws Exception {
82 | XmlRpcClient client = getXmlRcpClient();
83 | System.out.println("STATE: "+taskId);
84 | Object[] params = new Object[] {parentKDJ.userEMail,parentKDJ.userCode,taskId,parentKDJ.userEMail.replaceAll("[@.]","_")};
85 | String aRes = (String)client.execute("Middleware.kaiState",params);
86 | System.out.println("Res: "+aRes);
87 | return aRes;
88 | }
89 |
90 | public void get() throws Exception {
91 | XmlRpcClient client = getXmlRcpClient();
92 | System.out.println("GET: "+taskId);
93 | Object[] params = new Object[] {parentKDJ.userEMail,parentKDJ.userCode,taskId,parentKDJ.userEMail.replaceAll("[@.]","_")};
94 | byte[] aKai = (byte[])client.execute("Middleware.kaiGet",params);
95 | FileOutputStream aFOS = new FileOutputStream(path+".kai");
96 | aFOS.write(aKai);
97 | aFOS.flush();
98 | aFOS.close();
99 | System.out.println("SAVED");
100 | FileUtils.unzipDir(path+".kai", new File(path).getParentFile().getCanonicalPath(), true);
101 | System.out.println("UNZIPPED");
102 | }
103 |
104 | public static void main(String[] args) {
105 | try {
106 | } catch (Exception e) {
107 | e.printStackTrace(System.err);
108 | }
109 | }
110 |
111 | }
112 |
--------------------------------------------------------------------------------
/src/com/cubaix/kai/KaiPlayer.java:
--------------------------------------------------------------------------------
1 | package com.cubaix.kai;
2 |
3 | import org.eclipse.swt.widgets.Composite;
4 |
5 | import com.cubaix.kaiDJ.KaiDJ;
6 | import com.cubaix.kaiDJ.db.SongDescr;
7 | import com.cubaix.kaiDJ.DJPlayer;
8 |
9 | public class KaiPlayer extends DJPlayer {
10 | SongDescr song = null;
11 | String stem = null;
12 |
13 | public KaiPlayer(KaiDJ aParentKDJ, Composite parent, int style, int aDest) {
14 | super(aParentKDJ, parent, style, aDest,false);
15 | }
16 |
17 | @Override
18 | protected void extractProperties() {
19 | super.extractProperties();
20 | if(stem != null) {
21 | currentAuthor = stem;
22 | }
23 | if(song != null) {
24 | currentTitle = song.title+" / "+song.author;
25 | }
26 | }
27 |
28 | void load(SongDescr aSong,String aPath,String aStem) {
29 | song = aSong;
30 | stem = aStem;
31 | super.load(aPath);
32 | }
33 |
34 | @Override
35 | public void timeToNext() {
36 | //Do nothing
37 | }
38 |
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/src/com/cubaix/kai/KaiScreener.java:
--------------------------------------------------------------------------------
1 | package com.cubaix.kai;
2 |
3 | import java.io.InputStream;
4 |
5 | import org.eclipse.swt.SWT;
6 | import org.eclipse.swt.events.KeyEvent;
7 | import org.eclipse.swt.events.KeyListener;
8 | import org.eclipse.swt.events.PaintEvent;
9 | import org.eclipse.swt.events.PaintListener;
10 | import org.eclipse.swt.graphics.GC;
11 | import org.eclipse.swt.graphics.Image;
12 | import org.eclipse.swt.graphics.Point;
13 | import org.eclipse.swt.graphics.Rectangle;
14 | import org.eclipse.swt.widgets.Composite;
15 |
16 | import com.cubaix.kaiDJ.KaiDJ;
17 | import com.cubaix.kaiDJ.db.SongDescr;
18 | import com.cubaix.kaiDJ.swt.TimedCanvas;
19 |
20 | public class KaiScreener extends TimedCanvas {
21 | KaiViewer parentKV = null;
22 |
23 | Rectangle panelBounds = null;
24 | Image dblBuf = null;
25 | Rectangle dblBounds = new Rectangle(0, 0, 1280, 720);
26 | GC dblBufGC;
27 |
28 | Image fullScreenBut = null;
29 |
30 | int currentKaiIdx = -1;
31 | int currentKaiIdxJustBefore = -1;
32 |
33 | public KaiScreener(KaiViewer aParentKV, Composite parent, int style) {
34 | super(aParentKV.parentKE.parentKDJ, parent, style);
35 | parentKV = aParentKV;
36 |
37 | InputStream aIS = getClass().getResourceAsStream("img2/fullscreen.png");
38 | fullScreenBut = new Image(parentKDJ.display, aIS);
39 |
40 | final KaiScreener aThis = this;
41 | addPaintListener(new PaintListener() {
42 | public void paintControl(PaintEvent aPE) {
43 | panelBounds = getClientArea();
44 | GC aPlGC = new GC(aThis);
45 | paintDbl(aPlGC);
46 | aPlGC.dispose();
47 | needRedraw();
48 | }
49 | });
50 | addKeyListener(new KeyListener() {
51 | @Override
52 | public void keyReleased(KeyEvent arg0) {
53 | }
54 |
55 | @Override
56 | public void keyPressed(KeyEvent arg0) {
57 | }
58 | });
59 | Thread aTrackTh = new Thread(new Runnable() {
60 | @Override
61 | public void run() {
62 | while(!aThis.isDisposed()) {
63 | try {
64 | SongDescr aSong = parentKV.parentKE.song;
65 | if(aSong != null && aSong.kaiSrt != null) {
66 | int aKaiIdx = aSong.kaiSrt.getChunkIdx(parentKV.parentKE.playerVocals.getPositionMs());
67 | int aJustBef = aSong.kaiSrt.getChunkIdxJustBefore(parentKV.parentKE.playerVocals.getPositionMs());
68 | if(aKaiIdx != currentKaiIdx || aJustBef != currentKaiIdxJustBefore) {
69 | currentKaiIdx = aKaiIdx;
70 | currentKaiIdxJustBefore = aJustBef;
71 | needRedraw();
72 | parentKV.parentKE.logoPanel.needRedraw();
73 | }
74 | }
75 | Thread.sleep(10);
76 | } catch (Exception e) {
77 | e.printStackTrace(System.err);
78 | }
79 | }
80 | }
81 | });
82 | aTrackTh.start();
83 | }
84 |
85 | @Override
86 | protected void paintTimed() {
87 | if(KaiDJ._DEBUG_PAINT) {
88 | System.out.println("SCREENER.paintTimed()");
89 | }
90 | try {
91 | if (dblBuf == null) {
92 | dblBuf = new Image(parentKDJ.display,dblBounds.width,dblBounds.height);
93 | dblBufGC = new GC(dblBuf);
94 | }
95 |
96 | dblBufGC.setClipping(0, 0,dblBounds.width,dblBounds.height);
97 | dblBufGC.setBackground(parentKDJ.mainBckC);
98 | dblBufGC.fillRectangle(0, 0,dblBounds.width,dblBounds.height);
99 |
100 | SongDescr aSong = parentKV.parentKE.song;
101 | if(aSong != null && aSong.kaiSrt != null) {
102 | currentKaiIdx = aSong.kaiSrt.getChunkIdx(parentKV.parentKE.playerVocals.getPositionMs());
103 | int aJustBef = aSong.kaiSrt.getChunkIdxJustBefore(parentKV.parentKE.playerVocals.getPositionMs());
104 |
105 | dblBufGC.setFont(parentKDJ.viewerFont);
106 | int aPadding = 5;
107 |
108 | Point aC = dblBufGC.textExtent("M");
109 | int aPosY = dblBounds.y+dblBounds.height/2;
110 | for(int i = currentKaiIdx;i >= 0 && i >= currentKaiIdx-5;i--) {
111 | if(i >= aSong.kaiSrt.chunkTexts.size()) {
112 | aPosY -= aC.y;
113 | continue;
114 | }
115 | String aKaiText = aSong.kaiSrt.chunkTexts.elementAt(i);
116 | if(i == currentKaiIdx) {
117 | Point aE = dblBufGC.textExtent(aKaiText);
118 | aPosY -= aE.y/2;
119 | continue;
120 | }
121 |
122 | for(String aT : aKaiText.split("\n")) {
123 | aPosY -= aC.y;
124 | }
125 | aPosY -= aC.y;
126 | }
127 | for(int i = currentKaiIdx-5;i < aSong.kaiSrt.chunkTexts.size();i++) {
128 | if(aPosY > dblBounds.height) {
129 | break;
130 | }
131 | if(i < 0) {
132 | continue;
133 | }
134 | // if(i == aJustBef) {
135 | // dblBufGC.setForeground(parentKDJ.logoLightC);
136 | // dblBufGC.drawLine(dblBounds.x, aPosY, dblBounds.x+dblBounds.width, aPosY);
137 | // }
138 | String aKaiText = aSong.kaiSrt.chunkTexts.elementAt(i);
139 | if(i == currentKaiIdx) {
140 | dblBufGC.setForeground(parentKDJ.logoLightC);
141 | }
142 | else {
143 | dblBufGC.setForeground(parentKDJ.logoDarkC);
144 | }
145 | for(String aT : aKaiText.split("\n")) {
146 | aT = aT.trim();
147 | if(i == aJustBef) {
148 | aT = "⇢⇢⇢ "+aT+" ⇠⇠⇠";
149 | }
150 | Point aE = dblBufGC.textExtent(aT);
151 | dblBufGC.drawText(aT,dblBounds.x + dblBounds.width/2 - aE.x/2, dblBounds.y + aPosY, true);
152 | aPosY += aC.y;
153 | }
154 | aPosY += aC.y;
155 | }
156 |
157 | }
158 |
159 | dblBufGC.drawImage(fullScreenBut, dblBounds.width-40, dblBounds.height-40);
160 |
161 | // Draw final image
162 | GC aPlGC = new GC(this);
163 | paintDbl(aPlGC);
164 | aPlGC.dispose();
165 | } catch (Throwable t) {
166 | System.err.println("Can't paint screen : " + t);
167 | t.printStackTrace(System.err);
168 | }
169 | }
170 |
171 | void paintDbl(GC aPlGC) {
172 | if(dblBuf == null) {
173 | return;
174 | }
175 | aPlGC.setAntialias(SWT.ON);
176 | aPlGC.setInterpolation(SWT.HIGH);
177 | aPlGC.drawImage(dblBuf
178 | ,0, 0, dblBounds.width, dblBounds.height
179 | , 0, 0,panelBounds.width,panelBounds.height);
180 | }
181 |
182 | }
183 |
--------------------------------------------------------------------------------
/src/com/cubaix/kai/KaiSrt.java:
--------------------------------------------------------------------------------
1 | package com.cubaix.kai;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.BufferedWriter;
5 | import java.io.File;
6 | import java.io.FileInputStream;
7 | import java.io.FileOutputStream;
8 | import java.io.InputStreamReader;
9 | import java.io.OutputStreamWriter;
10 | import java.util.Vector;
11 |
12 | import com.cubAIx.WhisperTimeSync.WhisperTimeSync;
13 | import com.cubaix.kaiDJ.utils.FileUtils;
14 |
15 | public class KaiSrt {
16 | static final boolean _DEBUG = false;
17 | String path = null;
18 | String text = null;
19 | String srt = null;
20 | String lng = "xx";
21 | public Vector chunkTexts = new Vector();
22 | public Vector chunkStarts = new Vector();
23 | public Vector chunkStops = new Vector();
24 |
25 | public KaiSrt(String aPath) {
26 | path = aPath;
27 | load();
28 | }
29 |
30 | public int getChunkIdx(long aTimeMS) {
31 | if(chunkStarts.size() <= 0) {
32 | return -1;
33 | }
34 | if(aTimeMS < chunkStarts.elementAt(0)) {
35 | return -1;
36 | }
37 | for(int l = 0;l < chunkTexts.size();l++) {
38 | if(chunkStarts.elementAt(l) <= aTimeMS && chunkStops.elementAt(l) > aTimeMS) {
39 | return l;
40 | }
41 | }
42 | for(int l = 0;l < chunkTexts.size();l++) {
43 | if(chunkStops.elementAt(l) > aTimeMS) {
44 | return l-1;
45 | }
46 | }
47 | if(aTimeMS > chunkStops.elementAt(chunkStops.size()-1)) {
48 | return chunkStops.size();
49 | }
50 | return -1;
51 | }
52 |
53 | public int getChunkIdxJustBefore(long aTimeMS) {
54 | for(int l = 0;l < chunkTexts.size();l++) {
55 | if(chunkStarts.elementAt(l) <= aTimeMS+1000 && chunkStarts.elementAt(l) > aTimeMS) {
56 | return l;
57 | }
58 | }
59 | return -1;
60 | }
61 |
62 | public String getChunkText(long aTimeMS) {
63 | int aIdx = getChunkIdx(aTimeMS);
64 | if(aIdx < 0) {
65 | return "";
66 | }
67 | return chunkTexts.elementAt(aIdx);
68 | }
69 |
70 | public void load() {
71 | try {
72 | String aKsrtPath = path+".ksrt";
73 | if(!new File(aKsrtPath).exists()) {
74 | FileUtils.unzipDir(path+".kai", new File(aKsrtPath).getParentFile().getCanonicalPath(), false);
75 | }
76 | if(new File(aKsrtPath+".edited").exists()) {
77 | aKsrtPath = aKsrtPath+".edited";
78 | }
79 | BufferedReader aBR = new BufferedReader(new InputStreamReader(new FileInputStream(aKsrtPath), "utf-8"));
80 | String aLine;
81 | StringBuffer aSB = new StringBuffer();
82 | while((aLine = aBR.readLine()) != null) {
83 | aLine = aLine.trim().replaceAll("\\\\n", "\n")
84 | .replaceAll("\r*\n", "\n");
85 | if(aSB.length() > 0) {
86 | aSB.append("\n");
87 | }
88 | aSB.append(aLine);
89 | }
90 | String aKsrt = aSB.toString();
91 | if(_DEBUG) {
92 | System.out.println(aKsrt);
93 | }
94 | if(aKsrt.indexOf("\n1\n") >= 0) {
95 | text = aKsrt.substring(0, aKsrt.indexOf("\n1\n00:"));
96 | srt = ("\n\n"+aKsrt.substring(aKsrt.indexOf("\n1\n00:")+1))
97 | .replaceAll("\n\n[0-9]+\n", "\n\n").substring(2);
98 | }
99 | else if(aKsrt.indexOf("\n00:") >= 0) {
100 | text = aKsrt.substring(0, aKsrt.indexOf("\n00:"));
101 | srt = ("\n\n"+aKsrt.substring(aKsrt.indexOf("\n00:")+1))
102 | .replaceAll("\n\n[0-9]+\n", "\n\n").substring(2);
103 | }
104 | else if(aKsrt.indexOf("\n") >= 0){
105 | text = aKsrt.substring(0, aKsrt.indexOf("\n"));
106 | srt = ("\n\n"+aKsrt.substring(aKsrt.indexOf("\n")+1))
107 | .replaceAll("\n\n[0-9]+\n", "\n\n").substring(2);
108 | }
109 | aBR.close();
110 |
111 | if(_DEBUG) {
112 | System.out.println("LOADED\n"
113 | + "----------\n"
114 | + "TEXT="+text+"\n"
115 | + "----------\n"
116 | + "SRT="+srt+"\n"
117 | );
118 | }
119 |
120 | resyncText2Srt();
121 | srt2Text();
122 | } catch (Exception e) {
123 | e.printStackTrace(System.err);
124 | }
125 | }
126 |
127 | public void save(String aPath) {
128 | try {
129 | BufferedWriter aBW = new BufferedWriter(
130 | new OutputStreamWriter(new FileOutputStream(aPath)
131 | ,"UTF8"));
132 | aBW.write(text+"\n"+srt);
133 | aBW.flush();
134 | aBW.close();
135 | } catch (Exception e) {
136 | }
137 | }
138 |
139 | public void resyncText2Srt() throws Exception {
140 | WhisperTimeSync aWTS = new WhisperTimeSync();
141 | srt = srt.replaceAll("<", "<").replaceAll(">", ">").replaceAll("\r*\n", "\n");
142 | text = text.replaceAll("<", "<").replaceAll(">", ">").replaceAll("\r*\n", "\n");
143 | String aSync = aWTS.processString(srt, text, lng);
144 | aSync = aSync.replaceAll("<", "<").replaceAll(">", ">").replaceAll("\r*\n", "\n");
145 | boolean aEmptyFound=true;
146 | StringBuffer aSB = new StringBuffer();
147 | chunkTexts = new Vector();
148 | chunkStarts = new Vector();
149 | chunkStops = new Vector();
150 | for(String aL : aSync.split("\n")) {
151 | aL = aL.trim();
152 | if(aL.isEmpty()) {
153 | aSB.append("\n");
154 | aEmptyFound = true;
155 | continue;
156 | }
157 | if(aEmptyFound && aL.matches("[0-9]+")) {
158 | //Ignore
159 | continue;
160 | }
161 | if(aL.matches("[0-9][0-9]:[0-9][0-9]:[0-9][0-9][.,][0-9][0-9][0-9] --> [0-9][0-9]:[0-9][0-9]:[0-9][0-9][.,][0-9][0-9][0-9]")) {
162 | aSB.append(aL);
163 | aSB.append("\n");
164 | chunkTexts.add("");
165 | Integer aStartH = Integer.parseInt(aL.substring(0, 2));
166 | Integer aStartM = Integer.parseInt(aL.substring(3, 5));
167 | Integer aStartS = Integer.parseInt(aL.substring(6, 8));
168 | Integer aStartMS = Integer.parseInt(aL.substring(9, 12));
169 | chunkStarts.add((long)(aStartH*60*60*1000+aStartM*60*1000+aStartS*1000+aStartMS));
170 | Integer aStopH = Integer.parseInt(aL.substring(17, 19));
171 | Integer aStopM = Integer.parseInt(aL.substring(20, 22));
172 | Integer aStopS = Integer.parseInt(aL.substring(23, 25));
173 | Integer aStopMS = Integer.parseInt(aL.substring(26, 29));
174 | chunkStops.add((long)(aStopH*60*60*1000+aStopM*60*1000+aStopS*1000+aStopMS));
175 | continue;
176 | }
177 | if(chunkTexts.size() <= 0) {
178 | //No chunk??
179 | aSB.append(aL);
180 | aSB.append("\n");
181 | continue;
182 | }
183 | String aCurrent = chunkTexts.elementAt(chunkTexts.size()-1);
184 | if(aCurrent.length() > 0) {
185 | aSB.append("\n");
186 | aCurrent += "\n";
187 | }
188 | aSB.append(aL);
189 | aCurrent += aL;
190 | chunkTexts.setElementAt(aCurrent,chunkTexts.size()-1);
191 | }
192 | srt = aSB.toString().trim();
193 | }
194 |
195 | public void srt2Text() {
196 | boolean aInText = false;
197 | StringBuffer aSB = new StringBuffer();
198 | srt = srt.replaceAll("<", "<").replaceAll(">", ">").replaceAll("\r*\n", "\n");
199 | if(_DEBUG) {
200 | System.out.println("srt2Text() srt="+srt);
201 | }
202 | for(String aL : srt.split("\n")) {
203 | aL = aL.trim();
204 | if(_DEBUG) {
205 | System.out.println("srt2Text() aL="+aL);
206 | }
207 | if(aL.isEmpty()) {
208 | aInText = false;
209 | if(_DEBUG) {
210 | System.out.println("srt2Text() INTEXT OFF");
211 | }
212 | }
213 | if(aL.matches("[0-9][0-9]:[0-9][0-9]:[0-9][0-9][.,][0-9][0-9][0-9] --> [0-9][0-9]:[0-9][0-9]:[0-9][0-9][.,][0-9][0-9][0-9]")) {
214 | aInText = true;
215 | if(_DEBUG) {
216 | System.out.println("srt2Text() INTEXT ON");
217 | }
218 | continue;
219 | }
220 | if(aInText) {
221 | aSB.append(aL);
222 | aSB.append("\n");
223 | if(_DEBUG) {
224 | System.out.println("srt2Text() ADDED TXT="+aL);
225 | }
226 | }
227 | }
228 | text = aSB.toString();
229 | if(_DEBUG) {
230 | System.out.println("srt2Text() text="+text);
231 | }
232 | }
233 |
234 | public static void main(String[] args) {
235 | try {
236 | KaiSrt aSrt = new KaiSrt("/home/cubaix/Musique/MP3/Soiree3eme/Best of 2011/Katy Perry - Firework.mp3");
237 | for(int l = 0;l < aSrt.chunkTexts.size();l++) {
238 | System.out.println(aSrt.chunkStarts.elementAt(l)+" --> "+aSrt.chunkStops.elementAt(l)+" "+aSrt.chunkTexts.elementAt(l));
239 | }
240 | } catch (Exception e) {
241 | e.printStackTrace(System.err);
242 | }
243 | }
244 |
245 | }
246 |
--------------------------------------------------------------------------------
/src/com/cubaix/kai/KaiViewer.java:
--------------------------------------------------------------------------------
1 | package com.cubaix.kai;
2 |
3 | import org.eclipse.swt.SWT;
4 | import org.eclipse.swt.events.MouseEvent;
5 | import org.eclipse.swt.events.MouseListener;
6 | import org.eclipse.swt.events.PaintEvent;
7 | import org.eclipse.swt.events.PaintListener;
8 | import org.eclipse.swt.graphics.GC;
9 | import org.eclipse.swt.graphics.Rectangle;
10 | import org.eclipse.swt.layout.GridData;
11 | import org.eclipse.swt.layout.GridLayout;
12 | import org.eclipse.swt.widgets.Display;
13 | import org.eclipse.swt.widgets.Shell;
14 |
15 | import com.cubaix.kaiDJ.KaiDJ;
16 |
17 | public class KaiViewer {
18 | protected KaiEditor parentKE = null;
19 |
20 | public Shell shell = null;
21 | public GC mainGC = null;
22 |
23 | KaiScreener screener = null;
24 |
25 | public KaiViewer(KaiEditor aParentKE) {
26 | parentKE = aParentKE;
27 | start();
28 | }
29 |
30 | void createInterface() {
31 | // final jDJ aThis = this;
32 | shell = new Shell(parentKE.parentKDJ.display, SWT.SHELL_TRIM);
33 | shell.setText("karaok-AI " + parentKE.parentKDJ._VERSION);
34 | shell.open();
35 | mainGC = new GC(shell);
36 | shell.addPaintListener(new PaintListener() {
37 | public void paintControl(PaintEvent arg0) {
38 | paint();
39 | }
40 | });
41 | shell.setImage(parentKE.parentKDJ.kaiIcon);
42 | GridLayout gridLayout = new GridLayout();
43 | gridLayout.numColumns = 1;
44 | gridLayout.marginWidth = 0;
45 | gridLayout.marginHeight = 0;
46 | gridLayout.horizontalSpacing = 0;
47 | gridLayout.verticalSpacing = 0;
48 | shell.setLayout(gridLayout);
49 |
50 | screener = new KaiScreener(this, shell, SWT.FILL);
51 | GridData aGD = new GridData(GridData.FILL_BOTH);
52 | screener.setLayoutData(aGD);
53 | screener.setBackground(parentKE.parentKDJ.playerC);
54 | screener.setForeground(parentKE.parentKDJ.blackC);
55 | screener.addMouseListener(new MouseListener() {
56 | @Override
57 | public void mouseUp(MouseEvent arg0) {
58 | shell.setFullScreen(!shell.getFullScreen());
59 | }
60 |
61 | @Override
62 | public void mouseDown(MouseEvent arg0) {
63 | }
64 |
65 | @Override
66 | public void mouseDoubleClick(MouseEvent arg0) {
67 | }
68 | });
69 |
70 | shell.pack();
71 | // Size
72 | Rectangle aR = parentKE.parentKDJ.display.getBounds();
73 | if(aR.width > 1920) {
74 | aR.width = 1920;
75 | }
76 | if(aR.height > 1080) {
77 | aR.height = 1080;
78 | }
79 | aR.width /=2;
80 | aR.height /=2;
81 | aR.x += aR.width;
82 | aR.y += aR.height;
83 | aR.width -= 20;
84 | if(aR.y+aR.height > parentKE.parentKDJ.display.getBounds().height - 40) {
85 | aR.y = parentKE.parentKDJ.display.getBounds().height-aR.height - 40;
86 | }
87 | if(KaiDJ._SIZE_FOR_SCREENSHOTS) {
88 | aR.width = KaiDJ._SIZE_FOR_SCREENSHOTS_W;
89 | aR.height = KaiDJ._SIZE_FOR_SCREENSHOTS_H;
90 | }
91 | shell.setBounds(aR);
92 | }
93 |
94 | void paint() {
95 | if(KaiDJ._DEBUG_PAINT) {
96 | System.out.println("VIEWER.paint()");
97 | }
98 | synchronized (mainGC) {
99 | Rectangle aRect = shell.getBounds();
100 | mainGC = new GC(shell);
101 | mainGC.setClipping(0, 0, aRect.width, aRect.height);
102 | mainGC.setBackground(parentKE.parentKDJ.mainBckC);
103 | mainGC.fillRectangle(0, 0, aRect.width, aRect.height);
104 | mainGC.dispose();
105 | screener.needRedrawSlow();
106 | }
107 | }
108 |
109 | void start() {
110 | try {
111 | // Create interface
112 | createInterface();
113 | }
114 | catch (Throwable t) {
115 | t.printStackTrace(System.err);
116 | }
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/src/com/cubaix/kai/LogoPanel.java:
--------------------------------------------------------------------------------
1 | package com.cubaix.kai;
2 |
3 | import java.io.InputStream;
4 | import java.util.StringTokenizer;
5 |
6 | import org.eclipse.swt.events.PaintEvent;
7 | import org.eclipse.swt.events.PaintListener;
8 | import org.eclipse.swt.graphics.GC;
9 | import org.eclipse.swt.graphics.Image;
10 | import org.eclipse.swt.graphics.Rectangle;
11 | import org.eclipse.swt.widgets.Composite;
12 |
13 | import com.cubaix.kaiDJ.DJPlayer;
14 | import com.cubaix.kaiDJ.KaiDJ;
15 | import com.cubaix.kaiDJ.swt.TimedCanvas;
16 |
17 | public class LogoPanel extends TimedCanvas {
18 | private KaiEditor parentKE;
19 | Image panelBck = null;
20 | // Image panelTransBck = null;
21 | public String help = null;
22 | final int lineHeight = 15;
23 |
24 | Rectangle panelBounds = null;
25 | Image dblBuf = null;
26 | GC dblBufGC;
27 |
28 | public LogoPanel(KaiEditor aParentKE, Composite parent, int style) {
29 | super(aParentKE.parentKDJ, parent, style);
30 | parentKE = aParentKE;
31 | final LogoPanel aThis = this;
32 | addPaintListener(new PaintListener() {
33 | public void paintControl(PaintEvent aPE) {
34 | panelBounds = getClientArea();
35 | GC aPlGC = new GC(aThis);
36 | paintDbl(aPlGC);
37 | aPlGC.dispose();
38 | needRedraw();
39 | }
40 | });
41 | }
42 |
43 | void loadImg() {
44 | if (parentKDJ == null || parentKDJ.display == null || parentKDJ.display.isDisposed()) {
45 | return;
46 | }
47 | InputStream aIS = getClass().getResourceAsStream("img/LogoSmall.png");
48 | panelBck = new Image(parentKDJ.display, aIS);
49 |
50 | // panelTransBck = new Image(parentJDJ.display, aIS);
51 | // byte[] aAlpha = panelTransBck.getImageData().alphaData;
52 | // if(aAlpha != null){
53 | // for(int i = 0;i < aAlpha.length;i++){
54 | // aAlpha[i] = 127;
55 | // }
56 | // }
57 | }
58 |
59 | protected void paintTimed() {
60 | if(KaiDJ._DEBUG_PAINT) {
61 | System.out.println("LOGOPANEL.paintTimed()");
62 | }
63 | if (panelBck == null) {
64 | loadImg();
65 | }
66 | if(panelBck == null || panelBounds == null){
67 | return;
68 | }
69 | try {
70 | Rectangle aRectDbl = null;
71 | if (dblBuf != null) {
72 | aRectDbl = dblBuf.getBounds();
73 | }
74 | if (dblBuf == null || panelBounds.width != aRectDbl.width || panelBounds.height != aRectDbl.height) {
75 | if (dblBuf != null) {
76 | dblBuf.dispose();
77 | dblBuf = null;
78 | dblBufGC.dispose();
79 | }
80 | dblBuf = new Image(parentKDJ.display, panelBounds);
81 | dblBufGC = new GC(dblBuf);
82 | }
83 |
84 | Rectangle aImgR = panelBck.getBounds();
85 | dblBufGC.setClipping(panelBounds.x, panelBounds.y, panelBounds.width, panelBounds.height);
86 | dblBufGC.setForeground(parentKDJ.blackC);
87 | dblBufGC.setBackground(parentKDJ.mainBckC);
88 | dblBufGC.fillRectangle(panelBounds);
89 | if (help == null) {
90 | dblBufGC.drawImage(panelBck, panelBounds.x /* + (panelBounds.width - aImgR.width) / 2 */, panelBounds.y);
91 | } else {
92 | // dblBufGC.drawImage(panelTransBck, panelBounds.x + (panelBounds.width - aImgR.width) / 2, panelBounds.y);
93 | dblBufGC.drawImage(panelBck, panelBounds.x, panelBounds.y);
94 | StringTokenizer aTok = new StringTokenizer(help, "\n");
95 | int aPosY = 0;
96 | dblBufGC.setFont(parentKDJ.initialFont);
97 | dblBufGC.setForeground(parentKDJ.playerC);
98 | // dblBufGC.drawText("** HELP **", aImgR.width, aPosY, true);
99 | aPosY += lineHeight;
100 | while (aTok.hasMoreTokens()) {
101 | String aStr = aTok.nextToken();
102 | dblBufGC.drawText(aStr, panelBounds.x + aImgR.width, panelBounds.y + aPosY, true);
103 | aPosY += lineHeight;
104 | }
105 | }
106 |
107 | dblBufGC.setForeground(parentKDJ.playerC);
108 | if(parentKE.song != null && parentKE.song.kaiSrt != null) {
109 | dblBufGC.setFont(parentKDJ.kaiFont);
110 | dblBufGC.setForeground(parentKDJ.playerC);
111 | int aPadding = 5;
112 |
113 | int aKaiIdx = parentKE.song.kaiSrt.getChunkIdx(parentKE.playerVocals.getPositionMs());
114 | String aKaiText = (aKaiIdx < 0) ? "" : ((aKaiIdx >= parentKE.song.kaiSrt.chunkTexts.size()) ? "" :parentKE.song.kaiSrt.chunkTexts.elementAt(aKaiIdx));
115 | aKaiText = aKaiText.replaceAll("\n", " ").trim();
116 |
117 | for(int i = aKaiIdx+1;i < parentKE.song.kaiSrt.chunkTexts.size();i++) {
118 | String aKaiTextNext = parentKE.song.kaiSrt.chunkTexts.elementAt(i);
119 | aKaiText += (aKaiText.length() > 0 ? " — ":"")+aKaiTextNext.replaceAll("\n", " ").trim();
120 | }
121 |
122 | dblBufGC.drawText(aKaiText,panelBounds.x + aPadding, panelBounds.y + panelBounds.height - aPadding - 18, true);
123 | }
124 | if(parentKDJ.player1.kaiSrt != null || parentKDJ.player2.kaiSrt != null) {
125 | needRedrawSlow();
126 | }
127 |
128 | // Draw final image
129 | GC aPlGC = new GC(this);
130 | paintDbl(aPlGC);
131 | aPlGC.dispose();
132 | }
133 | catch (Throwable t) {
134 | System.err.println("Can't paint logo : " + t);
135 | t.printStackTrace(System.err);
136 | }
137 | }
138 |
139 | void paintDbl(GC aPlGC) {
140 | if(dblBuf == null) {
141 | return;
142 | }
143 | aPlGC.drawImage(dblBuf, 0, 0);
144 | }
145 | }
146 |
--------------------------------------------------------------------------------
/src/com/cubaix/kai/img/Logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EtienneAb3d/karaok-AI/2eaaf4fba6234ad6206e112c59a0d6143540aace/src/com/cubaix/kai/img/Logo.png
--------------------------------------------------------------------------------
/src/com/cubaix/kai/img/LogoSmall.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EtienneAb3d/karaok-AI/2eaaf4fba6234ad6206e112c59a0d6143540aace/src/com/cubaix/kai/img/LogoSmall.png
--------------------------------------------------------------------------------
/src/com/cubaix/kai/img/LogoSquare.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EtienneAb3d/karaok-AI/2eaaf4fba6234ad6206e112c59a0d6143540aace/src/com/cubaix/kai/img/LogoSquare.png
--------------------------------------------------------------------------------
/src/com/cubaix/kai/img/LogoSquareL.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EtienneAb3d/karaok-AI/2eaaf4fba6234ad6206e112c59a0d6143540aace/src/com/cubaix/kai/img/LogoSquareL.png
--------------------------------------------------------------------------------
/src/com/cubaix/kai/img/kAI.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
89 |
--------------------------------------------------------------------------------
/src/com/cubaix/kai/img2/arrows-fullscreen.svg:
--------------------------------------------------------------------------------
1 |
2 |
45 |
--------------------------------------------------------------------------------
/src/com/cubaix/kai/img2/fullscreen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EtienneAb3d/karaok-AI/2eaaf4fba6234ad6206e112c59a0d6143540aace/src/com/cubaix/kai/img2/fullscreen.png
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/CategoryManager.java:
--------------------------------------------------------------------------------
1 | package com.cubaix.kaiDJ;
2 |
3 | import java.util.Vector;
4 |
5 | import org.eclipse.swt.SWT;
6 | import org.eclipse.swt.events.KeyEvent;
7 | import org.eclipse.swt.events.KeyListener;
8 | import org.eclipse.swt.events.MouseEvent;
9 | import org.eclipse.swt.events.MouseListener;
10 | import org.eclipse.swt.events.SelectionEvent;
11 | import org.eclipse.swt.events.SelectionListener;
12 | import org.eclipse.swt.layout.GridData;
13 | import org.eclipse.swt.layout.GridLayout;
14 | import org.eclipse.swt.widgets.Combo;
15 | import org.eclipse.swt.widgets.Composite;
16 | import org.eclipse.swt.widgets.Label;
17 |
18 | import com.cubaix.kaiDJ.db.SongDescr;
19 | import com.cubaix.kaiDJ.swt.PlayListListener;
20 |
21 | public class CategoryManager extends Composite {
22 | KaiDJ parentJDJ;
23 | PlayList pl;
24 | PlayListListener playListListener;
25 | Combo categoriesC;
26 | // Text categoryT;
27 | String currentCategory = "";
28 | public CategoryManager(KaiDJ aParentJDJ,Composite parent, int style) {
29 | super(parent, style);
30 | parentJDJ = aParentJDJ;
31 |
32 | String os = System.getProperty("os.name");
33 |
34 | //Main panel
35 | GridLayout aGL = new GridLayout();
36 | aGL.horizontalSpacing = 0;
37 | aGL.verticalSpacing = 0;
38 | aGL.marginHeight = 0;
39 | aGL.marginWidth = 0;
40 | aGL.numColumns = 1;
41 | this.setLayout(aGL);
42 | GridData aGD = new GridData(GridData.FILL_BOTH);
43 | this.setLayoutData(aGD);
44 |
45 | //Buttons
46 | Composite aButPanel = new Composite(this,SWT.NULL);
47 | aGL = new GridLayout();
48 | aGL.horizontalSpacing = 0;
49 | aGL.verticalSpacing = 0;
50 | aGL.marginHeight = 0;
51 | aGL.marginWidth = 0;
52 | aGL.numColumns = 2;
53 | aButPanel.setLayout(aGL);
54 | aGD = new GridData(GridData.FILL_HORIZONTAL);
55 | aButPanel.setLayoutData(aGD);
56 |
57 | Label aLabel = new Label(aButPanel,SWT.NULL);
58 | aLabel.setText("Category name: ");
59 | if(!os.toLowerCase().startsWith("mac")){
60 | //Mac seems to not support properly background colors here
61 | aLabel.setBackground(parentJDJ.mainBckC);
62 | aLabel.setForeground(parentJDJ.playerC);
63 | }
64 | aGD = new GridData(GridData.FILL_VERTICAL);
65 | aLabel.setLayoutData(aGD);
66 |
67 | categoriesC = new Combo(aButPanel,SWT.NULL);
68 | categoriesC.setToolTipText("Select/Enter a category");
69 | if(!os.toLowerCase().startsWith("mac")){
70 | //Mac seems to not support properly background colors here
71 | categoriesC.setBackground(parentJDJ.mainBckC);
72 | categoriesC.setForeground(parentJDJ.whiteC);
73 | }
74 | aGD = new GridData(GridData.FILL_BOTH);
75 | categoriesC.setLayoutData(aGD);
76 | categoriesC.addSelectionListener(new SelectionListener(){
77 | public void widgetDefaultSelected(SelectionEvent arg0) {
78 | }
79 | public void widgetSelected(SelectionEvent evt) {
80 | currentCategory = categoriesC.getItem(categoriesC.getSelectionIndex());
81 | doCategory();
82 | }
83 |
84 | });
85 | categoriesC.addKeyListener(new KeyListener() {
86 | public void keyPressed(KeyEvent arg0) {}
87 | public void keyReleased(KeyEvent arg0) {
88 | int aCharCode = arg0.character & 0xFF;
89 | if (aCharCode > 32 || arg0.keyCode == 8 || (arg0.keyCode >= 32 && arg0.keyCode < 65535)) {
90 | currentCategory = categoriesC.getText();
91 | doCategory();
92 | }
93 | }
94 | });
95 |
96 | // categoryT = new Text(aButPanel, SWT.BORDER);
97 | // categoryT.setToolTipText("Enter a category");
98 | // if(!os.toLowerCase().startsWith("mac")){
99 | // //Mac seems to not support properly background colors here
100 | // categoryT.setBackground(parentJDJ.mainBckC);
101 | // categoryT.setForeground(parentJDJ.whiteC);
102 | // }
103 | // aGD = new GridData(GridData.FILL_BOTH);
104 | // categoryT.setLayoutData(aGD);
105 | // categoryT.addKeyListener(new KeyListener() {
106 | // public void keyPressed(KeyEvent arg0) {}
107 | // public void keyReleased(KeyEvent arg0) {
108 | // int aCharCode = arg0.character & 0xFF;
109 | // if (aCharCode > 32 || arg0.keyCode == 8 || (arg0.keyCode >= 32 && arg0.keyCode < 65535)) {
110 | // currentCategory = categoryT.getText();
111 | // pl.getPl().clear();
112 | // parentJDJ.db.getCat(pl.getPl(),currentCategory);
113 | // pl.needRedraw();
114 | // }
115 | // }
116 | // });
117 |
118 | //PL
119 | pl = new PlayList(aParentJDJ, this, SWT.NONE);
120 | pl.listTC.setToolTip("Edit category: \n"//
121 | + "- Click to load a song on the pre-listen player\n"//
122 | + "- Double-click to add a song at the end of the playlist\n"//
123 | + "- Ctrl+Click to add a song after the current selection or the current playing song\n"//
124 | + "- Suppr key to remove a song");
125 | aGD = new GridData(GridData.FILL_BOTH);
126 | pl.setLayoutData(aGD);
127 | pl.addMouseListener(new MouseListener() {
128 | public void mouseDoubleClick(MouseEvent aEvt) {
129 | if (pl.isClickInTopBar(aEvt.x, aEvt.y)) {
130 | // Nothing to do
131 | } else {
132 | //Add song to playlist
133 | SongDescr aDescr = pl.getMp3Descr(aEvt.x, aEvt.y);
134 | if (aDescr != null) {
135 | parentJDJ.managerPlay.addSong(aDescr);
136 | }
137 | }
138 | }
139 |
140 | public void mouseDown(MouseEvent aEvt) {
141 | if(aEvt.stateMask == SWT.CTRL){
142 | //Add after
143 | if (pl.isClickInTopBar(aEvt.x, aEvt.y)) {
144 | // Nothing to do
145 | } else {
146 | SongDescr aDescr = pl.getMp3Descr(aEvt.x, aEvt.y);
147 | if (aDescr != null) {
148 | //Add song to playlist
149 | parentJDJ.managerPlay.addSongAfter(aDescr);
150 | }
151 | }
152 | }
153 | }
154 |
155 | public void mouseUp(MouseEvent arg0) {
156 | }
157 | });
158 | pl.addPlayListListener(playListListener = new PlayListListener(){
159 | public void removed(SongDescr aDescr) {
160 | parentJDJ.db.delInCat(aDescr,currentCategory);
161 | updateCategoriesList();
162 | }
163 | public void added(SongDescr aDescr) {
164 | parentJDJ.db.insertCat(aDescr,currentCategory);
165 | parentJDJ.db.commit();
166 | updateCategoriesList();
167 | }
168 | });
169 |
170 | //Init values
171 | updateCategoriesList();
172 | }
173 |
174 |
175 |
176 | /* (non-Javadoc)
177 | * @see org.eclipse.swt.widgets.Widget#dispose()
178 | */
179 | public void dispose() {
180 | pl.removePlayListListener(playListListener);
181 | super.dispose();
182 | }
183 |
184 | /**
185 | * @param aDefaultCat
186 | */
187 | public void checkCategory(String aDefaultCat){
188 | if(currentCategory == null || currentCategory.length() <= 0){
189 | currentCategory = aDefaultCat;
190 | parentJDJ.display.syncExec(new Runnable(){
191 | public void run() {
192 | categoriesC.setText(currentCategory);
193 | }
194 |
195 | });
196 | }
197 | }
198 |
199 | /**
200 | * @param aDescr
201 | */
202 | public void addSong(SongDescr aDescr){
203 | checkCategory("Misc");
204 | parentJDJ.db.insertCat(aDescr,currentCategory);
205 | parentJDJ.db.commit();
206 | pl.getPl().add(aDescr);
207 | pl.listTC.needRedraw();
208 | updateCategoriesList();
209 | }
210 |
211 | /**
212 | * @param aPath
213 | * @param aClear
214 | */
215 | public void load(String aPath, boolean aClear) {
216 | pl.load(aPath, aClear, 0);
217 | }
218 |
219 | /**
220 | *
221 | */
222 | void updateCategoriesList(){
223 | final Vector aRes = parentJDJ.db.getAllCat();
224 | parentJDJ.display.syncExec(new Runnable(){
225 | public void run() {
226 | categoriesC.removeAll();
227 | for(int c = 0;c < aRes.size();c++){
228 | categoriesC.add((String)aRes.elementAt(c));
229 | }
230 | categoriesC.setText(currentCategory);
231 | }
232 | });
233 | }
234 |
235 | /**
236 | *
237 | */
238 | void doCategory(){
239 | // Start main refresh thread
240 | Thread aThread = new Thread(new Runnable(){
241 | public void run() {
242 | pl.getPl().clear();
243 | parentJDJ.db.getCat(pl.getPl(),currentCategory);
244 | pl.listTC.needRedraw();
245 | }
246 | }, "Category request");
247 | aThread.setPriority(Thread.MIN_PRIORITY);
248 | aThread.start();
249 | }
250 |
251 | }
252 |
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/LogoPanel.java:
--------------------------------------------------------------------------------
1 | package com.cubaix.kaiDJ;
2 |
3 | import java.io.InputStream;
4 | import java.util.StringTokenizer;
5 |
6 | import org.eclipse.swt.events.PaintEvent;
7 | import org.eclipse.swt.events.PaintListener;
8 | import org.eclipse.swt.graphics.GC;
9 | import org.eclipse.swt.graphics.Image;
10 | import org.eclipse.swt.graphics.Rectangle;
11 | import org.eclipse.swt.widgets.Composite;
12 |
13 | import com.cubaix.kai.KaiSrt;
14 | import com.cubaix.kaiDJ.swt.TimedCanvas;
15 |
16 | public class LogoPanel extends TimedCanvas {
17 | private KaiDJ parentKDJ;
18 | Image panelBck = null;
19 | // Image panelTransBck = null;
20 | public String help = null;
21 | final int lineHeight = 15;
22 |
23 | Rectangle panelBounds = null;
24 | Image dblBuf = null;
25 | GC dblBufGC;
26 |
27 | static final int _SOUNDPROFILESIZE = 128;
28 | float[] soundProfile1 = new float[_SOUNDPROFILESIZE];
29 | float[] soundProfile2 = new float[_SOUNDPROFILESIZE];
30 | int soundProfilePos = 0;
31 |
32 | public LogoPanel(KaiDJ aParentKDJ, Composite parent, int style) {
33 | super(aParentKDJ, parent, style);
34 | parentKDJ = aParentKDJ;
35 | final LogoPanel aThis = this;
36 | addPaintListener(new PaintListener() {
37 | public void paintControl(PaintEvent aPE) {
38 | panelBounds = getClientArea();
39 | GC aPlGC = new GC(aThis);
40 | paintDbl(aPlGC);
41 | aPlGC.dispose();
42 | needRedraw();
43 | }
44 | });
45 |
46 | //EM 15/11/2008
47 | createSoundProfileThread();
48 | }
49 |
50 | void loadImg() {
51 | if (parentKDJ == null || parentKDJ.display == null || parentKDJ.display.isDisposed()) {
52 | return;
53 | }
54 | InputStream aIS = getClass().getResourceAsStream("img/LogoSmall.png");
55 | panelBck = new Image(parentKDJ.display, aIS);
56 |
57 | // panelTransBck = new Image(parentJDJ.display, aIS);
58 | // byte[] aAlpha = panelTransBck.getImageData().alphaData;
59 | // if(aAlpha != null){
60 | // for(int i = 0;i < aAlpha.length;i++){
61 | // aAlpha[i] = 127;
62 | // }
63 | // }
64 | }
65 |
66 | protected void paintTimed() {
67 | if(KaiDJ._DEBUG_PAINT) {
68 | System.out.println("LOGOPANEL.paintTimed()");
69 | }
70 | if (panelBck == null) {
71 | loadImg();
72 | }
73 | if(panelBck == null || panelBounds == null){
74 | return;
75 | }
76 | try {
77 | Rectangle aRectDbl = null;
78 | if (dblBuf != null) {
79 | aRectDbl = dblBuf.getBounds();
80 | }
81 | if (dblBuf == null || panelBounds.width != aRectDbl.width || panelBounds.height != aRectDbl.height) {
82 | if (dblBuf != null) {
83 | dblBuf.dispose();
84 | dblBuf = null;
85 | dblBufGC.dispose();
86 | }
87 | dblBuf = new Image(parentKDJ.display, panelBounds);
88 | dblBufGC = new GC(dblBuf);
89 | }
90 |
91 | Rectangle aImgR = panelBck.getBounds();
92 | dblBufGC.setClipping(panelBounds.x, panelBounds.y, panelBounds.width, panelBounds.height);
93 | dblBufGC.setForeground(parentKDJ.blackC);
94 | dblBufGC.setBackground(parentKDJ.mainBckC);
95 | dblBufGC.fillRectangle(panelBounds);
96 | if (help == null) {
97 | dblBufGC.drawImage(panelBck, panelBounds.x /* + (panelBounds.width - aImgR.width) / 2 */, panelBounds.y);
98 | } else {
99 | // dblBufGC.drawImage(panelTransBck, panelBounds.x + (panelBounds.width - aImgR.width) / 2, panelBounds.y);
100 | dblBufGC.drawImage(panelBck, panelBounds.x, panelBounds.y);
101 | StringTokenizer aTok = new StringTokenizer(help, "\n");
102 | int aPosY = 0;
103 | dblBufGC.setFont(parentKDJ.initialFont);
104 | dblBufGC.setForeground(parentKDJ.playerC);
105 | // dblBufGC.drawText("** HELP **", aImgR.width, aPosY, true);
106 | aPosY += lineHeight;
107 | while (aTok.hasMoreTokens()) {
108 | String aStr = aTok.nextToken();
109 | dblBufGC.drawText(aStr, panelBounds.x + aImgR.width, panelBounds.y + aPosY, true);
110 | aPosY += lineHeight;
111 | }
112 | }
113 |
114 | dblBufGC.setForeground(parentKDJ.playerC);
115 | DJPlayer aPlayerSrt = null;
116 | if(parentKDJ.player1.currentGain > parentKDJ.player2.currentGain) {
117 | aPlayerSrt = parentKDJ.player1;
118 | }
119 | else {
120 | aPlayerSrt = parentKDJ.player2;
121 | }
122 | if(aPlayerSrt.kaiSrt != null) {
123 | dblBufGC.setFont(parentKDJ.kaiFont);
124 | dblBufGC.setForeground(parentKDJ.playerC);
125 | int aPadding = 5;
126 |
127 | int aKaiIdx = aPlayerSrt.kaiSrt.getChunkIdx(aPlayerSrt.getPositionMs());
128 | String aKaiText = (aKaiIdx < 0) ? "" : aPlayerSrt.kaiSrt.chunkTexts.elementAt(aKaiIdx);
129 | aKaiText = aKaiText.replaceAll("\n", " ").trim();
130 |
131 | for(int i = aKaiIdx+1;i < aPlayerSrt.kaiSrt.chunkTexts.size();i++) {
132 | String aKaiTextNext = aPlayerSrt.kaiSrt.chunkTexts.elementAt(i);
133 | aKaiText += (aKaiText.length() > 0 ? " — ":"")+aKaiTextNext.replaceAll("\n", " ").trim();
134 | }
135 |
136 | dblBufGC.drawText(aKaiText,panelBounds.x + aPadding, panelBounds.y + panelBounds.height - aPadding - 18, true);
137 | }
138 | if(parentKDJ.player1.kaiSrt != null || parentKDJ.player2.kaiSrt != null) {
139 | needRedrawSlow();
140 | }
141 |
142 | // Draw final image
143 | GC aPlGC = new GC(this);
144 | paintDbl(aPlGC);
145 | aPlGC.dispose();
146 | }
147 | catch (Throwable t) {
148 | System.err.println("Can't paint logo : " + t);
149 | t.printStackTrace(System.err);
150 | }
151 | }
152 |
153 | void paintDbl(GC aPlGC) {
154 | if(dblBuf == null) {
155 | return;
156 | }
157 | aPlGC.drawImage(dblBuf, 0, 0);
158 | }
159 |
160 | //EM 15/11/2008
161 | void createSoundProfileThread(){
162 | Thread aTh = new Thread(new Runnable(){
163 | public void run() {
164 | while(true){
165 | try{
166 | Thread.sleep(40);
167 | //Read values
168 | soundProfile1[soundProfilePos] = (float)parentKDJ.player1.currentGain * (parentKDJ.player1.vuMeterRight + parentKDJ.player1.vuMeterLeft) / 2;
169 | soundProfile2[soundProfilePos] = (float)parentKDJ.player2.currentGain * (parentKDJ.player2.vuMeterRight + parentKDJ.player2.vuMeterLeft) / 2;
170 | soundProfilePos++;
171 | soundProfile1[soundProfilePos] = (float)parentKDJ.player1.currentGain * (parentKDJ.player1.vuMeterRightB + parentKDJ.player1.vuMeterLeftB) / 2;
172 | soundProfile2[soundProfilePos] = (float)parentKDJ.player2.currentGain * (parentKDJ.player2.vuMeterRightB + parentKDJ.player2.vuMeterLeftB) / 2;
173 | soundProfilePos++;
174 | soundProfilePos = soundProfilePos % _SOUNDPROFILESIZE;
175 |
176 | //EM 28/04/2009 : only if activated
177 | if(parentKDJ.showSoundProfile){
178 | parentKDJ.display.asyncExec(new Runnable() {
179 | public void run() {
180 | try {
181 | paintSoundProfile();
182 | } catch (Throwable t) {
183 | }
184 | }
185 | });
186 | }
187 |
188 | }
189 | catch(Throwable t){
190 | //??
191 | }
192 | }
193 | }
194 | });
195 | aTh.start();
196 | }
197 |
198 | static final int _SOUNDPROFILEHEIGHT = 20;
199 | void paintSoundProfile(){
200 | if(KaiDJ._DEBUG_PAINT) {
201 | System.out.println("LOGOPANEL.paintSoundProfile()");
202 | }
203 | if(panelBck == null || panelBounds == null){
204 | return;
205 | }
206 | try {
207 | GC panelGC = new GC(this);
208 | Rectangle aImgR = panelBck.getBounds();
209 | //panelGC.setClipping(panelBounds.x, panelBounds.y, panelBounds.width, panelBounds.height);
210 |
211 | for(int i = 0; i < _SOUNDPROFILESIZE;){
212 | panelGC.setForeground(parentKDJ.mainBckC);
213 | panelGC.drawLine(panelBounds.x + i, panelBounds.y + aImgR.height + 28, panelBounds.x + i, panelBounds.y + aImgR.height + 10 - _SOUNDPROFILEHEIGHT);
214 | panelGC.drawLine(panelBounds.x + i + 1, panelBounds.y + aImgR.height + 28, panelBounds.x + i + 1, panelBounds.y + aImgR.height + 10 - _SOUNDPROFILEHEIGHT);
215 | panelGC.setForeground(parentKDJ.redC);
216 | panelGC.drawLine(panelBounds.x + i, panelBounds.y + aImgR.height + 10, panelBounds.x + i, panelBounds.y + aImgR.height + 10 - (int)(_SOUNDPROFILEHEIGHT*soundProfile1[(soundProfilePos + i)%_SOUNDPROFILESIZE]));
217 | //EM 28/04/2009 : bottom to top
218 | panelGC.drawLine(panelBounds.x + i, panelBounds.y + aImgR.height + 28, panelBounds.x + i, panelBounds.y + aImgR.height + 28 - (int)(_SOUNDPROFILEHEIGHT*soundProfile2[(soundProfilePos + i)%_SOUNDPROFILESIZE]));
219 | i++;
220 | panelGC.setForeground(parentKDJ.yellowC);
221 | panelGC.drawLine(panelBounds.x + i, panelBounds.y + aImgR.height + 10, panelBounds.x + i, panelBounds.y + aImgR.height + 10 - (int)(_SOUNDPROFILEHEIGHT*soundProfile1[(soundProfilePos + i)%_SOUNDPROFILESIZE]));
222 | //EM 28/04/2009 : bottom to top
223 | panelGC.drawLine(panelBounds.x + i, panelBounds.y + aImgR.height + 28, panelBounds.x + i, panelBounds.y + aImgR.height + 28 - (int)(_SOUNDPROFILEHEIGHT*soundProfile2[(soundProfilePos + i)%_SOUNDPROFILESIZE]));
224 | i++;
225 | }
226 | panelGC.dispose();
227 | } catch (Throwable t) {
228 | System.err.println("Can't paint logo : " + t);
229 | t.printStackTrace(System.err);
230 | }
231 | }
232 | }
233 |
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/PlayManager.java:
--------------------------------------------------------------------------------
1 | package com.cubaix.kaiDJ;
2 |
3 | import org.eclipse.swt.SWT;
4 | import org.eclipse.swt.events.KeyEvent;
5 | import org.eclipse.swt.events.KeyListener;
6 | import org.eclipse.swt.events.MouseEvent;
7 | import org.eclipse.swt.events.MouseListener;
8 | import org.eclipse.swt.events.SelectionEvent;
9 | import org.eclipse.swt.events.SelectionListener;
10 | import org.eclipse.swt.layout.GridData;
11 | import org.eclipse.swt.layout.GridLayout;
12 | import org.eclipse.swt.widgets.Composite;
13 | import org.eclipse.swt.widgets.Text;
14 |
15 | import com.cubaix.kaiDJ.db.SongDescr;
16 | import com.cubaix.kaiDJ.swt.KaiButton;
17 |
18 | public class PlayManager extends Composite {
19 | KaiDJ parentJDJ;
20 | KaiButton addFolderB;
21 | Text folderText;
22 | PlayList pl;
23 | public PlayManager(KaiDJ aParentJDJ,Composite parent, int style) {
24 | super(parent, style);
25 | parentJDJ = aParentJDJ;
26 |
27 | //Main panel
28 | GridLayout aGL = new GridLayout();
29 | aGL.horizontalSpacing = 0;
30 | //aGL.verticalSpacing = 4;
31 | aGL.marginHeight = 0;
32 | aGL.marginWidth = 0;
33 | aGL.numColumns = 1;
34 | this.setLayout(aGL);
35 | GridData aGD = new GridData(GridData.FILL_BOTH);
36 | this.setLayoutData(aGD);
37 | setBackground(parentJDJ.mainBckC);
38 |
39 | //Buttons
40 | Composite aButPanel = new Composite(this,SWT.NULL);
41 | aButPanel.setBackground(parentJDJ.mainBckC);
42 | aGL = new GridLayout();
43 | //aGL.horizontalSpacing = 4;
44 | aGL.verticalSpacing = 0;
45 | aGL.marginHeight = 0;
46 | aGL.marginWidth = 0;
47 | aGL.numColumns = 2;
48 | aButPanel.setLayout(aGL);
49 | aGD = new GridData(GridData.FILL_HORIZONTAL);
50 | aButPanel.setLayoutData(aGD);
51 |
52 | addFolderB = new KaiButton(parentJDJ,aButPanel, SWT.NULL);
53 | addFolderB.setBackground(parentJDJ.mainBckC);
54 | addFolderB.setToolTipText("Add named group");
55 | addFolderB.setImagePath("img2/addGroupBut.png");
56 | aGD = new GridData();// GridData.FILL_HORIZONTAL);
57 | aGD.heightHint = KaiButton._HEIGHT;
58 | aGD.widthHint = KaiButton._WIDTH;
59 | addFolderB.setLayoutData(aGD);
60 | addFolderB.addSelectionListener(new SelectionListener() {
61 | public void widgetDefaultSelected(SelectionEvent arg0) {
62 | }
63 |
64 | public void widgetSelected(SelectionEvent arg0) {
65 | pl.addGroup(folderText.getText());
66 | }
67 | });
68 | // Group name Text
69 | String os = System.getProperty("os.name");
70 | folderText = new Text(aButPanel, SWT.BORDER);
71 | folderText.setToolTipText("Edit group name");
72 | if(!os.toLowerCase().startsWith("mac")){
73 | //Mac seems to not support properly background colors here
74 | folderText.setBackground(parentJDJ.mainBckC);
75 | folderText.setForeground(parentJDJ.whiteC);
76 | }
77 | aGD = new GridData(GridData.FILL_BOTH);
78 | // aGD.heightHint = 20;
79 | folderText.setLayoutData(aGD);
80 | folderText.addKeyListener(new KeyListener() {
81 | public void keyPressed(KeyEvent arg0) {
82 | }
83 |
84 | public void keyReleased(KeyEvent arg0) {
85 | int aCharCode = arg0.character & 0xFF;
86 | if (aCharCode > 32 || arg0.keyCode == 8 || (arg0.keyCode >= 32 && arg0.keyCode < 65535)) {
87 | pl.setGroupLabel(folderText.getText());
88 | }
89 | }
90 | });
91 |
92 | //PL
93 | pl = new PlayList(aParentJDJ, this, SWT.NONE);
94 | pl.listTC.setToolTip("Edit playlist: \n"//
95 | + "- Click to load a song on the pre-listen player\n"//
96 | + "- Double-click to play and mix a song\n"//
97 | + "- Click&Drag to move a song or a group, or resize a group\n"//
98 | + "- Ctrl+Click to move a song or a group after the current selection or the current playing song\n"//
99 | + "- Suppr key to remove a song or a group");
100 | aGD = new GridData(GridData.FILL_BOTH);
101 | pl.setLayoutData(aGD);
102 |
103 | //Listeners
104 | pl.listTC.addMouseListener(new MouseListener() {
105 | public void mouseDoubleClick(MouseEvent aEvt) {
106 | if (pl.isClickInTopBar(aEvt.x, aEvt.y)) {
107 | // Nothing to do
108 | } else {
109 | final SongDescr aDescr = pl.getMp3Descr(aEvt.x, aEvt.y);
110 | //No need to use SWT thread from here. Thread should end fastly, but player load may block (?)
111 | Thread aTh = new Thread(new Runnable(){
112 | public void run() {
113 | SongDescr aNewDescr;
114 | if (aDescr == null || (aNewDescr = pl.getFirstPlayable(aDescr.getPlID())) == null) {
115 | // Nothing detected, try to get something new
116 | parentJDJ.timeToNext(null);
117 | return;
118 | }
119 | pl.select(aNewDescr);
120 | if (parentJDJ.player1.playState <= 0 && parentJDJ.player2.playState <= 0) {
121 | // First play
122 | pl.setSelectedPlaying();
123 | parentJDJ.player1.currentGain = 0.8;
124 | parentJDJ.player1.load(aNewDescr.path);
125 | parentJDJ.player1.play();
126 | parentJDJ.player2.currentGain = 0;
127 | parentJDJ.player2.fadeOut();
128 | } else if (parentJDJ.player1.playState <= 0 || parentJDJ.player1.playState == 2) {
129 | // Cross fade
130 | pl.setSelectedPlaying();
131 | parentJDJ.player1.load(aNewDescr.path);
132 | parentJDJ.player1.play();
133 | parentJDJ.player1.fadeIn();
134 | parentJDJ.player2.fadeOut();
135 | } else if (parentJDJ.player2.playState <= 0 || parentJDJ.player2.playState == 2) {
136 | // Cross fade
137 | pl.setSelectedPlaying();
138 | parentJDJ.player2.load(aNewDescr.path);
139 | parentJDJ.player2.play();
140 | parentJDJ.player2.fadeIn();
141 | parentJDJ.player1.fadeOut();
142 | }
143 | }
144 | },"TMP (MANAGER PLAYER DBL-CLICK)");
145 | aTh.start();
146 | }
147 | }
148 |
149 | public void mouseDown(MouseEvent aEvt) {
150 | if(aEvt.stateMask == SWT.CTRL){
151 | //Add after
152 | if (pl.isClickInTopBar(aEvt.x, aEvt.y)) {
153 | // Nothing to do
154 | } else {
155 | Integer aSelPlId = pl.getLastSelectedPlId();
156 | SongDescr aDescr = pl.getMp3Descr(aEvt.x, aEvt.y);
157 | if (aDescr != null) {
158 | pl.clickedPlId = aDescr.getPlID();
159 | //Move song/group to playlist
160 | SongDescr aLastDescr = pl.moveAt(pl.getIndex(aSelPlId) + 1);
161 | if(aLastDescr != null){
162 | pl.select(aLastDescr);
163 | }
164 | }
165 | }
166 | }
167 | }
168 |
169 | public void mouseUp(MouseEvent arg0) {
170 | }
171 | });
172 | }
173 |
174 | /**
175 | * @param aDescr
176 | */
177 | public void addSong(SongDescr aDescr){
178 | pl.addSong(aDescr);
179 | }
180 |
181 | /**
182 | * @param aDescr
183 | */
184 | public void addSongAfter(SongDescr aDescr){
185 | pl.addSongAfter(aDescr);
186 | }
187 |
188 |
189 | /**
190 | * @param aPath
191 | * @param aClear
192 | */
193 | public void load(String aPath, boolean aClear) {
194 | pl.load(aPath, aClear, 1);
195 | }
196 |
197 | }
198 |
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/SearchManager.java:
--------------------------------------------------------------------------------
1 | package com.cubaix.kaiDJ;
2 |
3 | import java.util.TreeSet;
4 | import java.util.Vector;
5 |
6 | import org.eclipse.swt.SWT;
7 | import org.eclipse.swt.events.KeyEvent;
8 | import org.eclipse.swt.events.KeyListener;
9 | import org.eclipse.swt.events.ModifyEvent;
10 | import org.eclipse.swt.events.ModifyListener;
11 | import org.eclipse.swt.events.MouseEvent;
12 | import org.eclipse.swt.events.MouseListener;
13 | import org.eclipse.swt.events.SelectionEvent;
14 | import org.eclipse.swt.events.SelectionListener;
15 | import org.eclipse.swt.layout.GridData;
16 | import org.eclipse.swt.layout.GridLayout;
17 | import org.eclipse.swt.widgets.Composite;
18 | import org.eclipse.swt.widgets.Text;
19 |
20 | import com.cubaix.kaiDJ.db.SongDescr;
21 | import com.cubaix.kaiDJ.swt.KaiButton;
22 |
23 | public class SearchManager extends Composite {
24 | KaiDJ parentKDJ;
25 | KaiButton shuffleAllB;
26 | boolean randomAllFlag = false;
27 | Text searchText;
28 | boolean mustSearch = false;
29 | String mustSearchText = null;
30 | public PlayList pl;
31 |
32 | public SearchManager(KaiDJ aParentKDJ,Composite parent, int style) {
33 | super(parent, style);
34 | parentKDJ = aParentKDJ;
35 |
36 | //Main panel
37 | GridLayout aGL = new GridLayout();
38 | aGL.horizontalSpacing = 0;
39 | //aGL.verticalSpacing = 4;
40 | aGL.marginHeight = 0;
41 | aGL.marginWidth = 0;
42 | aGL.numColumns = 1;
43 | this.setLayout(aGL);
44 | GridData aGD = new GridData(GridData.FILL_BOTH);
45 | this.setLayoutData(aGD);
46 | setBackground(parentKDJ.mainBckC);
47 |
48 | //Buttons
49 | Composite aButPanel = new Composite(this,SWT.NULL);
50 | aButPanel.setBackground(parentKDJ.mainBckC);
51 | aGL = new GridLayout();
52 | //aGL.horizontalSpacing = 4;
53 | aGL.verticalSpacing = 0;
54 | aGL.marginHeight = 0;
55 | aGL.marginWidth = 0;
56 | aGL.numColumns = 2;
57 | aButPanel.setLayout(aGL);
58 | aGD = new GridData(GridData.FILL_HORIZONTAL);
59 | aButPanel.setLayoutData(aGD);
60 |
61 | shuffleAllB = new KaiButton(parentKDJ,aButPanel, SWT.TOGGLE);
62 | shuffleAllB.setBackground(parentKDJ.mainBckC);
63 | shuffleAllB.setToolTipText("Shuffle selection");
64 | shuffleAllB.setImagePath("img2/shuffleBut.png");
65 | shuffleAllB.setText("Shuffle");
66 | aGD = new GridData();// GridData.FILL_HORIZONTAL);
67 | aGD.heightHint = KaiButton._HEIGHT;
68 | aGD.widthHint = KaiButton._WIDTH;
69 | shuffleAllB.setLayoutData(aGD);
70 | shuffleAllB.addSelectionListener(new SelectionListener() {
71 | public void widgetDefaultSelected(SelectionEvent arg0) {
72 | }
73 |
74 | public void widgetSelected(SelectionEvent arg0) {
75 | randomAllFlag = shuffleAllB.getSelection();
76 | }
77 | });
78 | // Search Text
79 | searchText = new Text(aButPanel, SWT.BORDER);
80 | searchText.setToolTipText("Enter keywords");
81 | String os = System.getProperty("os.name");
82 | if(!os.toLowerCase().startsWith("mac")){
83 | //Mac seems to not support properly background colors here
84 | searchText.setBackground(parentKDJ.mainBckC);
85 | searchText.setForeground(parentKDJ.whiteC);
86 | }
87 | aGD = new GridData(GridData.FILL_BOTH);
88 | searchText.setLayoutData(aGD);
89 | searchText.addModifyListener(new ModifyListener() {
90 | @Override
91 | public void modifyText(ModifyEvent arg0) {
92 | mustSearch = true;
93 | parentKDJ.db.breakSearch = true;
94 | doSearch();
95 | }
96 | });
97 | // searchText.addKeyListener(new KeyListener() {
98 | // public void keyPressed(KeyEvent arg0) {
99 | // }
100 | //
101 | // public void keyReleased(KeyEvent arg0) {
102 | // int aCharCode = arg0.character & 0xFF;
103 | // if (aCharCode > 32 || arg0.keyCode == 8 || (arg0.keyCode >= 32 && arg0.keyCode < 65535)) {
104 | // mustSearch = true;
105 | // parentKDJ.db.breakSearch = true;
106 | // doSearch();
107 | // }
108 | // }
109 | // });
110 |
111 | //PL
112 | pl = new PlayList(parentKDJ, this, SWT.NONE);
113 | pl.listTC.setToolTip("Browse songs: \n"//
114 | + "- Click to load a song on the pre-listen player\n"//
115 | + "- Double-click to add a song at the end of the playlist or the current category\n"//
116 | + "- Ctrl+Click to add a song after the current selection or the current playing song\n"//
117 | + "- Shift+Click to add a range of songs after the current selection or the current playing song");
118 | aGD = new GridData(GridData.FILL_BOTH);
119 | pl.setLayoutData(aGD);
120 |
121 | //Listeners
122 | pl.listTC.addMouseListener(new MouseListener() {
123 | public void mouseDoubleClick(MouseEvent aEvt) {
124 | if (pl.isClickInTopBar(aEvt.x, aEvt.y)) {
125 | // Nothing to do
126 | } else {
127 | SongDescr aDescr = pl.getMp3Descr(aEvt.x, aEvt.y);
128 | if (aDescr != null) {
129 | if(parentKDJ.managerCategories != null){
130 | //Add song to category
131 | parentKDJ.managerCategories.addSong(aDescr);
132 | }
133 | else{
134 | //Add song to playlist
135 | parentKDJ.managerPlay.addSong(aDescr);
136 | }
137 | }
138 | }
139 | }
140 |
141 | public void mouseDown(MouseEvent aEvt) {
142 | if (pl.isClickInTopBar(aEvt.x, aEvt.y)) {
143 | // Nothing to do
144 | } else {
145 | if(aEvt.stateMask == SWT.CTRL){
146 | //Add after
147 | SongDescr aDescr = pl.getMp3Descr(aEvt.x, aEvt.y);
148 | if (aDescr != null) {
149 | pl.selectedPlIds = new TreeSet();
150 | pl.selectedPlIds.add(aDescr.getPlID());
151 | parentKDJ.managerPlay.addSongAfter(aDescr);
152 | pl.listTC.needRedraw();
153 | }
154 | }
155 | else if(aEvt.stateMask == SWT.SHIFT){
156 | //Add after
157 | Integer aBefPlId = pl.getLastSelectedPlId();
158 | SongDescr aDescr = pl.getMp3Descr(aEvt.x, aEvt.y);
159 | if (aDescr != null) {
160 | int aBefIndex = pl.getIndex(aBefPlId);
161 | int aIndex = pl.getIndex(aDescr.getPlID());
162 | if(aBefIndex >= 0 && aIndex >= 0 && aBefIndex <= aIndex){
163 | pl.selectedPlIds = new TreeSet();
164 | for(int i = aBefIndex;i <= aIndex;i++){
165 | aDescr = (SongDescr)pl.pl.elementAt(i);
166 | pl.selectedPlIds.add(aDescr.getPlID());
167 | //Add song to playlist
168 | parentKDJ.managerPlay.addSongAfter(aDescr);
169 | }
170 | pl.listTC.needRedraw();
171 | }
172 | }
173 | }
174 | }
175 | }
176 |
177 | public void mouseUp(MouseEvent arg0) {
178 | }
179 | });
180 | }
181 |
182 | /**
183 | *
184 | */
185 | public void doSearch(){
186 | // Start main refresh thread
187 | Thread aThread = new Thread(new Runnable(){
188 | public void run() {
189 | try {
190 | /*while (true)*/ {
191 | if (mustSearch) {
192 | parentKDJ.shell.getDisplay().syncExec(new Runnable() {
193 | public void run() {
194 | mustSearchText = searchText.getText();
195 | }
196 | });
197 | mustSearch = false;
198 | Vector aRes = new Vector();
199 | pl.setPl(aRes);
200 | parentKDJ.db.search(aRes, mustSearchText);
201 | pl.listTC.needRedraw();
202 | }
203 | //Thread.sleep(100);
204 | }
205 | } catch (Throwable t) {
206 | System.err.println("Main loop error : " + t);
207 | t.printStackTrace(System.err);
208 | }
209 | }
210 |
211 | }, "Search request");
212 | aThread.setPriority(Thread.MIN_PRIORITY);
213 | aThread.start();
214 | }
215 | }
216 |
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/db/Id3Analyzer.java:
--------------------------------------------------------------------------------
1 | package com.cubaix.kaiDJ.db;
2 |
3 | import java.io.File;
4 | import java.util.HashMap;
5 | import java.util.Iterator;
6 | import java.util.Map;
7 | import java.util.Vector;
8 |
9 | import javax.sound.sampled.AudioFileFormat;
10 | import javax.sound.sampled.AudioFormat;
11 | import javax.sound.sampled.AudioSystem;
12 |
13 | import javazoom.jlgui.basicplayer.BasicController;
14 | import javazoom.jlgui.basicplayer.BasicPlayer;
15 | import javazoom.jlgui.basicplayer.BasicPlayerEvent;
16 | import javazoom.jlgui.basicplayer.BasicPlayerListener;
17 |
18 | import org.tritonus.share.sampled.TAudioFormat;
19 | import org.tritonus.share.sampled.file.TAudioFileFormat;
20 |
21 | import com.cubaix.kaiDJ.KaiDJ;
22 |
23 | public class Id3Analyzer implements BasicPlayerListener {
24 | KaiDJ parentJDJ;
25 | BasicPlayer player;
26 | SongDescr currentDescr = null;
27 | Db db;
28 | public boolean stopScan = false;
29 |
30 | public Id3Analyzer(KaiDJ aParentJDJ,final Db aDao) {
31 | super();
32 | parentJDJ = aParentJDJ;
33 | db = aDao;
34 | scan();
35 | }
36 |
37 | public synchronized void scan(){
38 | Thread aTh = new Thread(new Runnable(){
39 | public void run() {
40 | try{
41 | scan(db);
42 | }
43 | catch(Throwable t){
44 | t.printStackTrace(System.err);
45 | }
46 | }
47 | },"ID3 Analyzer");
48 | aTh.setPriority(Thread.MIN_PRIORITY);
49 | aTh.start();
50 | }
51 | /**
52 | * @param aDao
53 | */
54 | synchronized void scan(Db aDao) {
55 | Vector aV = null;
56 | aV = aDao.getToAnalyze();
57 | stopScan = false;
58 | //EM 02/11/2008 : faster with an array
59 | Object[] aVs = aV.toArray();
60 | for (int m = 0; !stopScan && m < aVs.length; m++) {
61 | SongDescr aDescr = (SongDescr) aVs[m];//aV.elementAt(m);
62 | analyze(aDao, aDescr);
63 | //Display and commit only evry N
64 | if((m % 50) == 0){
65 | parentJDJ.setMsg("Analyzing ID3 .. " + m + " / " + aV.size() + " .. " + aDescr.path);
66 | aDao.commit();
67 | }
68 | // Let a bit CPU for other threads
69 | // try {
70 | // Thread.sleep(100);
71 | // } catch (Throwable t) {
72 | // }
73 | }
74 | if (aV.size() > 0) {
75 | aDao.commit();
76 | }
77 | parentJDJ.setMsg("");
78 | }
79 |
80 | public void analyze(Db aDao,SongDescr aDescr){
81 | if (player == null) {
82 | // Instantiate BasicPlayer.
83 | //EM 29/04/2009 : parentJDJ
84 | player = new BasicPlayer(parentJDJ,false);
85 | player.addBasicPlayerListener(this);
86 | }
87 | try{
88 | currentDescr = aDescr;
89 | try{
90 | //player.open(new File(aDescr.path));
91 | File file = new File(aDescr.path);
92 | AudioFileFormat m_audioFileFormat;
93 | m_audioFileFormat = AudioSystem.getAudioFileFormat(file);
94 | Map properties = null;
95 | if (m_audioFileFormat instanceof TAudioFileFormat)
96 | {
97 | // Tritonus SPI compliant audio file format.
98 | properties = ((TAudioFileFormat) m_audioFileFormat).properties();
99 | // Clone the Map because it is not mutable.
100 | HashMap map = new HashMap();
101 | if (properties != null)
102 | {
103 | Iterator it = properties.keySet().iterator();
104 | while (it.hasNext())
105 | {
106 | Object key = it.next();
107 | Object value = properties.get(key);
108 | map.put(key, value);
109 | }
110 | }
111 | properties = map;
112 | }
113 | else properties = new HashMap();
114 | // Add JavaSound properties.
115 | if (m_audioFileFormat.getByteLength() > 0) properties.put("audio.length.bytes", new Integer(m_audioFileFormat.getByteLength()));
116 | if (m_audioFileFormat.getFrameLength() > 0) properties.put("audio.length.frames", new Integer(m_audioFileFormat.getFrameLength()));
117 | if (m_audioFileFormat.getType() != null) properties.put("audio.type", (m_audioFileFormat.getType().toString()));
118 | // Audio format.
119 | AudioFormat audioFormat = m_audioFileFormat.getFormat();
120 | if (audioFormat.getFrameRate() > 0) properties.put("audio.framerate.fps", new Float(audioFormat.getFrameRate()));
121 | if (audioFormat.getFrameSize() > 0) properties.put("audio.framesize.bytes", new Integer(audioFormat.getFrameSize()));
122 | if (audioFormat.getSampleRate() > 0) properties.put("audio.samplerate.hz", new Float(audioFormat.getSampleRate()));
123 | if (audioFormat.getSampleSizeInBits() > 0) properties.put("audio.samplesize.bits", new Integer(audioFormat.getSampleSizeInBits()));
124 | if (audioFormat.getChannels() > 0) properties.put("audio.channels", new Integer(audioFormat.getChannels()));
125 | if (audioFormat instanceof TAudioFormat)
126 | {
127 | // Tritonus SPI compliant audio format.
128 | Map addproperties = ((TAudioFormat) audioFormat).properties();
129 | properties.putAll(addproperties);
130 | }
131 | // Add SourceDataLine
132 | //properties.put("basicplayer.sourcedataline", m_line);
133 |
134 | opened(null,properties);
135 | }
136 | catch(Throwable t){
137 | //Invalide ??
138 | currentDescr.author = "[INVALIDE]";
139 | currentDescr.title = "[INVALIDE]";
140 | currentDescr.album = "[INVALIDE]";
141 | currentDescr.duration = -1;
142 | }
143 | aDao.update(currentDescr);
144 | currentDescr = null;
145 | }
146 | catch(Throwable t){
147 | t.printStackTrace(System.err);
148 | }
149 | }
150 |
151 | public void opened(Object stream, Map properties) {
152 | //Get all props
153 | //Iterator aIt = properties.entrySet().iterator();
154 | /*
155 | while(aIt.hasNext()){
156 | Object aKey = aIt.next();
157 | System.out.println("Prop : " + aKey);
158 | }
159 | */
160 | // System.out.println("MP3 ID=" + currentDescr.id);
161 | // System.out.println("GET : author = " + properties.get("author"));
162 | // System.out.println("GET : title = " + properties.get("title"));
163 | // System.out.println("GET : album = " + properties.get("album"));
164 | // System.out.println("GET : duration = " + properties.get("duration"));
165 | currentDescr.set((String)properties.get("author"),(String)properties.get("title"),(String)properties.get("album"),((Long)properties.get("duration")).longValue());
166 | }
167 |
168 | public void progress(int bytesread, long microseconds, byte[] pcmdata,
169 | Map properties) {
170 | // TODO Auto-generated method stub
171 |
172 | }
173 |
174 | public void stateUpdated(BasicPlayerEvent event) {
175 | // TODO Auto-generated method stub
176 |
177 | }
178 |
179 | public void setController(BasicController controller) {
180 | // TODO Auto-generated method stub
181 |
182 | }
183 |
184 | }
185 |
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/db/SongDescr.java:
--------------------------------------------------------------------------------
1 | package com.cubaix.kaiDJ.db;
2 |
3 | import java.io.File;
4 | import java.text.NumberFormat;
5 |
6 | import com.cubaix.kai.KaiSrt;
7 |
8 | public class SongDescr {
9 | static NumberFormat ddNF;
10 | static {
11 | ddNF = NumberFormat.getInstance();
12 | ddNF.setMaximumIntegerDigits(2);
13 | ddNF.setMinimumIntegerDigits(2);
14 | }
15 |
16 | public Integer id = null;
17 | public String path = null;
18 | public String author = "[UNKNOWN]";
19 | public String title = "[UNKNOWN]";
20 | public String album = "[UNKNOWN]";
21 |
22 | public long duration = -1;
23 | String durationDisplay = "";
24 | public int hash = -1;
25 | int enablePlay = 0;//0 : undefined (not in play list), 1 : play, -1 : don't play
26 |
27 | Integer plID = new Integer((int)(Math.random() * Integer.MAX_VALUE));
28 |
29 | public KaiSrt kaiSrt = null;
30 |
31 | /**
32 | * @param aId
33 | * @param aPath
34 | */
35 | public SongDescr(Integer aId, String aPath) {
36 | id = aId;
37 | path = aPath;
38 | hash = path.toLowerCase().hashCode();
39 | if(new File(path+".kai").exists()) {
40 | kaiSrt = new KaiSrt(path);
41 | }
42 | }
43 |
44 | /**
45 | * @param aId
46 | * @param aPath
47 | * @param aAuthor
48 | * @param aTitle
49 | * @param aAlbum
50 | * @param aDuration
51 | */
52 | public SongDescr(Integer aId, String aPath, String aAuthor, String aTitle,
53 | String aAlbum, long aDuration) {
54 | id = aId;
55 | path = aPath;
56 | hash = path.toLowerCase().hashCode();
57 | set(aAuthor, aTitle, aAlbum, aDuration);
58 | if(new File(path+".kai").exists()) {
59 | kaiSrt = new KaiSrt(path);
60 | }
61 | }
62 |
63 | /**
64 | * @param aId
65 | * @param aPath
66 | * @param aAuthor
67 | * @param aTitle
68 | * @param aAlbum
69 | * @param aDuration
70 | * @param aHash
71 | */
72 | public SongDescr(Integer aId, String aPath, String aAuthor, String aTitle,
73 | String aAlbum, long aDuration, int aHash) {
74 | this(aId, aPath, aAuthor, aTitle, aAlbum, aDuration);
75 | if (aHash != 0) {
76 | hash = aHash;
77 | }
78 | }
79 |
80 | //Use this to build a copy with a new plID
81 | public SongDescr(SongDescr aDescr){
82 | this(aDescr.id,aDescr.path,aDescr.author,aDescr.title,aDescr.album,aDescr.duration,aDescr.hash);
83 | }
84 |
85 | /**
86 | * @param aAuthor
87 | * @param aTitle
88 | * @param aAlbum
89 | * @param aDuration
90 | */
91 | public void set(String aAuthor, String aTitle, String aAlbum, long aDuration) {
92 | author = aAuthor;
93 | title = aTitle;
94 | album = aAlbum;
95 | duration = aDuration;
96 |
97 | durationDisplay = durationToDisplay(duration);
98 | }
99 |
100 | /**
101 | * @param aTime
102 | * @return
103 | */
104 | static public String durationToDisplay(long aTime){
105 | long aSecAll = aTime / 1000000;
106 | long aDays = aSecAll / (3600 * 24);
107 | long aHours = (aSecAll / 3600)%24;
108 | long aMin = (aSecAll / 60)%60;
109 | long aSec = aSecAll % 60;
110 | //long aMs = (aTime % 1000) / 10;
111 | if(aDays > 0){
112 | return aDays + ":" + aHours + ":" + ddNF.format(aMin) + ":" + ddNF.format(aSec);
113 | }
114 | if(aHours > 0){
115 | return aHours + ":" + ddNF.format(aMin) + ":" + ddNF.format(aSec);
116 | }
117 | return ddNF.format(aMin) + ":" + ddNF.format(aSec);
118 | }
119 |
120 | public String getAlbum() {
121 | if (album == null) {
122 | return "[ERROR]";
123 | }
124 | return album;
125 | }
126 |
127 | public void setAlbum(String album) {
128 | this.album = album;
129 | }
130 |
131 | public String getAuthor() {
132 | if (author == null) {
133 | return "[ERROR]";
134 | }
135 | return author;
136 | }
137 |
138 | public void setAuthor(String author) {
139 | this.author = author;
140 | }
141 |
142 | public long getDuration() {
143 | return duration;
144 | }
145 |
146 | public void setDuration(long duration) {
147 | this.duration = duration;
148 | }
149 |
150 | public String getDurationDisplay() {
151 | if (durationDisplay == null) {
152 | return "[ERROR]";
153 | }
154 | return durationDisplay;
155 | }
156 |
157 | public void setDurationDisplay(String durationDisplay) {
158 | this.durationDisplay = durationDisplay;
159 | }
160 |
161 | public Integer getId() {
162 | if (id == null) {
163 | return new Integer(-1);
164 | }
165 | return id;
166 | }
167 |
168 | public void setId(Integer id) {
169 | this.id = id;
170 | }
171 |
172 | public String getPath() {
173 | if (path == null) {
174 | return "[ERROR]";
175 | }
176 | return path;
177 | }
178 |
179 | public void setPath(String path) {
180 | this.path = path;
181 | }
182 |
183 | //EM 28/04/2009
184 | public boolean isAccesible(){
185 | return new File(this.path).exists();
186 | }
187 |
188 | public String getTitle() {
189 | if (title == null) {
190 | return "[ERROR]";
191 | }
192 | return title;
193 | }
194 |
195 | public void setTitle(String title) {
196 | this.title = title;
197 | }
198 |
199 | public int getHash() {
200 | return hash;
201 | }
202 |
203 | public void setHash(int hash) {
204 | this.hash = hash;
205 | }
206 |
207 | public int getEnablePlay() {
208 | return enablePlay;
209 | }
210 |
211 | public void setEnablePlay(int enablePlay) {
212 | this.enablePlay = enablePlay;
213 | }
214 |
215 | public Integer getPlID() {
216 | return plID;
217 | }
218 |
219 | public void setPlID(Integer plID) {
220 | this.plID = plID;
221 | }
222 | // protected void finalize() throws Throwable {
223 | // System.out.println("SONGDESCR Finalizing..");
224 | // }
225 | }
226 |
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/db/SongGroup.java:
--------------------------------------------------------------------------------
1 | package com.cubaix.kaiDJ.db;
2 |
3 |
4 | public class SongGroup extends SongDescr {
5 | public static final int _KIND_OPEN = 0;
6 | public static final int _KIND_CLOSE = 1;
7 |
8 | public int kind = _KIND_OPEN;
9 |
10 | public SongGroup(int aKing,String aLabel) {
11 | super(new Integer(-1), aLabel);
12 | kind = aKing;
13 | }
14 |
15 | // @Override
16 | // protected void finalize() throws Throwable {
17 | // System.out.println("SONGGROUP Finalizing..");
18 | // }
19 | }
20 |
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/img/Icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EtienneAb3d/karaok-AI/2eaaf4fba6234ad6206e112c59a0d6143540aace/src/com/cubaix/kaiDJ/img/Icon.ico
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/img/Icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EtienneAb3d/karaok-AI/2eaaf4fba6234ad6206e112c59a0d6143540aace/src/com/cubaix/kaiDJ/img/Icon.png
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/img/LogoSmall.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EtienneAb3d/karaok-AI/2eaaf4fba6234ad6206e112c59a0d6143540aace/src/com/cubaix/kaiDJ/img/LogoSmall.png
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/img/kaiDJ.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
89 |
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/img/playerBck.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EtienneAb3d/karaok-AI/2eaaf4fba6234ad6206e112c59a0d6143540aace/src/com/cubaix/kaiDJ/img/playerBck.png
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/img/playerBck.xcf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EtienneAb3d/karaok-AI/2eaaf4fba6234ad6206e112c59a0d6143540aace/src/com/cubaix/kaiDJ/img/playerBck.xcf
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/img2/addDbBut.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EtienneAb3d/karaok-AI/2eaaf4fba6234ad6206e112c59a0d6143540aace/src/com/cubaix/kaiDJ/img2/addDbBut.png
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/img2/addDbBut.xcf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EtienneAb3d/karaok-AI/2eaaf4fba6234ad6206e112c59a0d6143540aace/src/com/cubaix/kaiDJ/img2/addDbBut.xcf
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/img2/addGroupBut.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EtienneAb3d/karaok-AI/2eaaf4fba6234ad6206e112c59a0d6143540aace/src/com/cubaix/kaiDJ/img2/addGroupBut.png
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/img2/addGroupBut.xcf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EtienneAb3d/karaok-AI/2eaaf4fba6234ad6206e112c59a0d6143540aace/src/com/cubaix/kaiDJ/img2/addGroupBut.xcf
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/img2/bookmarks.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/img2/butBck.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EtienneAb3d/karaok-AI/2eaaf4fba6234ad6206e112c59a0d6143540aace/src/com/cubaix/kaiDJ/img2/butBck.png
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/img2/butBck.xcf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EtienneAb3d/karaok-AI/2eaaf4fba6234ad6206e112c59a0d6143540aace/src/com/cubaix/kaiDJ/img2/butBck.xcf
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/img2/butBckDark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EtienneAb3d/karaok-AI/2eaaf4fba6234ad6206e112c59a0d6143540aace/src/com/cubaix/kaiDJ/img2/butBckDark.png
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/img2/butBckDark.xcf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EtienneAb3d/karaok-AI/2eaaf4fba6234ad6206e112c59a0d6143540aace/src/com/cubaix/kaiDJ/img2/butBckDark.xcf
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/img2/butBckMid.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EtienneAb3d/karaok-AI/2eaaf4fba6234ad6206e112c59a0d6143540aace/src/com/cubaix/kaiDJ/img2/butBckMid.png
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/img2/butBckMid.xcf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EtienneAb3d/karaok-AI/2eaaf4fba6234ad6206e112c59a0d6143540aace/src/com/cubaix/kaiDJ/img2/butBckMid.xcf
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/img2/catBut.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EtienneAb3d/karaok-AI/2eaaf4fba6234ad6206e112c59a0d6143540aace/src/com/cubaix/kaiDJ/img2/catBut.png
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/img2/catBut.xcf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EtienneAb3d/karaok-AI/2eaaf4fba6234ad6206e112c59a0d6143540aace/src/com/cubaix/kaiDJ/img2/catBut.xcf
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/img2/chat-square-text-fill.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/img2/chat-square-text.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/img2/database-add.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/img2/eraseDbBut.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EtienneAb3d/karaok-AI/2eaaf4fba6234ad6206e112c59a0d6143540aace/src/com/cubaix/kaiDJ/img2/eraseDbBut.png
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/img2/folder2-open.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/img2/globe.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/img2/kaiBut.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EtienneAb3d/karaok-AI/2eaaf4fba6234ad6206e112c59a0d6143540aace/src/com/cubaix/kaiDJ/img2/kaiBut.png
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/img2/kaiIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EtienneAb3d/karaok-AI/2eaaf4fba6234ad6206e112c59a0d6143540aace/src/com/cubaix/kaiDJ/img2/kaiIcon.png
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/img2/kaiIcon.svg:
--------------------------------------------------------------------------------
1 |
2 |
44 |
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/img2/mixBut.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EtienneAb3d/karaok-AI/2eaaf4fba6234ad6206e112c59a0d6143540aace/src/com/cubaix/kaiDJ/img2/mixBut.png
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/img2/mixBut.xcf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EtienneAb3d/karaok-AI/2eaaf4fba6234ad6206e112c59a0d6143540aace/src/com/cubaix/kaiDJ/img2/mixBut.xcf
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/img2/newPLBut.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EtienneAb3d/karaok-AI/2eaaf4fba6234ad6206e112c59a0d6143540aace/src/com/cubaix/kaiDJ/img2/newPLBut.png
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/img2/newPLBut.xcf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EtienneAb3d/karaok-AI/2eaaf4fba6234ad6206e112c59a0d6143540aace/src/com/cubaix/kaiDJ/img2/newPLBut.xcf
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/img2/openCatBut.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EtienneAb3d/karaok-AI/2eaaf4fba6234ad6206e112c59a0d6143540aace/src/com/cubaix/kaiDJ/img2/openCatBut.png
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/img2/openPLBut.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EtienneAb3d/karaok-AI/2eaaf4fba6234ad6206e112c59a0d6143540aace/src/com/cubaix/kaiDJ/img2/openPLBut.png
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/img2/save2.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/img2/saveCatBut.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EtienneAb3d/karaok-AI/2eaaf4fba6234ad6206e112c59a0d6143540aace/src/com/cubaix/kaiDJ/img2/saveCatBut.png
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/img2/savePLBut.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EtienneAb3d/karaok-AI/2eaaf4fba6234ad6206e112c59a0d6143540aace/src/com/cubaix/kaiDJ/img2/savePLBut.png
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/img2/search.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/img2/searchKaiBut.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EtienneAb3d/karaok-AI/2eaaf4fba6234ad6206e112c59a0d6143540aace/src/com/cubaix/kaiDJ/img2/searchKaiBut.png
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/img2/showProfBut.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EtienneAb3d/karaok-AI/2eaaf4fba6234ad6206e112c59a0d6143540aace/src/com/cubaix/kaiDJ/img2/showProfBut.png
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/img2/showProfBut.xcf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EtienneAb3d/karaok-AI/2eaaf4fba6234ad6206e112c59a0d6143540aace/src/com/cubaix/kaiDJ/img2/showProfBut.xcf
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/img2/shuffleBut.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EtienneAb3d/karaok-AI/2eaaf4fba6234ad6206e112c59a0d6143540aace/src/com/cubaix/kaiDJ/img2/shuffleBut.png
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/img2/shuffleBut.xcf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EtienneAb3d/karaok-AI/2eaaf4fba6234ad6206e112c59a0d6143540aace/src/com/cubaix/kaiDJ/img2/shuffleBut.xcf
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/img2/stars.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/img2/stopAftBut.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EtienneAb3d/karaok-AI/2eaaf4fba6234ad6206e112c59a0d6143540aace/src/com/cubaix/kaiDJ/img2/stopAftBut.png
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/img2/stopAftBut.xcf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EtienneAb3d/karaok-AI/2eaaf4fba6234ad6206e112c59a0d6143540aace/src/com/cubaix/kaiDJ/img2/stopAftBut.xcf
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/img2/trash3.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/img2/webSiteBut.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EtienneAb3d/karaok-AI/2eaaf4fba6234ad6206e112c59a0d6143540aace/src/com/cubaix/kaiDJ/img2/webSiteBut.png
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/img2/webSiteBut.xcf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EtienneAb3d/karaok-AI/2eaaf4fba6234ad6206e112c59a0d6143540aace/src/com/cubaix/kaiDJ/img2/webSiteBut.xcf
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/swt/KaiButton.java:
--------------------------------------------------------------------------------
1 | package com.cubaix.kaiDJ.swt;
2 |
3 | import java.io.InputStream;
4 | import java.util.Vector;
5 | import org.eclipse.swt.SWT;
6 | import org.eclipse.swt.events.MouseEvent;
7 | import org.eclipse.swt.events.MouseListener;
8 | import org.eclipse.swt.events.MouseTrackListener;
9 | import org.eclipse.swt.events.PaintEvent;
10 | import org.eclipse.swt.events.PaintListener;
11 | import org.eclipse.swt.events.SelectionListener;
12 | import org.eclipse.swt.graphics.GC;
13 | import org.eclipse.swt.graphics.Image;
14 | import org.eclipse.swt.graphics.Rectangle;
15 | import org.eclipse.swt.widgets.Canvas;
16 | import org.eclipse.swt.widgets.Composite;
17 |
18 | import com.cubaix.kaiDJ.KaiDJ;
19 |
20 | public class KaiButton extends Canvas {
21 | public static final int _WIDTH = 60;
22 | public static final int _HEIGHT = 25;
23 |
24 | KaiDJ parentJDJ;
25 |
26 | static Image butBck = null;
27 | static Image butBckMid = null;
28 | static Image butBckDark = null;
29 | String imgPath = null;
30 | Image img = null;
31 |
32 | String text;
33 |
34 | boolean isToggle = false;
35 | boolean selection = false;
36 | Vector selectionListeners = new Vector();
37 | int state = 0;//0 current selection state, 1 over
38 |
39 | String toolTip = null;
40 |
41 | Rectangle buttonBounds = null;
42 |
43 | public KaiButton(KaiDJ aParentJDJ,Composite aParent, int aStyle) {
44 | super(aParent, aStyle);
45 | parentJDJ = aParentJDJ;
46 | isToggle = (aStyle & SWT.TOGGLE) != 0;
47 | this.addPaintListener(new PaintListener(){
48 | public void paintControl(PaintEvent aPE) {
49 | buttonBounds = getClientArea();
50 | paint();
51 | }
52 | });
53 | this.addMouseTrackListener(new MouseTrackListener(){
54 | public void mouseEnter(MouseEvent arg0) {
55 | parentJDJ.logoPanel.help = toolTip;
56 | parentJDJ.logoPanel.needRedraw();
57 | state = 1;
58 | needRedraw();
59 | }
60 | public void mouseExit(MouseEvent arg0) {
61 | parentJDJ.logoPanel.help = null;
62 | parentJDJ.logoPanel.needRedraw();
63 | state = 0;
64 | if(!isToggle){
65 | //Always deselected
66 | selection = false;
67 | }
68 | needRedraw();
69 | }
70 | public void mouseHover(MouseEvent arg0) {
71 | }
72 | });
73 | this.addMouseListener(new MouseListener(){
74 | public void mouseDoubleClick(MouseEvent aEvt) {
75 | }
76 | public void mouseDown(MouseEvent aEvt) {
77 | // state = 0;
78 | if(isToggle){
79 | selection = !selection;
80 | }
81 | else{
82 | selection = true;
83 | }
84 | needRedraw();
85 | notifySelection();
86 | }
87 | public void mouseUp(MouseEvent aEvt) {
88 | // state = 0;
89 | if(!isToggle){
90 | //Always deselected
91 | selection = false;
92 | }
93 | needRedraw();
94 | // notifySelection();
95 | }
96 |
97 | });
98 | }
99 |
100 | void notifySelection(){
101 | for(int i = 0;i < selectionListeners.size();i++){
102 | ((SelectionListener)selectionListeners.elementAt(i)).widgetSelected(null);
103 | }
104 | }
105 |
106 | public void setSelection(boolean aSel){
107 | selection = aSel;
108 | }
109 | public boolean getSelection(){
110 | return selection;
111 | }
112 |
113 | public void setImagePath(String aPath){
114 | imgPath = aPath;
115 | }
116 |
117 | public void setText(String aText){
118 | text = aText;
119 | }
120 |
121 | public void setToolTipText(String aText){
122 | toolTip = aText;
123 | }
124 |
125 | public void addSelectionListener(SelectionListener aListener){
126 | selectionListeners.add(aListener);
127 | }
128 |
129 | void needRedraw() {
130 | if (parentJDJ.display == null || parentJDJ.display.isDisposed()) {
131 | // Wait until it is available
132 | return;
133 | }
134 | // Use SWT async
135 | final KaiButton aThis = this;
136 | parentJDJ.display.asyncExec(new Runnable() {
137 | public void run() {
138 | try {
139 | buttonBounds = aThis.getClientArea();
140 | paint();
141 | } catch (Throwable t) {
142 | }
143 | }
144 | });
145 | }
146 |
147 | /**
148 | *
149 | */
150 | void loadBckImg() {
151 | if (parentJDJ == null || parentJDJ.display == null || parentJDJ.display.isDisposed()) {
152 | return;
153 | }
154 | InputStream aIS = KaiDJ.class.getResourceAsStream("img2/butBck.png");
155 | butBck = new Image(parentJDJ.display, aIS);
156 | aIS = KaiDJ.class.getResourceAsStream("img2/butBckMid.png");
157 | butBckMid = new Image(parentJDJ.display, aIS);
158 | aIS = KaiDJ.class.getResourceAsStream("img2/butBckDark.png");
159 | butBckDark = new Image(parentJDJ.display, aIS);
160 | }
161 |
162 | void loadImg() {
163 | if (parentJDJ == null || parentJDJ.display == null || parentJDJ.display.isDisposed()) {
164 | return;
165 | }
166 | if(imgPath == null){
167 | return;
168 | }
169 | InputStream aIS = KaiDJ.class.getResourceAsStream(imgPath);
170 | img = new Image(parentJDJ.display, aIS);
171 | }
172 |
173 | void paint() {
174 | if (butBck == null) {
175 | loadBckImg();
176 | }
177 | if (img == null) {
178 | loadImg();
179 | }
180 | if(butBck == null || img == null || buttonBounds == null){
181 | return;
182 | }
183 | try{
184 | GC aGC = new GC(this);
185 | // aPlayerGC.setClipping(playerBounds.x, playerBounds.y,
186 | // playerBounds.width, playerBounds.height);
187 |
188 | aGC.setClipping(buttonBounds.x, buttonBounds.y, buttonBounds.width, buttonBounds.height);
189 | aGC.setForeground(parentJDJ.blackC);
190 | aGC.setBackground(parentJDJ.mainBckC);
191 | aGC.fillRectangle(buttonBounds);
192 |
193 | Image aImgBck;
194 | if(state == 1){
195 | //Over
196 | aImgBck = butBck;
197 | }
198 | else{
199 | //Current selection
200 | if(selection){
201 | aImgBck = butBckMid;
202 | }
203 | else{
204 | aImgBck = butBckDark;
205 | }
206 | }
207 |
208 | aGC.drawImage(aImgBck, buttonBounds.x, buttonBounds.y);
209 | aGC.drawImage(img, buttonBounds.x + 8, buttonBounds.y + 5);
210 | // aGC.setFont(parentJDJ.initialFont);
211 | // aGC.drawText(text,32 - (int)(3.7 * (text.length()/2)),0,true);
212 |
213 | if (isToggle) {
214 | if (selection) {
215 | aGC.setBackground(parentJDJ.playerC);
216 | } else {
217 | //EM 06/07/2008 : background color for off state
218 | aGC.setBackground(parentJDJ.mainBckC/*.redC*/);
219 | }
220 | aGC.setForeground(parentJDJ.playerBarC);
221 | aGC.fillOval(buttonBounds.x + 40, buttonBounds.y + 8, 8, 8);
222 | aGC.drawOval(buttonBounds.x + 40, buttonBounds.y + 8, 8, 8);
223 | }
224 |
225 | if(state == 1){
226 | //Over
227 | aGC.setForeground(parentJDJ.playerC);
228 | }
229 | else{
230 | aGC.setForeground(parentJDJ.playerBarC);
231 | }
232 | aGC.setLineWidth(1);
233 | aGC.drawRectangle(buttonBounds.x,buttonBounds.y + 1,_WIDTH - 1,_HEIGHT - 2);
234 |
235 | aGC.dispose();
236 | } catch (Throwable t) {
237 | System.err.println("Can't paint button : " + t);
238 | t.printStackTrace(System.err);
239 | }
240 | }
241 | }
242 |
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/swt/KaiScrollBar.java:
--------------------------------------------------------------------------------
1 | package com.cubaix.kaiDJ.swt;
2 |
3 | import java.util.Vector;
4 |
5 | import org.eclipse.swt.SWT;
6 | import org.eclipse.swt.events.MouseEvent;
7 | import org.eclipse.swt.events.MouseListener;
8 | import org.eclipse.swt.events.MouseMoveListener;
9 | import org.eclipse.swt.events.MouseWheelListener;
10 | import org.eclipse.swt.events.PaintEvent;
11 | import org.eclipse.swt.events.PaintListener;
12 | import org.eclipse.swt.events.SelectionListener;
13 | import org.eclipse.swt.graphics.Color;
14 | import org.eclipse.swt.graphics.GC;
15 | import org.eclipse.swt.graphics.Point;
16 | import org.eclipse.swt.graphics.Rectangle;
17 | import org.eclipse.swt.widgets.Canvas;
18 | import org.eclipse.swt.widgets.Composite;
19 |
20 | import com.cubaix.kaiDJ.KaiDJ;
21 |
22 | public class KaiScrollBar extends Canvas implements MouseWheelListener {
23 | KaiDJ parentKDJ = null;
24 | int style = SWT.VERTICAL;
25 | Composite parent = null;
26 |
27 | Vector selectionListener = new Vector();
28 | int selection = 0;
29 | int maximum = 100;
30 | int thumb = 10;
31 | int increment = 1;
32 | int pageIncrement = 10;
33 |
34 | Point mouseLastPos = null;
35 | Point mouseLastDrag = null;
36 |
37 | Color thumbC = null;
38 | Color incrementC = null;
39 | Color pageIncrementC = null;
40 | Color borderC = null;
41 |
42 | public KaiScrollBar(KaiDJ aParentKDJ,Composite aParent, int aStyle) {
43 | super(aParent, SWT.None);
44 | parentKDJ = aParentKDJ;
45 | style = aStyle;
46 | parent = aParent;
47 |
48 | thumbC = parentKDJ.logoDarkC;
49 | incrementC = parentKDJ.logoDarkC;
50 | pageIncrementC = parentKDJ.mainBckC;
51 | borderC = parentKDJ.logoLightC;
52 | addPaintListener(new PaintListener() {
53 | @Override
54 | public void paintControl(PaintEvent aE) {
55 | paint(aE.gc);
56 | }
57 | });
58 | final KaiScrollBar aMe = this;
59 | addMouseWheelListener(new MouseWheelListener() {
60 | @Override
61 | public void mouseScrolled(MouseEvent aE) {
62 | aMe.mouseScrolled(aE);
63 | }
64 | });
65 | addMouseListener(new MouseListener() {
66 | @Override
67 | public void mouseUp(MouseEvent aME) {
68 | mouseLastDrag = null;
69 | if(mouseLastPos == null) {
70 | return;
71 | }
72 | if(mouseLastPos.x == aME.x && mouseLastPos.y == aME.y) {
73 | Rectangle aRect = getBounds();
74 | if((style & SWT.VERTICAL) > 0) {
75 | double aScreenRange = aRect.height*(maximum-thumb)/(double)maximum;
76 | selection = (int)(maximum * (aME.y - aRect.y) / aScreenRange);
77 | if(selection < 0) {
78 | selection = 0;
79 | }
80 | if(selection > maximum) {
81 | selection = maximum;
82 | }
83 | for(SelectionListener aL : selectionListener) {
84 | aL.widgetSelected(null);
85 | }
86 | }
87 | else {
88 | double aScreenRange = aRect.width*(maximum-thumb)/(double)maximum;
89 | selection = (int)(maximum * (aME.x - aRect.x) / aScreenRange);
90 | if(selection < 0) {
91 | selection = 0;
92 | }
93 | if(selection > maximum) {
94 | selection = maximum;
95 | }
96 | for(SelectionListener aL : selectionListener) {
97 | aL.widgetSelected(null);
98 | }
99 | }
100 | redraw();
101 | }
102 | mouseLastPos = null;
103 | }
104 | @Override
105 | public void mouseDown(MouseEvent aME) {
106 | mouseLastPos = new Point(aME.x, aME.y);
107 | }
108 | @Override
109 | public void mouseDoubleClick(MouseEvent arg0) {
110 | }
111 | });
112 | addMouseMoveListener(new MouseMoveListener() {
113 | @Override
114 | public void mouseMove(MouseEvent aME) {
115 | if(mouseLastPos != null) {
116 | mouseLastDrag = mouseLastPos;
117 | mouseLastPos = null;
118 | }
119 | if(mouseLastDrag == null) {
120 | return;
121 | }
122 |
123 | Rectangle aRect = getBounds();
124 | if((style & SWT.VERTICAL) > 0) {
125 | double aScreenRange = aRect.height*(maximum-thumb)/(double)maximum;
126 | int aDelta = (int)(maximum * (aME.y - mouseLastDrag.y) / aScreenRange);
127 | if(Math.abs(aDelta) <= 2) {
128 | //Do nothing on too small move
129 | return;
130 | }
131 | selection += aDelta;
132 | if(selection < 0) {
133 | selection = 0;
134 | }
135 | if(selection > maximum) {
136 | selection = maximum;
137 | }
138 | for(SelectionListener aL : selectionListener) {
139 | aL.widgetSelected(null);
140 | }
141 | }
142 | else {
143 | double aScreenRange = aRect.width*(maximum-thumb)/(double)maximum;
144 | int aDelta = (int)(maximum * (aME.x - mouseLastDrag.x) / aScreenRange);
145 | if(Math.abs(aDelta) <= 2) {
146 | //Do nothing on too small move
147 | return;
148 | }
149 | selection += aDelta;
150 | if(selection < 0) {
151 | selection = 0;
152 | }
153 | if(selection > maximum) {
154 | selection = maximum;
155 | }
156 | for(SelectionListener aL : selectionListener) {
157 | aL.widgetSelected(null);
158 | }
159 | }
160 | redraw();
161 | mouseLastDrag.x = aME.x;
162 | mouseLastDrag.y = aME.y;
163 | }
164 | });
165 | }
166 |
167 | void paint(GC aGC) {
168 | if(KaiDJ._DEBUG_PAINT) {
169 | System.out.println("KaiScrollBar.paint()");
170 | }
171 | Rectangle aRect = getBounds();
172 | aGC.setBackground(pageIncrementC);
173 | aGC.fillRectangle(0,0,aRect.width,aRect.height);
174 | aGC.setForeground(borderC);
175 |
176 | aGC.setBackground(thumbC);
177 | int aFreeRange = maximum-thumb;
178 |
179 | if((style & SWT.VERTICAL) > 0) {
180 | aGC.fillRectangle(aRect.width/2,0,1,aRect.height);
181 | if(aFreeRange <= 0) {
182 | aGC.fillRectangle(2,0,aRect.width - 3,aRect.height);
183 | }
184 | else {
185 | int aPos = (int)(aRect.height * (selection / (double)maximum) * (aFreeRange / (double)maximum));
186 | int aThumb = (aRect.height * thumb) / maximum;
187 | if(aThumb <= 0) {
188 | aThumb = 2;
189 | }
190 | aGC.fillRectangle(2,aPos, aRect.width - 3, aThumb);
191 | }
192 | }
193 | else {
194 | aGC.fillRectangle(0,aRect.height/2,aRect.width,1);
195 | if(aFreeRange <= 0) {
196 | aGC.fillRectangle(0,2,aRect.width,aRect.height-2);
197 | }
198 | else {
199 | int aPos = (int)(aRect.width * (selection / (double)maximum) * (aFreeRange / (double)maximum));
200 | int aThumb = (aRect.width * thumb) / maximum;
201 | if(aThumb <= 0) {
202 | aThumb = 2;
203 | }
204 | aGC.fillRectangle(aPos,2,aThumb,aRect.height - 3);
205 | }
206 | }
207 | }
208 |
209 | public void setThumbColor(Color aC) {
210 | thumbC = aC;
211 | }
212 | public void setIncrementColor(Color aC) {
213 | pageIncrementC = aC;
214 | }
215 | public void setPageIncrementColor(Color aC) {
216 | pageIncrementC = aC;
217 | }
218 |
219 | public void addSelectionListener(SelectionListener aSelectionListener) {
220 | selectionListener.add(aSelectionListener);
221 | }
222 |
223 | public int getSelection() {
224 | return selection;
225 | }
226 | public void setSelection(int aS) {
227 | selection = aS;
228 | }
229 | public int getMaximum() {
230 | return maximum;
231 | }
232 | public void setMaximum(int aM) {
233 | maximum = aM;
234 | }
235 | public int getThumb() {
236 | return thumb;
237 | }
238 | public void setThumb(int aT) {
239 | thumb = aT;
240 | }
241 | public int getIncrement() {
242 | return increment;
243 | }
244 | public void setIncrement(int aI) {
245 | increment = aI;
246 | }
247 | public int getPageIncrement() {
248 | return pageIncrement;
249 | }
250 | public void setPageIncrement(int aI) {
251 | pageIncrement = aI;
252 | }
253 |
254 | @Override
255 | public void mouseScrolled(MouseEvent aME) {
256 | selection -= (thumb * aME.count)/8;
257 | if(selection < 0) {
258 | selection = 0;
259 | }
260 | if(selection > maximum) {
261 | selection = maximum;
262 | }
263 | for(SelectionListener aL : selectionListener) {
264 | aL.widgetSelected(null);
265 | }
266 | redraw();
267 | }
268 |
269 | }
270 |
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/swt/PlayListListener.java:
--------------------------------------------------------------------------------
1 | package com.cubaix.kaiDJ.swt;
2 |
3 | import com.cubaix.kaiDJ.db.SongDescr;
4 |
5 | public interface PlayListListener {
6 | public void removed(SongDescr aDescr);
7 | public void added(SongDescr aDescr);
8 | }
9 |
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/swt/TimedCanvas.java:
--------------------------------------------------------------------------------
1 | package com.cubaix.kaiDJ.swt;
2 |
3 | import org.eclipse.swt.SWT;
4 | import org.eclipse.swt.events.MouseEvent;
5 | import org.eclipse.swt.events.MouseTrackListener;
6 | import org.eclipse.swt.graphics.GC;
7 | import org.eclipse.swt.widgets.Canvas;
8 | import org.eclipse.swt.widgets.Composite;
9 |
10 | import com.cubaix.kaiDJ.KaiDJ;
11 |
12 | public class TimedCanvas extends Canvas {
13 | protected KaiDJ parentKDJ;
14 | private Thread paintThread = null;
15 | private boolean needRedraw = true;
16 | //EM 02/11/2008
17 | private boolean needRedrawSlow = true;
18 |
19 | private String toolTip = null;
20 |
21 | //EM 12/11/2008
22 | protected int refreshRate = 100;
23 |
24 | public TimedCanvas(KaiDJ aParentKDJ, Composite parent, int style) {
25 | super(parent, style);
26 | parentKDJ = aParentKDJ;
27 | this.addMouseTrackListener(new MouseTrackListener() {
28 | public void mouseEnter(MouseEvent arg0) {
29 | parentKDJ.logoPanel.help = toolTip;
30 | parentKDJ.logoPanel.needRedraw();
31 | }
32 |
33 | public void mouseExit(MouseEvent arg0) {
34 | parentKDJ.logoPanel.help = null;
35 | parentKDJ.logoPanel.needRedraw();
36 | }
37 |
38 | public void mouseHover(MouseEvent arg0) {
39 | }
40 | });
41 | }
42 |
43 | /**
44 | *
45 | */
46 | public void needRedraw() {
47 | needRedraw = true;
48 | checkRedrawThread();
49 | }
50 |
51 | //EM 02/11/2008
52 | public void needRedrawSlow() {
53 | needRedrawSlow = true;
54 | checkRedrawThread();
55 | }
56 |
57 | //EM 02/11/2008 : needRedrawSlow
58 | public void checkRedrawThread(){
59 | if (paintThread == null || !paintThread.isAlive()) {
60 | // Create a new paint thread
61 | final TimedCanvas aThis = this;
62 | paintThread = new Thread(new Runnable() {
63 | public void run() {
64 | //EM 02/11/2008 : needRedrawSlow
65 | long aCount = 0;
66 |
67 | while (true) {
68 | try {
69 | // Be time respectuous
70 | Thread.sleep(refreshRate);
71 | aCount++;
72 | // Search for a possible change in interface
73 | if (aThis.paintThread != Thread.currentThread() || aThis.isDisposed()) {
74 | // Something has changed ??
75 | break;
76 | }
77 | // Is there a request to draw ?
78 | if (needRedraw //
79 | //EM 02/11/2008 : needRedrawSlow
80 | || (needRedrawSlow && (aCount%10) == 0)) {
81 | // Immediatly take request into account
82 | needRedraw = false;
83 | needRedrawSlow = false;
84 | aCount = 0;
85 |
86 | if (parentKDJ.display == null || parentKDJ.display.isDisposed()) {
87 | // Wait until it is available
88 | continue;
89 | }
90 | // Use SWT async
91 | parentKDJ.display.asyncExec(new Runnable() {
92 | public void run() {
93 | try {
94 | paintTimed();
95 | }
96 | catch (Throwable t) {
97 | t.printStackTrace(System.err);
98 | }
99 | }
100 | });
101 | }
102 | } catch (Throwable t) {
103 | System.err.println("Display thread error (shutdown ?) : " + t);
104 | }
105 | }
106 | }
107 | }, "Display daemon {" + this.getClass().getName() + "}");
108 | paintThread.setPriority(Thread.MIN_PRIORITY);
109 | paintThread.start();
110 | }
111 | }
112 |
113 | @Override
114 | public void drawBackground(GC gc, int x, int y, int width, int height, int offsetX, int offsetY) {
115 | }
116 |
117 | /**
118 | *
119 | */
120 | protected void paintTimed() {
121 | }
122 |
123 | public String getToolTip() {
124 | return toolTip;
125 | }
126 |
127 | public void setToolTip(String toolTip) {
128 | this.toolTip = toolTip;
129 | }
130 | }
131 |
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/utils/FileUtils.java:
--------------------------------------------------------------------------------
1 | package com.cubaix.kaiDJ.utils;
2 |
3 | import java.io.File;
4 | import java.io.FileInputStream;
5 | import java.io.FileOutputStream;
6 | import java.io.OutputStream;
7 | import java.nio.charset.Charset;
8 | import java.util.Vector;
9 | import java.util.zip.ZipEntry;
10 | import java.util.zip.ZipInputStream;
11 |
12 | public class FileUtils {
13 |
14 | final static public Vector unzipDir(String aZipPath,String aDestPath) throws Exception {
15 | return unzipDir(aZipPath,aDestPath,true);
16 | }
17 | final static public Vector unzipDir(String aZipPath,String aDestPath,boolean aOverWrite) throws Exception {
18 | String aCharEncoding = "utf-8";
19 | ZipInputStream in = null;
20 | try{
21 | in = new ZipInputStream(new FileInputStream(aZipPath),Charset.forName(aCharEncoding));
22 | while (true) {
23 | //Will throw an Exception if not UTF-8
24 | ZipEntry entry = in.getNextEntry();
25 | if (entry == null) {
26 | // End of zip
27 | break;
28 | }
29 | }
30 | }
31 | catch(Throwable t){
32 | aCharEncoding = "Cp437";
33 | }
34 | finally{
35 | in.close();
36 | }
37 |
38 | System.out.println("Using char encoding '"+aCharEncoding+"' for file names in zip file : "+ aZipPath);
39 |
40 | Vector aPathList = new Vector();
41 | // Open the ZIP file
42 | in = new ZipInputStream(new FileInputStream(aZipPath),Charset.forName(aCharEncoding));
43 | String aMainPath = aDestPath;
44 |
45 | if(!new File(aDestPath).exists()){
46 | new File(aDestPath).mkdir();
47 | }
48 |
49 | // Get the first entry
50 | while (true) {
51 | ZipEntry entry = in.getNextEntry();
52 | if (entry == null) {
53 | // End of zip
54 | break;
55 | }
56 | String outFilename = aMainPath + File.separator + entry.getName();
57 | System.out.println("Unzipping : "+ outFilename);
58 | if (entry.isDirectory()) {
59 | new File(outFilename).mkdir();
60 | continue;
61 | }
62 | if(!new File(outFilename).getParentFile().exists()){
63 | new File(outFilename).getParentFile().mkdir();
64 | }
65 |
66 | aPathList.add(outFilename);
67 |
68 | //EM 15/01/2008 : need an overwrite option
69 | OutputStream out = (aOverWrite || !new File(outFilename).exists())? new FileOutputStream(outFilename) : null;
70 |
71 | // Transfer bytes from the ZIP file to the
72 | // output file
73 | byte[] buf = new byte[1024];
74 | int len;
75 | while ((len = in.read(buf)) > 0) {
76 | //EM 15/01/2008 : need a overwrite option
77 | if(out != null){
78 | out.write(buf, 0, len);
79 | }
80 | }
81 |
82 | // Close the streams
83 | //EM 15/01/2008 : need a overwrite option
84 | if(out != null){
85 | out.flush();
86 | out.close();
87 | }
88 | }
89 | in.close();
90 | return aPathList;
91 | }
92 |
93 | public static void main(String[] args) {
94 | try{
95 |
96 | }
97 | catch(Throwable t){
98 | t.printStackTrace();
99 | }
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/web/BrowserControl.java:
--------------------------------------------------------------------------------
1 | package com.cubaix.kaiDJ.web;
2 |
3 |
4 | public class BrowserControl {
5 | /**
6 | * Display a file in the system browser. If you want to display a file, you must include the absolute path name.
7 | *
8 | * @param url
9 | * the file's url (the url must start with either "http://" or "file://").
10 | */
11 | // Used to identify the windows platform.
12 | private static final String WIN_ID = "Windows";
13 | // The default system browser under windows.
14 | //private static final String WIN_PATH = "rundll32";
15 | // The flag to display a url.
16 | //private static final String WIN_FLAG = "url.dll,FileProtocolHandler";
17 | // The default browser under unix.
18 | //private static final String UNIX_PATH = "netscape";
19 | // The flag to display a url.
20 | //private static final String UNIX_FLAG = "-remote openURL";
21 |
22 | public static void displayURL(String url) {
23 | String osName = System.getProperty("os.name");
24 | try {
25 | if (osName.startsWith("Mac OS")) {
26 | Runtime.getRuntime().exec("open " + url);
27 | } else if (osName.startsWith("Windows"))
28 | Runtime.getRuntime().exec("rundll32 url.dll,FileProtocolHandler " + url);
29 | else { // assume Unix or Linux
30 | String[] browsers = { "firefox", "opera", "konqueror", "epiphany", "mozilla", "netscape" };
31 | String browser = null;
32 | for (int count = 0; count < browsers.length && browser == null; count++)
33 | if (Runtime.getRuntime().exec(new String[] { "which", browsers[count] }).waitFor() == 0)
34 | browser = browsers[count];
35 | if (browser == null)
36 | throw new Exception("Could not find web browser");
37 | else
38 | Runtime.getRuntime().exec(new String[] { browser, url });
39 | }
40 | } catch (Exception t) {
41 | t.printStackTrace(System.err);
42 | }
43 | }
44 | // boolean windows = isWindowsPlatform();
45 | // String cmd = null;
46 | // try {
47 | // if (windows) {
48 | // // cmd = 'rundll32 url.dll,FileProtocolHandler http://...'
49 | // cmd = WIN_PATH + " " + WIN_FLAG + " " + url;
50 | // Process p = Runtime.getRuntime().exec(cmd);
51 | // } else {
52 | // // Under Unix, Netscape has to be running for the "-remote"
53 | // // command to work. So, we try sending the command and
54 | // // check for an exit value. If the exit command is 0,
55 | // // it worked, otherwise we need to start the browser.
56 | // // cmd = 'netscape -remote openURL(http://www.javaworld.com)'
57 | // cmd = UNIX_PATH + " " + UNIX_FLAG + "(" + url + ")";
58 | // Process p = Runtime.getRuntime().exec(cmd);
59 | // try {
60 | // // wait for exit code -- if it's 0, command worked,
61 | // // otherwise we need to start the browser up.
62 | // int exitCode = p.waitFor();
63 | // if (exitCode != 0) {
64 | // // Command failed, start up the browser
65 | // // cmd = 'netscape http://www.javaworld.com'
66 | // cmd = UNIX_PATH + " " + url;
67 | // p = Runtime.getRuntime().exec(cmd);
68 | // }
69 | // } catch (InterruptedException x) {
70 | // System.err.println("Error bringing up browser, cmd='" + cmd + "'");
71 | // System.err.println("Caught: " + x);
72 | // }
73 | // }
74 | // } catch (IOException x) {
75 | // // couldn't exec browser
76 | // System.err.println("Could not invoke browser, command=" + cmd);
77 | // System.err.println("Caught: " + x);
78 | // }
79 | // }
80 |
81 | /**
82 | * Try to determine whether this application is running under Windows or some other platform by examing the "os.name" property.
83 | *
84 | * @return true if this application is running under a Windows OS
85 | */
86 | public static boolean isWindowsPlatform() {
87 | String os = System.getProperty("os.name");
88 | if (os != null && os.startsWith(WIN_ID))
89 | return true;
90 | else
91 | return false;
92 | }
93 |
94 | /**
95 | * Simple example.
96 | */
97 | public static void main(String[] args) {
98 | displayURL("http://www.javaworld.com");
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/xml/ConfigLoader.java:
--------------------------------------------------------------------------------
1 | package com.cubaix.kaiDJ.xml;
2 |
3 | import java.util.Vector;
4 |
5 | import com.cubaix.kaiDJ.KaiDJ;
6 |
7 | public class ConfigLoader {
8 | public ConfigLoader() {
9 | super();
10 | // TODO Auto-generated constructor stub
11 | }
12 |
13 | /**
14 | * @param parentJDJ
15 | * @param aPathIn
16 | */
17 | public static void save(KaiDJ parentJDJ, String aPathIn){
18 |
19 | String aPath;
20 | if (aPathIn.toLowerCase().endsWith(".xml")) {
21 | aPath = aPathIn;
22 | } else {
23 | aPath = aPathIn + ".xml";
24 | }
25 | try {
26 | // Create X structure
27 | Vector aXOs = new Vector();
28 | aXOs.add(new XTag(""));
29 | aXOs.add(new XObject("\n", XObject.PUNCT));
30 | aXOs.add(new XTag(""));
31 | aXOs.add(new XObject("\n", XObject.PUNCT));
32 | //String aDecal = "\t";
33 |
34 | aXOs.add(new XTag(""));
35 | aXOs.add(new XObject("\n", XObject.PUNCT));
36 |
37 | aXOs.add(new XTag(""));
38 | aXOs.add(new XObject("\n", XObject.PUNCT));
39 |
40 | aXOs.add(new XTag(""));
41 | aXOs.add(new XObject("\n", XObject.PUNCT));
42 |
43 | aXOs.add(new XTag(""));
44 | aXOs.add(new XObject("\n", XObject.PUNCT));
45 |
46 | new XLoader("UTF-8").save(aPath, aXOs);
47 | } catch (Throwable t) {
48 | t.printStackTrace(System.err);
49 | }
50 | }
51 |
52 | /**
53 | * @param parentJDJ
54 | * @param aPath
55 | * @return
56 | */
57 | public static Vector load(KaiDJ parentJDJ, String aPath) {
58 | Vector pl = new Vector();
59 | Vector aXOs = new XLoader("UTF-8").load(aPath);
60 | //Vector aGroups = new Vector();
61 | for (int o = 0; o < aXOs.size(); o++) {
62 | XObject aXO = (XObject) aXOs.elementAt(o);
63 | if (aXO.kind == XObject.TAG) {
64 | XTag aXTag = (XTag) aXO;
65 | if (aXTag.tagName.equalsIgnoreCase("user")) {
66 | parentJDJ.userEMail = aXTag.getValue("email");
67 | parentJDJ.userCode = aXTag.getValue("code");
68 | if(aXTag.getValue("welcomed") != null) {
69 | parentJDJ.welcomed = true;
70 | }
71 | }
72 | else if (aXTag.tagName.equalsIgnoreCase("soundcard1")) {
73 | parentJDJ.soundCard1 = Integer.parseInt(aXTag.getValue("id"));
74 | }
75 | else if (aXTag.tagName.equalsIgnoreCase("soundcard2")) {
76 | parentJDJ.soundCard2 = Integer.parseInt(aXTag.getValue("id"));
77 | }
78 | else if (aXTag.tagName.equalsIgnoreCase("soundcardPre")) {
79 | parentJDJ.soundCardPre = Integer.parseInt(aXTag.getValue("id"));
80 | }
81 | }
82 | }
83 | return pl;
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/xml/PlayListLoader.java:
--------------------------------------------------------------------------------
1 | package com.cubaix.kaiDJ.xml;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.BufferedWriter;
5 | import java.io.File;
6 | import java.io.FileInputStream;
7 | import java.io.FileOutputStream;
8 | import java.io.InputStreamReader;
9 | import java.io.OutputStreamWriter;
10 | import java.util.TreeMap;
11 | import java.util.Vector;
12 |
13 | import com.cubaix.kaiDJ.KaiDJ;
14 | import com.cubaix.kaiDJ.db.SongDescr;
15 | import com.cubaix.kaiDJ.db.SongGroup;
16 |
17 | public class PlayListLoader {
18 |
19 | public PlayListLoader() {
20 | }
21 |
22 | /**
23 | * @param parentJDJ
24 | * @param pl
25 | * @param aPathIn
26 | */
27 | public static void save(KaiDJ parentJDJ, Vector pl, String aPath) {
28 | if (aPath.toLowerCase().endsWith(".m3u")) {
29 | saveM3U(parentJDJ, pl, aPath,"ISO-8859-1");
30 | return;
31 | }
32 | if (aPath.toLowerCase().endsWith(".m3u8")) {
33 | saveM3U(parentJDJ, pl, aPath,"UTF-8");
34 | return;
35 | }
36 | saveJDJ(parentJDJ, pl, aPath);
37 | }
38 |
39 | /**
40 | * @param parentJDJ
41 | * @param pl
42 | * @param aPath
43 | */
44 | public static void saveM3U(KaiDJ parentJDJ, Vector pl, String aPath,String currentCharset) {
45 | try {
46 | BufferedWriter aOut = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(aPath), currentCharset));
47 | aOut.write("#JDJ version soft=\"" + KaiDJ._VERSION + "\" pl=\"" + "1.0" + "\"\n");
48 | for (int s = 0; s < pl.size(); s++) {
49 | SongDescr aDescr = (SongDescr) pl.elementAt(s);
50 | if (aDescr instanceof SongGroup) {
51 | if (((SongGroup) aDescr).kind == SongGroup._KIND_OPEN) {
52 | aOut.write("#JDJ group name=\"" + aDescr.getPath() + "\"\n");
53 | } else {
54 | aOut.write("#JDJ /group\n");
55 | }
56 | } else {
57 | aOut.write(aDescr.getPath() + "\n");
58 | }
59 | }
60 | aOut.flush();
61 | aOut.close();
62 | } catch (Throwable t) {
63 | t.printStackTrace(System.err);
64 | }
65 | }
66 |
67 | /**
68 | * @param parentJDJ
69 | * @param pl
70 | * @param aPathIn
71 | */
72 | public static void saveJDJ(KaiDJ parentJDJ, Vector pl, String aPathIn) {
73 | String aPath;
74 | if (aPathIn.toLowerCase().endsWith(".jdj")) {
75 | aPath = aPathIn;
76 | } else {
77 | aPath = aPathIn + ".jdj";
78 | }
79 | try {
80 | // Create X structure
81 | Vector aXOs = new Vector();
82 | aXOs.add(new XTag(""));
83 | aXOs.add(new XObject("\n", XObject.PUNCT));
84 | aXOs.add(new XTag(""));
85 | aXOs.add(new XObject("\n", XObject.PUNCT));
86 | String aDecal = "\t";
87 | for (int s = 0; s < pl.size(); s++) {
88 | SongDescr aDescr = (SongDescr) pl.elementAt(s);
89 | if (aDescr instanceof SongGroup) {
90 | if (((SongGroup) aDescr).kind == SongGroup._KIND_OPEN) {
91 | aXOs.add(new XObject(aDecal, XObject.PUNCT));
92 | aDecal += "\t";
93 | aXOs.add(new XTag(""));
94 | } else {
95 | aDecal = aDecal.substring(1);
96 | aXOs.add(new XObject(aDecal, XObject.PUNCT));
97 | aXOs.add(new XTag(""));
98 | }
99 | } else {
100 | aXOs.add(new XObject(aDecal, XObject.PUNCT));
101 | aXOs.add(new XTag(""));
102 | }
103 | aXOs.add(new XObject("\n", XObject.PUNCT));
104 | }
105 | new XLoader("UTF-8").save(aPath, aXOs);
106 | } catch (Throwable t) {
107 | t.printStackTrace(System.err);
108 | }
109 | }
110 |
111 | /**
112 | * @param parentJDJ
113 | * @param aPath
114 | * @return
115 | */
116 | public static Vector load(KaiDJ parentJDJ, String aPath) {
117 | if (aPath.toLowerCase().endsWith(".m3u")) {
118 | return loadM3U(parentJDJ, aPath,"ISO-8859-1");
119 | }
120 | if (aPath.toLowerCase().endsWith(".m3u8")) {
121 | return loadM3U(parentJDJ, aPath,"UTF-8");
122 | }
123 | return loadJDJ(parentJDJ, aPath);
124 | }
125 |
126 | /**
127 | * @param parentJDJ
128 | * @param aPath
129 | * @return
130 | */
131 | public static Vector loadM3U(KaiDJ parentJDJ, String aPath,String currentCharset) {
132 | Vector pl = new Vector();
133 | try {
134 | BufferedReader aIn = new BufferedReader(new InputStreamReader(new FileInputStream(aPath), currentCharset));
135 | String aLine;
136 | Vector aGroups = new Vector();
137 | String aDir = new File(aPath).getParentFile().getCanonicalPath();
138 | //EM 13/09/2008 : faster with all in a TreeMap
139 | TreeMap aAll = parentJDJ.db.getAllByPaths();
140 | while ((aLine = aIn.readLine()) != null) {
141 | if (aLine.toLowerCase().startsWith("#jdj group ")) {
142 | XTag aXTag = new XTag("<" + aLine + ">");
143 | pl.add(new SongGroup(SongGroup._KIND_OPEN, aXTag.getValue("name")));
144 | aGroups.add(pl.elementAt(pl.size() - 1));
145 | } else if (aLine.toLowerCase().startsWith("#jdj /group")) {
146 | //XTag aXTag = new XTag("<" + aLine + ">");
147 | pl.add(new SongGroup(SongGroup._KIND_CLOSE, ((SongGroup) aGroups.elementAt(aGroups.size() - 1)).getPath()));
148 | aGroups.remove(aGroups.size() - 1);
149 | } else if (!aLine.toLowerCase().startsWith("#")) {
150 | String aNewPath = aLine.trim();
151 | if(!aNewPath.matches("[a-zA-Z]:.*")){
152 | //Build a full path
153 | aNewPath = new File(aDir,aNewPath).getCanonicalPath();
154 | }
155 | //EM 13/09/2008 : faster with all in a TreeMap
156 | SongDescr aDescr = (SongDescr)aAll.get(aNewPath);//parentJDJ.db.searchPath(aNewPath);
157 | if (aDescr == null) {//Direct search
158 | aDescr = parentJDJ.db.searchPath(aNewPath);
159 | }
160 | if (aDescr == null) {
161 | aDescr = new SongDescr(new Integer(-1), aNewPath);
162 | }
163 | pl.add(aDescr);
164 | }
165 | }
166 | } catch (Throwable t) {
167 | t.printStackTrace(System.err);
168 | }
169 | return pl;
170 | }
171 |
172 | /**
173 | * @param parentJDJ
174 | * @param aPath
175 | * @return
176 | */
177 | public static Vector loadJDJ(KaiDJ parentJDJ, String aPath) {
178 | Vector pl = new Vector();
179 | Vector aXOs = new XLoader("UTF-8").load(aPath);
180 | Vector aGroups = new Vector();
181 | //EM 13/09/2008 : faster with all in a TreeMap
182 | TreeMap aAll = parentJDJ.db.getAllByPaths();
183 | for (int o = 0; o < aXOs.size(); o++) {
184 | XObject aXO = (XObject) aXOs.elementAt(o);
185 | if (aXO.kind == XObject.TAG) {
186 | XTag aXTag = (XTag) aXO;
187 | if (aXTag.tagName.equalsIgnoreCase("group")) {
188 | pl.add(new SongGroup(SongGroup._KIND_OPEN, aXTag.getValue("name")));
189 | aGroups.add(pl.elementAt(pl.size() - 1));
190 | } else if (aXTag.tagName.equalsIgnoreCase("/group")) {
191 | pl.add(new SongGroup(SongGroup._KIND_CLOSE, ((SongGroup) aGroups.elementAt(aGroups.size() - 1)).getPath()));
192 | aGroups.remove(aGroups.size() - 1);
193 | } else if (aXTag.tagName.equalsIgnoreCase("song")) {
194 | String aNewPath = aXTag.getValue("path").replaceAll("“", "\"");
195 | //EM 13/09/2008 : faster with all in a TreeMap
196 | SongDescr aDescr = (SongDescr)aAll.get(aNewPath);//parentJDJ.db.searchPath(aNewPath);
197 | if (aDescr == null) {//Direct search
198 | aDescr = parentJDJ.db.searchPath(aNewPath);
199 | }
200 | if (aDescr == null) {
201 | aDescr = new SongDescr(new Integer(-1), aNewPath);
202 | }
203 | pl.add(aDescr);
204 | }
205 | }
206 | }
207 | return pl;
208 | }
209 | }
210 |
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/xml/XObject.java:
--------------------------------------------------------------------------------
1 | package com.cubaix.kaiDJ.xml;
2 |
3 | public class XObject
4 | {
5 | public static final int UNKNOWN = -1;
6 | public static final int WORD = 0;
7 | public static final int PUNCT = 1;
8 | public static final int TAG = 2;
9 | public static final int COMMENT = 3;
10 | public static final int SCRIPT = 3;
11 |
12 | public String text;
13 | public int kind = UNKNOWN;
14 |
15 | /**
16 | *
17 | */
18 | public XObject()
19 | {
20 | }
21 |
22 | /**
23 | * @param aStr
24 | * @param aKind
25 | */
26 | public XObject(String aStr,int aKind)
27 | {
28 | text = aStr;
29 | kind = aKind;
30 | // System.err.println("ABSgO " + aKind + " = " + text);
31 | }
32 |
33 | /**
34 | * @return
35 | */
36 | public XObject getClone(){
37 | return new XObject(text,kind);
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/xml/XQualifier.java:
--------------------------------------------------------------------------------
1 | package com.cubaix.kaiDJ.xml;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.InputStreamReader;
5 | import java.util.Hashtable;
6 | import java.util.Properties;
7 | import java.util.StringTokenizer;
8 |
9 | public class XQualifier {
10 | //Default values
11 | static public char nbsp = (char)160;
12 | static public String nbspStr = ""+nbsp;
13 | static public String PUNCTS = " ,;:.!?()[]{}\"\'*/+-=|\\�\n\r\t"
14 | + nbsp;
15 | static public String NL_AFTER_CHAR_RE = "[\n\r]";
16 | static public String NL_AFTER_TAG_RE = "(/(p|tr|h[0-9]|il|title|head)|br)";
17 | static public String INLINE_TAG_RE = "/?(b|i|u|a|img|font|span)";
18 | static public String SPECIAL_EMPTY_RE = "(br|hr)";
19 | static public boolean USE_ALPHA_ENTITIES = false;
20 | static public String EDITABLE_TAG_RE = "(b|i|u|a|img|font|span)";
21 | static public String HIDDEN_FIELD_RE = "script";
22 |
23 | static Properties properties = null;
24 |
25 | //EM 06/06/2006 : char entities is now here
26 | // Create and load charEntities table
27 | static public Hashtable alphaentitiesToNum = new Hashtable();
28 | static public Hashtable numToAlphaentities = new Hashtable();
29 |
30 | final static String charEntityRessource = "charEntities.tsv";
31 |
32 | //IMPORTANT
33 | //Always init the settings
34 | static boolean initOk = init();
35 |
36 | /**
37 | *
38 | */
39 | static boolean init(){
40 | properties = new Properties();
41 | try{
42 | // InputStream aIS = new FileInputStream(ServerLocationProperties.getInstance().getRootDir() + "/xml.properties");//XQualifier.class.getResourceAsStream("xml.properties");
43 | // if(aIS == null){
44 | // //Not found, keep default
45 | // log.debug("Can't find XML properties, will use default values");
46 | // return false;
47 | // }
48 | // properties.load(aIS);
49 | // String aStr;
50 | // if((aStr = properties.getProperty("nbsp")) != null){
51 | // nbsp = (char)Integer.parseInt(aStr);
52 | // }
53 | // if((aStr = properties.getProperty("poncts")) != null){
54 | // PONCTS = aStr + nbsp;
55 | // }
56 | // if((aStr = properties.getProperty("nl.after.char.re")) != null){
57 | // NL_AFTER_CHAR_RE = aStr;
58 | // }
59 | // if((aStr = properties.getProperty("nl.after.tag.re")) != null){
60 | // NL_AFTER_TAG_RE = aStr;
61 | // }
62 | // if((aStr = properties.getProperty("inline.tag.re")) != null){
63 | // INLINE_TAG_RE = aStr;
64 | // }
65 | // if((aStr = properties.getProperty("editable.tag.re")) != null){
66 | // EDITABLE_TAG_RE = aStr;
67 | // }
68 | // if((aStr = properties.getProperty("hidden.field.re")) != null){
69 | // HIDDEN_FIELD_RE = aStr;
70 | // }
71 | // if((aStr = properties.getProperty("special.empty.re")) != null){
72 | // SPECIAL_EMPTY_RE = aStr;
73 | // }
74 | // if((aStr = properties.getProperty("use.alpha.entities")) != null){
75 | // USE_ALPHA_ENTITIES = (Integer.parseInt(aStr) > 0);
76 | // }
77 | }
78 | catch(Throwable t){
79 | System.err.println("Can't load XML properties, will use default values" + t);
80 | return false;
81 | }
82 |
83 | //EM 06/06/2006
84 | try{
85 | loadCharEntities();
86 | }
87 | catch(Throwable t){
88 | System.err.println("Can't load char entities"+t);
89 | return false;
90 | }
91 |
92 | return true;
93 | }
94 |
95 | //EM 06/06/2006 : char entities are now here
96 | /**
97 | *
98 | */
99 | static void loadCharEntities() {
100 | if (!alphaentitiesToNum.isEmpty()) {
101 | // Already loaded ?
102 | return;
103 | }
104 | try {
105 | // Load charEntities ressource
106 | BufferedReader aBR = new BufferedReader(new InputStreamReader(XLoader.class.getResourceAsStream(charEntityRessource)));
107 | String aLine;
108 | while ((aLine = aBR.readLine()) != null) {
109 | StringTokenizer aST = new StringTokenizer(aLine, "\t", false);
110 | String aEntAlpha = aST.nextToken();
111 | /*String aEntNum =*/ aST.nextToken();
112 | String aExa = aST.nextToken();
113 | Integer aNum = Integer.decode(aExa);
114 | alphaentitiesToNum.put(aEntAlpha, aNum);
115 | numToAlphaentities.put(aNum,aEntAlpha);
116 | }
117 | } catch (Throwable t) {
118 | System.err.println("Can't load entity char table !"+ t);
119 | System.exit(-1);
120 | }
121 | }
122 |
123 | /**
124 | * @param aEntity
125 | * @return
126 | */
127 | static public String transcodeFromEntity(String aEntity) {
128 | Integer aValue = null;
129 | if ((aValue = (Integer) XQualifier.alphaentitiesToNum.get(aEntity)) != null) {
130 | // Found in table
131 | char aChar = (char) (aValue.intValue() & 0xFFFF);
132 | return "" + aChar;
133 | }
134 | if (aEntity.matches("[0-9]+;")) {
135 | // Decode num
136 | char aChar = (char) (Integer.parseInt(aEntity.substring(2, aEntity.length() - 1)) & 0xFFFF);
137 | return "" + aChar;
138 | }
139 | if (aEntity.matches("[xX][0-9A-Fa-f]+;")) {
140 | // Decode hexa
141 | String aHexa = "0x" + aEntity.substring(3, aEntity.length() - 1);
142 | char aChar = (char) (Integer.decode(aHexa).intValue() & 0xFFFF);
143 | return "" + aChar;
144 | }
145 | System.err.println("Unknown entity '" + aEntity + "', will be kept like this");
146 | // Not found
147 | return null;
148 | }
149 |
150 | //EM 06/06/2006 : char entities moved here
151 | /**
152 | * @param aStrIn
153 | * @return
154 | */
155 | static public String transcodeToEntities(String aStrIn,boolean aUseLowCharTable) {
156 | StringBuffer aSB = new StringBuffer();
157 | char aChar;
158 | int aInt;
159 | String aEntity;
160 | int aEntLen;
161 | for (int i = 0; i < aStrIn.length(); i++) {
162 | aChar = aStrIn.charAt(i);
163 | aInt = aChar & 0xFFFFFFFF;
164 | //First check for a & < > conversions
165 | if(aChar == '&'){
166 | if((aEntLen = XQualifier.entityLen(aStrIn,i)) > 0){
167 | //Ok it's an entity
168 | aSB.append(aStrIn.substring(i,i + aEntLen));
169 | i += aEntLen - 1;
170 | continue;
171 | }
172 | //Not en entity, need to be transcoded
173 | aSB.append("&");
174 | continue;
175 | }
176 | else if(aChar == '<'){
177 | //Must be transcoded
178 | aSB.append("<");
179 | continue;
180 | }
181 | else if(aChar == '>'){
182 | //Must be transcoded
183 | aSB.append(">");
184 | continue;
185 | }
186 | //Check for std conversions
187 | //EM 06/06/2006
188 | //if(charsetChecked && aInt <= 255) {
189 | if(aUseLowCharTable && aInt <= 255) {
190 | //For known charset, use low char table
191 | aSB.append(aChar);
192 | }
193 | else{
194 | //Search for a conversion
195 | if(XQualifier.USE_ALPHA_ENTITIES && (aEntity = (String)XQualifier.numToAlphaentities.get(new Integer(aInt))) != null){
196 | //Ok, alpha entity found
197 | aSB.append(aEntity);
198 | }
199 | else if(aInt <= 255){
200 | //Style use low char table
201 | aSB.append(aChar);
202 | }
203 | else{
204 | //Use decimal entity
205 | aSB.append("" + (aChar & 0xFFFF) + ";");
206 | }
207 | }
208 | }
209 | return aSB.toString();
210 | }
211 |
212 | /**
213 | * @param aChar
214 | * @return
215 | */
216 | static public boolean useAlphaEntities(){
217 | return USE_ALPHA_ENTITIES;
218 | }
219 |
220 | /**
221 | * @param aChar
222 | * @return
223 | */
224 | static public boolean isPonctChar(char aChar){
225 | return PUNCTS.indexOf(aChar) >= 0;
226 | }
227 |
228 | /**
229 | * @param aStr
230 | * @param aStartPos
231 | * @return
232 | */
233 | static public int entityLen(String aStr,int aStartPos){
234 | if(aStr.charAt(aStartPos) != '&'){
235 | //Not possible
236 | return -1;
237 | }
238 | int aPos = aStartPos;
239 | String aChar;
240 | while(aPos < aStr.length()){
241 | aChar = aStr.substring(aPos,aPos+1);
242 | if(aChar.equals(";")){
243 | //Could be the end of entity
244 | if(aStr.substring(aStartPos,aPos + 1).matches("&([a-zA-Z]+|#[0-9]+|#0[xX][0-9a-fA-F]+);")){
245 | //Ok entity
246 | return aPos + 1 - aStartPos;
247 | }
248 | //Not a good entity
249 | return -1;
250 | }
251 | if(!aChar.matches("[-9a-zA-Z;]")){
252 | //Impossible
253 | return -1;
254 | }
255 | aPos++;
256 | }
257 | return -1;
258 | }
259 |
260 | /**
261 | * @param aXLT
262 | * @return
263 | */
264 | // static public boolean nlAfter(XLineToken aXLT) {
265 | // switch(aXLT.kind){
266 | // case XLineToken.COLLAPSE:
267 | // for(int o = 0;o < ((XLineTokenCollapse)aXLT).chain.size();o++){
268 | // if(nlAfter((XObject)((XLineTokenCollapse)aXLT).chain.elementAt(o))){
269 | // return true;
270 | // }
271 | // }
272 | // return false;
273 | // default:
274 | // return nlAfter(aXLT.xO);
275 | // }
276 | // //return false;
277 | // }
278 |
279 | /**
280 | * @param aXO
281 | * @return
282 | */
283 | static public boolean nlAfter(XObject aXO) {
284 | if(aXO.text.matches(NL_AFTER_CHAR_RE)){
285 | return true;
286 | }
287 | if (aXO.kind != XObject.TAG) {
288 | return false;
289 | }
290 | if (((XTag) aXO).tagName.toLowerCase().matches(NL_AFTER_TAG_RE)) {
291 | return true;
292 | }
293 | return false;
294 | }
295 |
296 | /**
297 | * @param aT
298 | * @return
299 | */
300 | static public boolean isInline(XTag aT){
301 | return aT.tagName.toLowerCase().matches(INLINE_TAG_RE);
302 | }
303 |
304 | /**
305 | * @param aT
306 | * @return
307 | */
308 | static public boolean isEditableTag(XTag aT){
309 | return aT.tagName.toLowerCase().matches(EDITABLE_TAG_RE);
310 | }
311 |
312 | /**
313 | * @param aT
314 | * @return
315 | */
316 | static public boolean isHiddenField(XTag aT){
317 | return aT.tagName.toLowerCase().matches(HIDDEN_FIELD_RE);
318 | }
319 |
320 | /**
321 | * @return
322 | */
323 | static public boolean isSpecialEmpty(XTag aT){
324 | return aT.tagName.toLowerCase().matches(SPECIAL_EMPTY_RE);
325 | }
326 |
327 | /**
328 | * @return
329 | */
330 | static public boolean isOpen(XTag aT){
331 | if(isSpecialEmpty(aT)){
332 | return false;
333 | }
334 | if(aT.text.matches("<( */.*|.*/ *)>")){
335 | return false;
336 | }
337 | return true;
338 | }
339 |
340 | /**
341 | * @return
342 | */
343 | static public boolean isClose(XTag aT){
344 | return aT.text.matches("< */.*>");
345 | }
346 |
347 | /**
348 | * @return
349 | */
350 | static public boolean isEmpty(XTag aT){
351 | if(isSpecialEmpty(aT)){
352 | return true;
353 | }
354 | return aT.text.matches("<.*/ *>");
355 | }
356 |
357 | }
358 |
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/xml/XTag.java:
--------------------------------------------------------------------------------
1 | package com.cubaix.kaiDJ.xml;
2 |
3 | import java.util.*;
4 |
5 | public class XTag extends XObject {
6 |
7 | public String tagName;
8 | Vector names, values;
9 |
10 | public boolean parseOk = true;
11 |
12 | /**
13 | * @param aStr
14 | */
15 | public XTag(String aStr) {
16 | text = aStr;
17 | kind = TAG;
18 |
19 | names = new Vector();
20 | values = new Vector();
21 |
22 | parse();
23 |
24 | // System.err.println("XTag name=" + tagName + " Names = " + names +
25 | // " Values = " + values);
26 | }
27 |
28 | public XObject getClone(){
29 | return new XTag(text);
30 | }
31 |
32 | /**
33 | *
34 | */
35 | void parse() {
36 | parseOk = true;
37 | StringTokenizer aTokenizer = new StringTokenizer(text, " \t\n\r<>=\"\'", true);
38 | int aState = -1;
39 | String aTok = null, aTmpName = null, aName = null, aValue = null;
40 |
41 | while (aState >= -1 && aTokenizer.hasMoreTokens()) {
42 | switch (aState) {
43 | case 2: // Attribute = ''
44 | aTok = aTokenizer.nextToken();
45 | if ("\'".equals(aTok)) {
46 | // End
47 | names.add(aName);
48 | values.add(aValue);
49 | aName = null;
50 | aValue = null;
51 | aState = 0;
52 | continue;
53 | }
54 | aValue += aTok;
55 | break;
56 | case 1: // Attribute = ""
57 | aTok = aTokenizer.nextToken();
58 | if ("\"".equals(aTok)) {
59 | // End
60 | names.add(aName);
61 | values.add(aValue);
62 | aName = null;
63 | aValue = null;
64 | aState = 0;
65 | continue;
66 | }
67 | aValue += aTok;
68 | break;
69 | case 0:
70 | default:
71 | aTok = aTokenizer.nextToken();
72 | if (">".equals(aTok)) {
73 | aState = -2;
74 | if(aTokenizer.hasMoreElements()){
75 | // Error
76 | System.err.println("Warning, bad tag attribute : " + text);
77 | parseOk = false;
78 | }
79 | continue;
80 | }
81 | if ("<".equals(aTok)) {
82 | if(aState != -1){
83 | // Error
84 | System.err.println("Warning, bad tag attribute : " + text);
85 | parseOk = false;
86 | }
87 | //Begin of tag
88 | aState = 0;
89 | continue;
90 | }
91 | if (" ".equals(aTok) || "\t".equals(aTok) || "\r".equals(aTok) || "\n".equals(aTok)) {
92 | //No interest
93 | continue;
94 | }
95 | if ("=".equals(aTok)) {
96 | if(aTmpName == null){
97 | // Error
98 | System.err.println("Warning, bad tag attribute : " + text);
99 | parseOk = false;
100 | }
101 | aName = aTmpName;
102 | aValue = "";
103 | aTmpName = null;
104 | continue;
105 | }
106 | if ("\"".equals(aTok)) {
107 | if (aName == null) {
108 | // Error
109 | System.err.println("Warning, bad tag attribute : " + text);
110 | parseOk = false;
111 | }
112 | aState = 1;
113 | continue;
114 | }
115 | if ("\'".equals(aTok)) {
116 | if (aName == null) {
117 | // Error
118 | parseOk = false;
119 | System.err.println("Error, bad tag attribute : " + text);
120 | }
121 | aState = 2;
122 | continue;
123 | }
124 | if (aName != null && aName.length() > 0) {
125 | names.add(aName);
126 | values.add(aTok);
127 | aName = null;
128 | aValue = null;
129 | continue;
130 | }
131 | if (tagName == null) {
132 | tagName = aTok;
133 | if (tagName.startsWith("!")) {
134 | // Not a parsable tag !
135 | parseOk = false;
136 | return;
137 | }
138 | continue;
139 | }
140 | if(aTmpName != null){
141 | // Error
142 | System.err.println("Warning, bad tag attribute : " + text);
143 | parseOk = false;
144 | }
145 | aTmpName = aTok;
146 | break;
147 | }
148 | }
149 | //EM 29/05/2006
150 | // also take aAttrName into account : a possible attribute without a value
151 | if(aState >= 0 || aName != null || aValue != null || aTmpName != null){
152 | parseOk = false;
153 | }
154 | }
155 |
156 | /**
157 | * @param aName
158 | * @return
159 | */
160 | public String getValue(String aName) {
161 | for (int i = 0; i < names.size(); i++) {
162 | if (aName.equalsIgnoreCase((String) names.elementAt(i))) {
163 | if (i > values.size()) {
164 | return null;
165 | }
166 | return (String) values.elementAt(i);
167 | }
168 | }
169 | return null;
170 | }
171 | }
172 |
--------------------------------------------------------------------------------
/src/com/cubaix/kaiDJ/xml/charEntities.tsv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EtienneAb3d/karaok-AI/2eaaf4fba6234ad6206e112c59a0d6143540aace/src/com/cubaix/kaiDJ/xml/charEntities.tsv
--------------------------------------------------------------------------------
/src/javazoom/jlgui/basicplayer/BasicController.java:
--------------------------------------------------------------------------------
1 | /*
2 | * BasicController.
3 | *
4 | * JavaZOOM : jlgui@javazoom.net
5 | * http://www.javazoom.net
6 | *
7 | *-----------------------------------------------------------------------
8 | * This program is free software; you can redistribute it and/or modify
9 | * it under the terms of the GNU Library General Public License as published
10 | * by the Free Software Foundation; either version 2 of the License, or
11 | * (at your option) any later version.
12 | *
13 | * This program is distributed in the hope that it will be useful,
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | * GNU Library General Public License for more details.
17 | *
18 | * You should have received a copy of the GNU Library General Public
19 | * License along with this program; if not, write to the Free Software
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 | *----------------------------------------------------------------------
22 | */
23 | package javazoom.jlgui.basicplayer;
24 |
25 | import java.io.File;
26 | import java.io.InputStream;
27 | import java.net.URL;
28 |
29 | /**
30 | * This interface defines player controls available.
31 | */
32 | public interface BasicController
33 | {
34 | /**
35 | * Open inputstream to play.
36 | * @param in
37 | * @throws BasicPlayerException
38 | */
39 | public void open(InputStream in) throws BasicPlayerException;
40 |
41 | /**
42 | * Open file to play.
43 | * @param file
44 | * @throws BasicPlayerException
45 | */
46 | public void open(File file) throws BasicPlayerException;
47 |
48 | /**
49 | * Open URL to play.
50 | * @param url
51 | * @throws BasicPlayerException
52 | */
53 | public void open(URL url) throws BasicPlayerException;
54 |
55 | /**
56 | * Skip bytes.
57 | * @param bytes
58 | * @return bytes skipped according to audio frames constraint.
59 | * @throws BasicPlayerException
60 | */
61 | public long seek(long bytes) throws BasicPlayerException;
62 |
63 | /**
64 | * Start playback.
65 | * @throws BasicPlayerException
66 | */
67 | public void play() throws BasicPlayerException;
68 |
69 | /**
70 | * Stop playback.
71 | * @throws BasicPlayerException
72 | */
73 | public void stop() throws BasicPlayerException;
74 |
75 | /**
76 | * Pause playback.
77 | * @throws BasicPlayerException
78 | */
79 | public void pause() throws BasicPlayerException;
80 |
81 | /**
82 | * Resume playback.
83 | * @throws BasicPlayerException
84 | */
85 | public void resume() throws BasicPlayerException;
86 |
87 | /**
88 | * Sets Pan (Balance) value.
89 | * Linear scale : -1.0 <--> +1.0
90 | * @param pan value from -1.0 to +1.0
91 | * @throws BasicPlayerException
92 | */
93 | public void setPan(double pan) throws BasicPlayerException;
94 |
95 | /**
96 | * Sets Gain value.
97 | * Linear scale 0.0 <--> 1.0
98 | * @param gain value from 0.0 to 1.0
99 | * @throws BasicPlayerException
100 | */
101 | public void setGain(double gain) throws BasicPlayerException;
102 | }
103 |
--------------------------------------------------------------------------------
/src/javazoom/jlgui/basicplayer/BasicPlayerEvent.java:
--------------------------------------------------------------------------------
1 | /*
2 | * BasicPlayerEvent.
3 | *
4 | * JavaZOOM : jlgui@javazoom.net
5 | * http://www.javazoom.net
6 | *
7 | *-----------------------------------------------------------------------
8 | * This program is free software; you can redistribute it and/or modify
9 | * it under the terms of the GNU Library General Public License as published
10 | * by the Free Software Foundation; either version 2 of the License, or
11 | * (at your option) any later version.
12 | *
13 | * This program is distributed in the hope that it will be useful,
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | * GNU Library General Public License for more details.
17 | *
18 | * You should have received a copy of the GNU Library General Public
19 | * License along with this program; if not, write to the Free Software
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 | *----------------------------------------------------------------------
22 | */
23 | package javazoom.jlgui.basicplayer;
24 |
25 | /**
26 | * This class implements player events.
27 | */
28 | public class BasicPlayerEvent
29 | {
30 | public static final int UNKNOWN = -1;
31 | public static final int OPENING = 0;
32 | public static final int OPENED = 1;
33 | public static final int PLAYING = 2;
34 | public static final int STOPPED = 3;
35 | public static final int PAUSED = 4;
36 | public static final int RESUMED = 5;
37 | public static final int SEEKING = 6;
38 | public static final int SEEKED = 7;
39 | public static final int EOM = 8;
40 | public static final int PAN = 9;
41 | public static final int GAIN = 10;
42 | private int code = UNKNOWN;
43 | private int position = -1;
44 | private double value = -1.0;
45 | private Object source = null;
46 | private Object description = null;
47 |
48 | /**
49 | * Constructor
50 | * @param source of the event
51 | * @param code of the envent
52 | * @param position optional stream position
53 | * @param value opitional control value
54 | * @param desc optional description
55 | */
56 | public BasicPlayerEvent(Object source, int code, int position, double value, Object desc)
57 | {
58 | this.value = value;
59 | this.position = position;
60 | this.source = source;
61 | this.code = code;
62 | this.description = desc;
63 | }
64 |
65 | /**
66 | * Return code of the event triggered.
67 | * @return
68 | */
69 | public int getCode()
70 | {
71 | return code;
72 | }
73 |
74 | /**
75 | * Return position in the stream when event occured.
76 | * @return
77 | */
78 | public int getPosition()
79 | {
80 | return position;
81 | }
82 |
83 | /**
84 | * Return value related to event triggered.
85 | * @return
86 | */
87 | public double getValue()
88 | {
89 | return value;
90 | }
91 |
92 | /**
93 | * Return description.
94 | * @return
95 | */
96 | public Object getDescription()
97 | {
98 | return description;
99 | }
100 |
101 | public Object getSource()
102 | {
103 | return source;
104 | }
105 |
106 | public String toString()
107 | {
108 | if (code == OPENED) return "OPENED:" + position;
109 | else if (code == OPENING) return "OPENING:" + position + ":" + description;
110 | else if (code == PLAYING) return "PLAYING:" + position;
111 | else if (code == STOPPED) return "STOPPED:" + position;
112 | else if (code == PAUSED) return "PAUSED:" + position;
113 | else if (code == RESUMED) return "RESUMED:" + position;
114 | else if (code == SEEKING) return "SEEKING:" + position;
115 | else if (code == SEEKED) return "SEEKED:" + position;
116 | else if (code == EOM) return "EOM:" + position;
117 | else if (code == PAN) return "PAN:" + value;
118 | else if (code == GAIN) return "GAIN:" + value;
119 | else return "UNKNOWN:" + position;
120 | }
121 | }
122 |
--------------------------------------------------------------------------------
/src/javazoom/jlgui/basicplayer/BasicPlayerEventLauncher.java:
--------------------------------------------------------------------------------
1 | /*
2 | * BasicPlayerEventLauncher.
3 | *
4 | * JavaZOOM : jlgui@javazoom.net
5 | * http://www.javazoom.net
6 | *
7 | *-----------------------------------------------------------------------
8 | * This program is free software; you can redistribute it and/or modify
9 | * it under the terms of the GNU Library General Public License as published
10 | * by the Free Software Foundation; either version 2 of the License, or
11 | * (at your option) any later version.
12 | *
13 | * This program is distributed in the hope that it will be useful,
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | * GNU Library General Public License for more details.
17 | *
18 | * You should have received a copy of the GNU Library General Public
19 | * License along with this program; if not, write to the Free Software
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 | *----------------------------------------------------------------------
22 | */
23 | package javazoom.jlgui.basicplayer;
24 |
25 | import java.util.Collection;
26 | import java.util.Iterator;
27 |
28 | /**
29 | * This class implements a threaded events launcher.
30 | */
31 | public class BasicPlayerEventLauncher extends Thread
32 | {
33 | private int code = -1;
34 | private int position = -1;
35 | private double value = 0.0;
36 | private Object description = null;
37 | private Collection listeners = null;
38 | private Object source = null;
39 |
40 | /**
41 | * Contructor.
42 | * @param code
43 | * @param position
44 | * @param value
45 | * @param description
46 | * @param listeners
47 | * @param source
48 | */
49 | public BasicPlayerEventLauncher(int code, int position, double value, Object description, Collection listeners, Object source)
50 | {
51 | super();
52 | this.code = code;
53 | this.position = position;
54 | this.value = value;
55 | this.description = description;
56 | this.listeners = listeners;
57 | this.source = source;
58 | }
59 |
60 | public void run()
61 | {
62 | if (listeners != null)
63 | {
64 | Iterator it = listeners.iterator();
65 | while (it.hasNext())
66 | {
67 | BasicPlayerListener bpl = (BasicPlayerListener) it.next();
68 | BasicPlayerEvent event = new BasicPlayerEvent(source, code, position, value, description);
69 | bpl.stateUpdated(event);
70 | }
71 | }
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/src/javazoom/jlgui/basicplayer/BasicPlayerException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * BasicPlayerException.
3 | *
4 | * JavaZOOM : jlgui@javazoom.net
5 | * http://www.javazoom.net
6 | *
7 | *-----------------------------------------------------------------------
8 | * This program is free software; you can redistribute it and/or modify
9 | * it under the terms of the GNU Library General Public License as published
10 | * by the Free Software Foundation; either version 2 of the License, or
11 | * (at your option) any later version.
12 | *
13 | * This program is distributed in the hope that it will be useful,
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | * GNU Library General Public License for more details.
17 | *
18 | * You should have received a copy of the GNU Library General Public
19 | * License along with this program; if not, write to the Free Software
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 | *----------------------------------------------------------------------
22 | */
23 | package javazoom.jlgui.basicplayer;
24 |
25 | import java.io.PrintStream;
26 | import java.io.PrintWriter;
27 |
28 | /**
29 | * This class implements custom exception for basicplayer.
30 | */
31 | public class BasicPlayerException extends Exception
32 | {
33 | public static final String GAINCONTROLNOTSUPPORTED = "Gain control not supported";
34 | public static final String PANCONTROLNOTSUPPORTED = "Pan control not supported";
35 | public static final String WAITERROR = "Wait error";
36 | public static final String CANNOTINITLINE = "Cannot init line";
37 | public static final String SKIPNOTSUPPORTED = "Skip not supported";
38 | private Throwable cause = null;
39 |
40 | public BasicPlayerException()
41 | {
42 | super();
43 | }
44 |
45 | public BasicPlayerException(String msg)
46 | {
47 | super(msg);
48 | }
49 |
50 | public BasicPlayerException(Throwable cause)
51 | {
52 | super();
53 | this.cause = cause;
54 | }
55 |
56 | public BasicPlayerException(String msg, Throwable cause)
57 | {
58 | super(msg);
59 | this.cause = cause;
60 | }
61 |
62 | public Throwable getCause()
63 | {
64 | return cause;
65 | }
66 |
67 | /**
68 | * Returns the detail message string of this throwable. If it was
69 | * created with a null message, returns the following:
70 | * (cause==null ? null : cause.toString()).
71 | */
72 | public String getMessage()
73 | {
74 | if (super.getMessage() != null)
75 | {
76 | return super.getMessage();
77 | }
78 | else if (cause != null)
79 | {
80 | return cause.toString();
81 | }
82 | else
83 | {
84 | return null;
85 | }
86 | }
87 |
88 | public void printStackTrace()
89 | {
90 | printStackTrace(System.err);
91 | }
92 |
93 | public void printStackTrace(PrintStream out)
94 | {
95 | synchronized (out)
96 | {
97 | PrintWriter pw = new PrintWriter(out, false);
98 | printStackTrace(pw);
99 | pw.flush();
100 | }
101 | }
102 |
103 | public void printStackTrace(PrintWriter out)
104 | {
105 | if (cause != null) cause.printStackTrace(out);
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/src/javazoom/jlgui/basicplayer/BasicPlayerListener.java:
--------------------------------------------------------------------------------
1 | /*
2 | * BasicPlayerListener.
3 | *
4 | * JavaZOOM : jlgui@javazoom.net
5 | * http://www.javazoom.net
6 | *
7 | *-----------------------------------------------------------------------
8 | * This program is free software; you can redistribute it and/or modify
9 | * it under the terms of the GNU Library General Public License as published
10 | * by the Free Software Foundation; either version 2 of the License, or
11 | * (at your option) any later version.
12 | *
13 | * This program is distributed in the hope that it will be useful,
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | * GNU Library General Public License for more details.
17 | *
18 | * You should have received a copy of the GNU Library General Public
19 | * License along with this program; if not, write to the Free Software
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 | *----------------------------------------------------------------------
22 | */
23 | package javazoom.jlgui.basicplayer;
24 |
25 | import java.util.Map;
26 |
27 | /**
28 | * This interface defines callbacks methods that will be notified
29 | * for all registered BasicPlayerListener of BasicPlayer.
30 | */
31 | public interface BasicPlayerListener
32 | {
33 | /**
34 | * Open callback, stream is ready to play.
35 | *
36 | * properties map includes audio format dependant features such as
37 | * bitrate, duration, frequency, channels, number of frames, vbr flag,
38 | * id3v2/id3v1 (for MP3 only), comments (for Ogg Vorbis), ...
39 | *
40 | * @param stream could be File, URL or InputStream
41 | * @param properties audio stream properties.
42 | */
43 | public void opened(Object stream, Map properties);
44 |
45 | /**
46 | * Progress callback while playing.
47 | *
48 | * This method is called severals time per seconds while playing.
49 | * properties map includes audio format features such as
50 | * instant bitrate, microseconds position, current frame number, ...
51 | *
52 | * @param bytesread from encoded stream.
53 | * @param microseconds elapsed (reseted after a seek !).
54 | * @param pcmdata PCM samples.
55 | * @param properties audio stream parameters.
56 | */
57 | public void progress(int bytesread, long microseconds, byte[] pcmdata, Map properties);
58 |
59 | /**
60 | * Notification callback for basicplayer events such as opened, eom ...
61 | *
62 | * @param event
63 | */
64 | public void stateUpdated(BasicPlayerEvent event);
65 |
66 | /**
67 | * A handle to the BasicPlayer, plugins may control the player through
68 | * the controller (play, stop, ...)
69 | * @param controller : a handle to the player
70 | */
71 | public void setController(BasicController controller);
72 | }
73 |
--------------------------------------------------------------------------------
/src/kj/audio/KJAudioDataConsumer.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Created on Jul 10, 2004
3 | *
4 | * TODO To change the template for this generated file go to
5 | * Window - Preferences - Java - Code Generation - Code and Comments
6 | */
7 | package kj.audio;
8 |
9 | /**
10 | * @author Kris
11 | *
12 | * TODO To change the template for this generated type comment go to
13 | * Window - Preferences - Java - Code Generation - Code and Comments
14 | */
15 | public interface KJAudioDataConsumer {
16 |
17 | void writeAudioData( byte[] pAudioData );
18 | void writeAudioData( byte[] pAudioData, int pOffset, int pLength );
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/src/kj/dsp/KJDigitalSignalProcessingAudioDataConsumer.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Created on Nov 30, 2004
3 | *
4 | * TODO To change the template for this generated file go to
5 | * Window - Preferences - Java - Code Generation - Code and Comments
6 | */
7 | package kj.dsp;
8 |
9 | import java.util.ArrayList;
10 |
11 | import javax.sound.sampled.SourceDataLine;
12 |
13 | import com.cubaix.kaiDJ.KaiDJ;
14 |
15 | import kj.audio.KJAudioDataConsumer;
16 | //import kj.ui.KJJukeBox;
17 |
18 | /**
19 | * @author Kris
20 | *
21 | * TODO To change the template for this generated type comment go to
22 | * Window - Preferences - Java - Code Generation - Code and Comments
23 | */
24 | public final class KJDigitalSignalProcessingAudioDataConsumer implements KJAudioDataConsumer {
25 | //EM 29/04/2009 : parentJDJ
26 | protected KaiDJ parentJDJ;
27 |
28 | private static final int DEFAULT_SAMPLE_SIZE = 2048;
29 | private static final int DEFAULT_FPS = 70;
30 |
31 | public static final int SAMPLE_TYPE_EIGHT_BIT = 1;
32 | public static final int SAMPLE_TYPE_SIXTEEN_BIT = 2;
33 | public static final int CHANNEL_MODE_MONO = 1;
34 | public static final int CHANNEL_MODE_STEREO = 2;
35 |
36 | //EM 14/11/2008 : public
37 | public Object readWriteLock = new Object();
38 |
39 | //EM 14/11/2008 : public
40 | public SourceDataLine sourceDataLine;
41 |
42 | //EM 14/11/2008 : public
43 | public int sampleSize;
44 |
45 | //EM 14/11/2008 : public
46 | public long fpsAsNS;
47 | public long desiredFpsAsNS;
48 |
49 | //EM 14/11/2008 : public
50 | public byte[] audioDataBuffer;
51 |
52 | //EM 14/11/2008 : public
53 | public float[] left;
54 | public float[] right;
55 |
56 | private int position;
57 | //EM 14/11/2008 : public
58 | public long offset;
59 |
60 | //EM 14/11/2008 : externalization of inner class for more efficiency
61 | //(possibly not a big gain, but much more fluent in JOP profiler)
62 | //private SignalProcessor signalProcessor;
63 | private KJDigitalSignalProcessor1 signalProcessor;
64 |
65 | //EM 14/11/2008 : public
66 | public ArrayList dsps = new ArrayList();
67 |
68 | //EM 14/11/2008 : public
69 | public int sampleType;
70 | //EM 14/11/2008 : public
71 | public int channelMode;
72 |
73 | /**
74 | * Default constructor creates a DSPAC with DEFAULT_SAMPLE_SIZE and DEFAULT_FPS as
75 | * parameters.
76 | */
77 | //EM 29/04/2009 : parentJDJ
78 | public KJDigitalSignalProcessingAudioDataConsumer(KaiDJ aParentJDJ) {
79 | this( DEFAULT_SAMPLE_SIZE, DEFAULT_FPS );
80 |
81 | //EM 29/04/2009
82 | parentJDJ = aParentJDJ;
83 | }
84 |
85 | /**
86 | * @param pSampleSize The sample size to extract from audio data sent to the SourceDataLine.
87 | * @param pFramePerSecond The desired refresh rate per second of registered DSP's.
88 | */
89 | public KJDigitalSignalProcessingAudioDataConsumer( int pSampleSize, int pFramesPerSecond ) {
90 | this( pSampleSize, pFramesPerSecond, SAMPLE_TYPE_SIXTEEN_BIT, CHANNEL_MODE_STEREO );
91 | }
92 |
93 | /**
94 | * @param pSampleSize The sample size to extract from audio data sent to the SourceDataLine.
95 | * @param pFramePerSecond The desired refresh rate per second of registered DSP's.
96 | * @param pSampleType The sample type SAMPLE_TYPE_EIGHT_BIT or SAMPLE_TYPE_SIXTEEN_BIT.
97 | * @param pFramePerSecond The channel mode CHANNEL_MODE_MONO or CHANNEL_MODE_STEREO.
98 | */
99 | public KJDigitalSignalProcessingAudioDataConsumer( int pSampleSize, int pFramesPerSecond, int pSampleType, int pChannelMode ) {
100 |
101 | sampleSize = pSampleSize;
102 | desiredFpsAsNS = 1000000000L / (long)pFramesPerSecond;
103 | fpsAsNS = desiredFpsAsNS;
104 |
105 | setSampleType( pSampleType );
106 | setChannelMode( pChannelMode );
107 | }
108 |
109 | /**
110 | * Adds a DSP to the DSPAC and forwards any audio data to it at the specific
111 | * frame rate.
112 | *
113 | * @param A class implementing the KJDigitalSignalProcessor interface.
114 | */
115 | public void add( KJDigitalSignalProcessor pSignalProcessor ) {
116 | dsps.add( pSignalProcessor );
117 | }
118 |
119 | /**
120 | * Removes the specified DSP from this DSPAC if it exists.
121 | *
122 | * @param A class implementing the KJDigitalSignalProcessor interface.
123 | */
124 | public void remove( KJDigitalSignalProcessor pSignalProcessor ) {
125 | dsps.remove( pSignalProcessor );
126 | }
127 |
128 | public void setChannelMode( int pChannelMode ) {
129 | channelMode = pChannelMode;
130 | }
131 |
132 | public void setSampleType( int pSampleType ) {
133 | sampleType = pSampleType;
134 | }
135 |
136 | /**
137 | * Start monitoring the specified SourceDataLine.
138 | *
139 | * @param pSdl A SourceDataLine.
140 | */
141 | public synchronized void start( SourceDataLine pSdl ) {
142 |
143 | // -- Stop processing previous source data line.
144 | if ( signalProcessor != null ) {
145 | stop();
146 | }
147 |
148 | if ( signalProcessor == null ) {
149 |
150 | // System.out.println( "ADBS: " + pSdl.getBufferSize() );
151 |
152 | sourceDataLine = pSdl;
153 |
154 | // -- Allocate double the memory than the SDL to prevent
155 | // buffer overlapping.
156 | audioDataBuffer = new byte[ pSdl.getBufferSize() << 1 ];
157 |
158 | left = new float[ sampleSize ];
159 | right = new float[ sampleSize ];
160 |
161 | position = 0;
162 | offset = 0;
163 |
164 | //EM 14/11/2008 : externalization of inner class for more efficiency
165 | signalProcessor = new /*SignalProcessor();/*/KJDigitalSignalProcessor1(this);
166 |
167 | Thread aTh = new Thread( signalProcessor ,"DSP SignalProcessor");
168 | aTh.start();
169 | }
170 |
171 | }
172 |
173 | /**
174 | * Stop monitoring the currect SourceDataLine.
175 | */
176 | public synchronized void stop() {
177 |
178 | if ( signalProcessor != null ) {
179 |
180 | signalProcessor.stop();
181 | signalProcessor = null;
182 |
183 | audioDataBuffer = null;
184 | sourceDataLine = null;
185 |
186 | }
187 |
188 | }
189 |
190 | private void storeAudioData( byte[] pAudioData, int pOffset, int pLength ) {
191 |
192 | synchronized( readWriteLock ) {
193 |
194 | if ( audioDataBuffer == null ) {
195 | return;
196 | }
197 |
198 | int wOverrun = 0;
199 |
200 | if ( position + pLength > audioDataBuffer.length - 1 ) {
201 |
202 | wOverrun = ( position + pLength ) - audioDataBuffer.length;
203 | pLength = audioDataBuffer.length - position;
204 |
205 | }
206 |
207 | System.arraycopy( pAudioData, pOffset, audioDataBuffer, position, pLength );
208 |
209 | if ( wOverrun > 0 ) {
210 |
211 | System.arraycopy( pAudioData, pOffset + pLength, audioDataBuffer, 0, wOverrun );
212 | position = wOverrun;
213 |
214 | } else {
215 | position += pLength;
216 | }
217 |
218 | // KJJukeBox.getDSPDialog().setDSPBufferInfo(
219 | // position,
220 | // pOffset,
221 | // pLength,
222 | // audioDataBuffer.length );
223 |
224 | }
225 |
226 | }
227 |
228 | /* (non-Javadoc)
229 | * @see kj.audio.KJAudioDataConsumer#writeAudioData(byte[])
230 | */
231 | public void writeAudioData( byte[] pAudioData ) {
232 | storeAudioData( pAudioData, 0, pAudioData.length );
233 | }
234 |
235 | /* (non-Javadoc)
236 | * @see kj.audio.KJAudioDataConsumer#writeAudioData(byte[], int, int)
237 | */
238 | public void writeAudioData( byte[] pAudioData, int pOffset, int pLength ) {
239 | storeAudioData( pAudioData, pOffset, pLength );
240 | }
241 |
242 | private class SignalProcessor implements Runnable {
243 |
244 | boolean process = true;
245 |
246 | long lfp = 0;
247 |
248 | int frameSize;
249 |
250 | public SignalProcessor() {
251 | frameSize = sourceDataLine.getFormat().getFrameSize();
252 | }
253 |
254 | private int calculateSamplePosition() {
255 |
256 | synchronized( readWriteLock ) {
257 |
258 | long wFp = sourceDataLine.getLongFramePosition();
259 | long wNfp = lfp;
260 |
261 | lfp = wFp;
262 |
263 | int wSdp = (int)( (long)( wNfp * frameSize ) - (long)( audioDataBuffer.length * offset ) );
264 |
265 | // KJJukeBox.getDSPDialog().setOutputPositionInfo(
266 | // wFp,
267 | // wFp - wNfp,
268 | // wSdp );
269 |
270 | return wSdp;
271 |
272 | }
273 |
274 | }
275 |
276 | private void processSamples( int pPosition ) {
277 |
278 | int c = pPosition;
279 |
280 | if ( channelMode == CHANNEL_MODE_MONO && sampleType == SAMPLE_TYPE_EIGHT_BIT ) {
281 |
282 | for( int a = 0; a < sampleSize; a++, c++ ) {
283 |
284 | if ( c >= audioDataBuffer.length ) {
285 | offset++;
286 | c = ( c - audioDataBuffer.length );
287 | }
288 |
289 | left[ a ] = (float)( (int)audioDataBuffer[ c ] / 128.0f );
290 | right[ a ] = left[ a ];
291 |
292 | }
293 |
294 | } else if ( channelMode == CHANNEL_MODE_STEREO && sampleType == SAMPLE_TYPE_EIGHT_BIT ) {
295 |
296 | for( int a = 0; a < sampleSize; a++, c += 2 ) {
297 |
298 | if ( c >= audioDataBuffer.length ) {
299 | offset++;
300 | c = ( c - audioDataBuffer.length );
301 | }
302 |
303 | left[ a ] = (float)( (int)audioDataBuffer[ c ] / 128.0f );
304 | right[ a ] = (float)( (int)audioDataBuffer[ c + 1 ] / 128.0f );
305 |
306 | }
307 |
308 | } else if ( channelMode == CHANNEL_MODE_MONO && sampleType == SAMPLE_TYPE_SIXTEEN_BIT ) {
309 |
310 | for( int a = 0; a < sampleSize; a++, c += 2 ) {
311 |
312 | if ( c >= audioDataBuffer.length ) {
313 | offset++;
314 | c = ( c - audioDataBuffer.length );
315 | }
316 |
317 | left[ a ] = (float)( ( (int)audioDataBuffer[ c + 1 ] << 8 ) + audioDataBuffer[ c ] ) / 32767.0f;;
318 | right[ a ] = left[ a ];
319 |
320 | }
321 |
322 | } else if ( channelMode == CHANNEL_MODE_STEREO && sampleType == SAMPLE_TYPE_SIXTEEN_BIT ) {
323 |
324 | for( int a = 0; a < sampleSize; a++, c += 4 ) {
325 |
326 | if ( c >= audioDataBuffer.length ) {
327 | offset++;
328 | c = ( c - audioDataBuffer.length );
329 | }
330 |
331 | left[ a ] = (float)( ( (int)audioDataBuffer[ c + 1 ] << 8 ) + audioDataBuffer[ c ] ) / 32767.0f;
332 | right[ a ] = (float)( ( (int)audioDataBuffer[ c + 3 ] << 8 ) + audioDataBuffer[ c + 2 ] ) / 32767.0f;
333 |
334 | }
335 |
336 | }
337 |
338 | }
339 |
340 | public void run() {
341 |
342 | while( process ) {
343 |
344 | try {
345 |
346 | long wStn = System.nanoTime();
347 |
348 | int wSdp = calculateSamplePosition();
349 |
350 | if ( wSdp > 0 ) {
351 | processSamples( wSdp );
352 | }
353 |
354 | // -- Dispatch sample data to digtal signal processors.
355 | for( int a = 0; a < dsps.size(); a++ ) {
356 |
357 | // -- Calculate the frame rate ratio hint. This value can be used by
358 | // animated DSP's to fast forward animation frames to make up for
359 | // inconsistencies with the frame rate.
360 | float wFrr = (float)fpsAsNS / (float)desiredFpsAsNS;
361 |
362 | try {
363 | ( (KJDigitalSignalProcessor)dsps.get( a ) ).process( left, right, wFrr );
364 | } catch( Exception pEx ) {
365 | System.err.println( "-- DSP Exception: " );
366 | pEx.printStackTrace();
367 | }
368 | }
369 |
370 | // KJJukeBox.getDSPDialog().setDSPInformation(
371 | // String.valueOf( 1000.0f / ( (float)( wEtn - wStn ) / 1000000.0f ) ) );
372 |
373 | // System.out.println( 1000.0f / ( (float)( wEtn - wStn ) / 1000000.0f ) );
374 |
375 | long wDelay = fpsAsNS - ( System.nanoTime() - wStn );
376 |
377 | // -- No DSP registered? Put the the DSP thread to sleep.
378 | if ( dsps.isEmpty() ) {
379 | wDelay = 1000000000; // -- 1 second.
380 | }
381 |
382 | if ( wDelay > 0 ) {
383 |
384 | try {
385 | Thread.sleep( wDelay / 1000000, (int)wDelay % 1000000 );
386 | } catch ( Exception pEx ) {
387 | // TODO Auto-generated catch block
388 | }
389 |
390 | // -- Adjust FPS until we meet the "desired FPS".
391 | if ( fpsAsNS > desiredFpsAsNS ) {
392 | fpsAsNS -= wDelay;
393 | } else {
394 | fpsAsNS = desiredFpsAsNS;
395 | }
396 |
397 | } else {
398 |
399 | // -- Reduce FPS because we cannot keep up with the "desired FPS".
400 | fpsAsNS += -wDelay;
401 |
402 | // -- Keep thread from hogging CPU.
403 | try {
404 | Thread.sleep( 10 );
405 | } catch ( InterruptedException pEx ) {
406 | // TODO Auto-generated catch block
407 | }
408 |
409 | }
410 |
411 | } catch( Exception pEx ) {
412 | System.err.println( "- DSP Exception: " );
413 | pEx.printStackTrace();
414 | }
415 |
416 | }
417 |
418 | }
419 |
420 | public void stop() {
421 | process = false;
422 | }
423 |
424 | }
425 |
426 | }
427 |
--------------------------------------------------------------------------------
/src/kj/dsp/KJDigitalSignalProcessor.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Created on Nov 30, 2004
3 | *
4 | * TODO To change the template for this generated file go to
5 | * Window - Preferences - Java - Code Generation - Code and Comments
6 | */
7 | package kj.dsp;
8 |
9 | /**
10 | * @author Kris Fudalewski
11 | *
12 | * Classes must implement this interface in order to be registered with the
13 | * KJDigitalSignalProcessingAudioDataConsumer class.
14 | *
15 | */
16 | public interface KJDigitalSignalProcessor {
17 |
18 | /**
19 | * Called by the KJDigitalSignalProcessingAudioDataConsumer.
20 | *
21 | * @param pLeftChannel Audio data for the left channel.
22 | * @param pRightChannel Audio data for the right channel.
23 | * @param pFrameRateRatioHint A float value representing the ratio of the current
24 | * frame rate to the desired frame rate. It is used to
25 | * keep DSP animation consistent if the frame rate drop
26 | * below the desired frame rate.
27 | */
28 | void process( float[] pLeftChannel, float[] pRightChannel, float pFrameRateRatioHint );
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/src/kj/dsp/KJDigitalSignalProcessor1.java:
--------------------------------------------------------------------------------
1 | package kj.dsp;
2 |
3 | //EM 14/11/2008 : externalization of inner class for more efficiency
4 | //(possibly not a big gain, but much more fluent in JOP profiler)
5 | public final class KJDigitalSignalProcessor1 implements Runnable {
6 |
7 | KJDigitalSignalProcessingAudioDataConsumer dspadc;
8 |
9 | boolean process = true;
10 |
11 | long lfp = 0;
12 |
13 | int frameSize;
14 |
15 | KJDigitalSignalProcessor1(KJDigitalSignalProcessingAudioDataConsumer aDspadc){
16 | dspadc = aDspadc;
17 | frameSize = dspadc.sourceDataLine.getFormat().getFrameSize();
18 | }
19 |
20 | private int calculateSamplePosition() {
21 |
22 | synchronized( dspadc.readWriteLock ) {
23 |
24 | long wFp = dspadc.sourceDataLine.getLongFramePosition();
25 | long wNfp = lfp;
26 |
27 | lfp = wFp;
28 |
29 | int wSdp = (int)( (long)( wNfp * frameSize ) - (long)( dspadc.audioDataBuffer.length * dspadc.offset ) );
30 |
31 | // KJJukeBox.getDSPDialog().setOutputPositionInfo(
32 | // wFp,
33 | // wFp - wNfp,
34 | // wSdp );
35 |
36 | return wSdp;
37 |
38 | }
39 |
40 | }
41 |
42 | private void processSamples( int pPosition ) {
43 |
44 | int c = pPosition;
45 |
46 | if ( dspadc.channelMode == dspadc.CHANNEL_MODE_MONO && dspadc.sampleType == dspadc.SAMPLE_TYPE_EIGHT_BIT ) {
47 |
48 | for( int a = 0; a < dspadc.sampleSize; a++, c++ ) {
49 |
50 | if ( c >= dspadc.audioDataBuffer.length ) {
51 | dspadc.offset++;
52 | c = ( c - dspadc.audioDataBuffer.length );
53 | }
54 |
55 | dspadc.left[ a ] = (float)( (int)dspadc.audioDataBuffer[ c ] / 128.0f );
56 | dspadc.right[ a ] = dspadc.left[ a ];
57 |
58 | }
59 |
60 | } else if ( dspadc.channelMode == dspadc.CHANNEL_MODE_STEREO && dspadc.sampleType == dspadc.SAMPLE_TYPE_EIGHT_BIT ) {
61 |
62 | for( int a = 0; a < dspadc.sampleSize; a++, c += 2 ) {
63 |
64 | if ( c >= dspadc.audioDataBuffer.length ) {
65 | dspadc.offset++;
66 | c = ( c - dspadc.audioDataBuffer.length );
67 | }
68 |
69 | dspadc.left[ a ] = (float)( (int)dspadc.audioDataBuffer[ c ] / 128.0f );
70 | dspadc.right[ a ] = (float)( (int)dspadc.audioDataBuffer[ c + 1 ] / 128.0f );
71 |
72 | }
73 |
74 | } else if ( dspadc.channelMode == dspadc.CHANNEL_MODE_MONO && dspadc.sampleType == dspadc.SAMPLE_TYPE_SIXTEEN_BIT ) {
75 |
76 | for( int a = 0; a < dspadc.sampleSize; a++, c += 2 ) {
77 |
78 | if ( c >= dspadc.audioDataBuffer.length ) {
79 | dspadc.offset++;
80 | c = ( c - dspadc.audioDataBuffer.length );
81 | }
82 |
83 | dspadc.left[ a ] = (float)( ( (int)dspadc.audioDataBuffer[ c + 1 ] << 8 ) + dspadc.audioDataBuffer[ c ] ) / 32767.0f;;
84 | dspadc.right[ a ] = dspadc.left[ a ];
85 |
86 | }
87 |
88 | } else if ( dspadc.channelMode == dspadc.CHANNEL_MODE_STEREO && dspadc.sampleType == dspadc.SAMPLE_TYPE_SIXTEEN_BIT ) {
89 |
90 | for( int a = 0; a < dspadc.sampleSize; a++, c += 4 ) {
91 |
92 | if ( c >= dspadc.audioDataBuffer.length ) {
93 | dspadc.offset++;
94 | c = ( c - dspadc.audioDataBuffer.length );
95 | }
96 |
97 | dspadc.left[ a ] = (float)( ( (int)dspadc.audioDataBuffer[ c + 1 ] << 8 ) + dspadc.audioDataBuffer[ c ] ) / 32767.0f;
98 | dspadc.right[ a ] = (float)( ( (int)dspadc.audioDataBuffer[ c + 3 ] << 8 ) + dspadc.audioDataBuffer[ c + 2 ] ) / 32767.0f;
99 |
100 | }
101 |
102 | }
103 |
104 | }
105 |
106 | public void run() {
107 | while( process ) {
108 |
109 | try {
110 |
111 | long wStn = System.nanoTime();
112 |
113 | int wSdp = calculateSamplePosition();
114 |
115 | if ( wSdp > 0 ) {
116 | processSamples( wSdp );
117 | }
118 |
119 | // -- Dispatch sample data to digtal signal processors.
120 | for( int a = 0; a < dspadc.dsps.size(); a++ ) {
121 |
122 | // -- Calculate the frame rate ratio hint. This value can be used by
123 | // animated DSP's to fast forward animation frames to make up for
124 | // inconsistencies with the frame rate.
125 | float wFrr = (float)dspadc.fpsAsNS / (float)dspadc.desiredFpsAsNS;
126 |
127 | try {
128 | ( (KJDigitalSignalProcessor)dspadc.dsps.get( a ) ).process( dspadc.left, dspadc.right, wFrr );
129 | } catch( Exception pEx ) {
130 | System.err.println( "-- DSP Exception: " );
131 | pEx.printStackTrace();
132 | }
133 | }
134 |
135 | // KJJukeBox.getDSPDialog().setDSPInformation(
136 | // String.valueOf( 1000.0f / ( (float)( wEtn - wStn ) / 1000000.0f ) ) );
137 |
138 | // System.out.println( 1000.0f / ( (float)( wEtn - wStn ) / 1000000.0f ) );
139 |
140 | long wDelay = dspadc.fpsAsNS - ( System.nanoTime() - wStn );
141 |
142 | // -- No DSP registered? Put the the DSP thread to sleep.
143 | if ( dspadc.dsps.isEmpty() ) {
144 | wDelay = 1000000000; // -- 1 second.
145 | }
146 |
147 | if ( wDelay > 0 ) {
148 |
149 | try {
150 | Thread.sleep( wDelay / 1000000, (int)wDelay % 1000000 );
151 | } catch ( Exception pEx ) {
152 | // TODO Auto-generated catch block
153 | }
154 |
155 | // -- Adjust FPS until we meet the "desired FPS".
156 | if ( dspadc.fpsAsNS > dspadc.desiredFpsAsNS ) {
157 | dspadc.fpsAsNS -= wDelay;
158 | } else {
159 | dspadc.fpsAsNS = dspadc.desiredFpsAsNS;
160 | }
161 |
162 | } else {
163 |
164 | // -- Reduce FPS because we cannot keep up with the "desired FPS".
165 | dspadc.fpsAsNS += -wDelay;
166 |
167 | // -- Keep thread from hogging CPU.
168 | try {
169 | Thread.sleep( 10 );
170 | } catch ( InterruptedException pEx ) {
171 | // TODO Auto-generated catch block
172 | }
173 |
174 | }
175 |
176 | } catch( Exception pEx ) {
177 | System.err.println( "- DSP Exception: " );
178 | pEx.printStackTrace();
179 | }
180 |
181 | }
182 |
183 | }
184 |
185 | public void stop() {
186 | process = false;
187 | }
188 |
189 | }
190 |
--------------------------------------------------------------------------------
/src/kj/dsp/KJFFT.java:
--------------------------------------------------------------------------------
1 | package kj.dsp;
2 |
3 | /**
4 | * @author Kris
5 | *
6 | * TODO To change the template for this generated type comment go to
7 | * Window - Preferences - Java - Code Generation - Code and Comments
8 | */
9 | public class KJFFT {
10 |
11 | private float[] xre;
12 | private float[] xim;
13 | private float[] mag;
14 |
15 | private float[] fftSin;
16 | private float[] fftCos;
17 | private int[] fftBr;
18 |
19 | private int ss, ss2, nu, nu1;
20 |
21 | /**
22 | * @param The amount of the sample provided to the "calculate" method to use during
23 | * FFT calculations.
24 | */
25 | public KJFFT( int pSampleSize ) {
26 |
27 | ss = pSampleSize;
28 | ss2 = ss >> 1;
29 |
30 | xre = new float[ ss ];
31 | xim = new float[ ss ];
32 | mag = new float[ ss2 ];
33 |
34 | nu = (int)( Math.log( ss ) / Math.log( 2 ) );
35 | nu1 = nu - 1;
36 |
37 | prepareFFTTables();
38 |
39 | }
40 |
41 | private int bitrev( int j, int nu ) {
42 |
43 | int j1 = j;
44 | int j2;
45 | int k = 0;
46 |
47 | for( int i = 1; i <= nu; i++ ) {
48 | j2 = j1 >> 1;
49 | k = ( k << 1 ) + j1 - ( j2 << 1 );
50 | j1 = j2;
51 | }
52 |
53 | return k;
54 |
55 | }
56 |
57 |
58 | /**
59 | * @param pSample The sample to compute FFT values on.
60 | * @return The results of the calculation, normalized between 0.0 and 1.0.
61 | */
62 | public float[] calculate( float[] pSample ) {
63 |
64 | int n2 = ss2;
65 | int nu1 = nu - 1;
66 |
67 | int wAps = pSample.length / ss;
68 |
69 | // -- FIXME: This affects the calculation accuracy, because
70 | // is compresses the digital signal. Looks nice on
71 | // the spectrum analyser, as it chops off most of
72 | // sound we cannot hear anyway.
73 | for ( int a = 0, b = 0; a < pSample.length; a += wAps, b++ ) {
74 | xre[ b ] = pSample[ a ];
75 | xim[ b ] = 0.0f;
76 | }
77 |
78 | float tr, ti, c, s;
79 | int k, kn2, x = 0;
80 |
81 | for ( int l = 1; l <= nu; l++ ) {
82 |
83 | k = 0;
84 |
85 | while ( k < ss ) {
86 |
87 | for ( int i = 1; i <= n2; i++ ) {
88 |
89 | // -- Tabled sin/cos
90 | c = fftCos[ x ];
91 | s = fftSin[ x ];
92 |
93 | kn2 = k + n2;
94 |
95 | tr = xre[ kn2 ] * c + xim[ kn2 ] * s;
96 | ti = xim[ kn2 ] * c - xre[ kn2 ] * s;
97 |
98 | xre[ kn2 ] = xre[ k ] - tr;
99 | xim[ kn2 ] = xim[ k ] - ti;
100 | xre[ k ] += tr;
101 | xim[ k ] += ti;
102 |
103 | k++; x++;
104 |
105 | }
106 |
107 | k += n2;
108 |
109 | }
110 |
111 | nu1--;
112 | n2 >>= 1;
113 |
114 | }
115 |
116 | int r;
117 |
118 | // -- Reorder output.
119 | for( k = 0; k < ss; k++ ) {
120 |
121 | // -- Use tabled BR values.
122 | r = fftBr[ k ];
123 |
124 | if ( r > k ) {
125 |
126 | tr = xre[ k ];
127 | ti = xim[ k ];
128 |
129 | xre[ k ] = xre[ r ];
130 | xim[ k ] = xim[ r ];
131 | xre[ r ] = tr;
132 | xim[ r ] = ti;
133 |
134 | }
135 |
136 | }
137 |
138 | // -- Calculate magnitude.
139 | mag[ 0 ] = (float)( Math.sqrt( xre[ 0 ] * xre[ 0 ] + xim[ 0 ] * xim[ 0 ] ) ) / ss;
140 |
141 | for ( int i = 1; i < ss2; i++ ) {
142 | mag[ i ]= 2 * (float)( Math.sqrt( xre[ i ] * xre[ i ] + xim[ i ] * xim[ i ] ) ) / ss;
143 | }
144 |
145 | return mag;
146 |
147 | }
148 |
149 | private void prepareFFTTables() {
150 |
151 | int n2 = ss2;
152 | int nu1 = nu - 1;
153 |
154 | // -- Allocate FFT SIN/COS tables.
155 | fftSin = new float[ nu * n2 ];
156 | fftCos = new float[ nu * n2 ];
157 |
158 | float tr, ti, p, arg;
159 | int k = 0, x = 0;
160 |
161 | // -- Prepare SIN/COS tables.
162 | for ( int l = 1; l <= nu; l++ ) {
163 |
164 | while ( k < ss ) {
165 |
166 | for ( int i = 1; i <= n2; i++ ) {
167 |
168 | p = bitrev( k >> nu1, nu );
169 |
170 | arg = 2 * (float)Math.PI * p / ss;
171 |
172 | fftSin[ x ] = (float)Math.sin( arg );
173 | fftCos[ x ] = (float)Math.cos( arg );
174 |
175 | k++;
176 | x++;
177 |
178 | }
179 |
180 | k += n2;
181 |
182 | }
183 |
184 | k = 0;
185 |
186 | nu1--;
187 | n2 >>= 1;
188 |
189 | }
190 |
191 | // -- Prepare bitrev table.
192 | fftBr = new int[ ss ];
193 |
194 | for( k = 0; k < ss; k++ ) {
195 | fftBr[ k ] = bitrev( k, nu );
196 | }
197 |
198 | }
199 |
200 | }
201 |
--------------------------------------------------------------------------------