0 && ch < 128)
- return (byte) ch;
- else if (ch == 0x401)
- return -88; // Ё
- else if (ch == 0x404)
- return -86; // Є
- else if (ch == 0x407)
- return -81; // Ї
- else if (ch == 0x451)
- return -72; // ё
- else if (ch == 0x454)
- return -70; // є
- else if (ch == 0x457)
- return -65; // ї
- return (byte)((byte)(ch) + 176);
- }
public static char checkCP1251 (char ch)
{
diff --git a/src/com/annimon/Util.java b/src/com/annimon/Util.java
new file mode 100644
index 0000000..0520131
--- /dev/null
+++ b/src/com/annimon/Util.java
@@ -0,0 +1,63 @@
+/*
+ * aNNiMON 2011
+ * For more info visit http://annimon.com/
+ */
+package com.annimon;
+
+import java.util.Calendar;
+import java.util.Random;
+import java.util.Vector;
+import seps.Rms;
+
+/**
+ *
+ * @author aNNiMON
+ */
+public class Util {
+
+ private static final Random rnd = new Random();
+
+ public static boolean checkTime() {
+ Calendar cal = Calendar.getInstance();
+ int ch = cal.get(Calendar.HOUR_OF_DAY);
+ int cm = cal.get(Calendar.MINUTE);
+ if(ch!=Rms.dh) return false;
+ else return (cm>=Rms.dm);
+ }
+
+ public static String getTime() {
+ StringBuffer sb = new StringBuffer();
+ Calendar cal = Calendar.getInstance();
+ int tmp;
+ tmp = cal.get(Calendar.HOUR_OF_DAY);
+ if(tmp<=9) sb.append('0'); sb.append(tmp);
+ sb.append(':');
+ //Минута
+ tmp = cal.get(Calendar.MINUTE);
+ if(tmp<=9) sb.append('0'); sb.append(tmp);
+ return sb.toString();
+ }
+
+ public static int random(int min, int max) {
+ return min + rnd.nextInt(max+1-min);
+ }
+
+ public static String[] splitString(String str, String delim) {
+ if (str.equals("") || delim == null || delim.length() == 0) return new String[]{str};
+ String[] s;
+ Vector v = new Vector();
+ int pos = 0;
+ int newpos = str.indexOf(delim, 0);
+
+ while (newpos != -1) {
+ v.addElement(str.substring(pos, newpos));
+ pos = newpos + delim.length();
+ newpos = str.indexOf(delim, pos);
+ }
+ v.addElement(str.substring(pos));
+
+ s = new String[v.size()];
+ v.copyInto(s);
+ return s;
+ }
+}
diff --git a/src/fx/AnimatedImage.java b/src/fx/AnimatedImage.java
new file mode 100644
index 0000000..fb12d67
--- /dev/null
+++ b/src/fx/AnimatedImage.java
@@ -0,0 +1,51 @@
+package fx;
+
+import javax.microedition.lcdui.Graphics;
+import javax.microedition.lcdui.Image;
+
+public class AnimatedImage {
+
+ ImageFx fx;
+ Image image;
+ int imageWidth;
+ int imageHeight;
+
+ public AnimatedImage(Image image) {
+ fx = null;
+ this.image = null;
+ imageWidth = 0;
+ imageHeight = 0;
+ this.image = image;
+ imageWidth = image.getWidth();
+ imageHeight = image.getHeight();
+ }
+
+ public void setFx(ImageFx fx) {
+ this.fx = fx;
+ }
+
+ public void start(long duration) {
+ fx.start(duration);
+ }
+
+ public boolean isEnded() {
+ return fx.isEnded();
+ }
+
+ public void paint(Graphics g, int x, int y, int constraints) {
+ if (fx == null) {
+ g.drawImage(image, x, y, constraints);
+ } else {
+ int cx = g.getClipX();
+ int cy = g.getClipY();
+ int cw = g.getClipWidth();
+ int ch = g.getClipHeight();
+ int translateX = (constraints & 8) <= 0 ? (constraints & 1) <= 0 ? x : x - imageWidth / 2 : x - imageWidth;
+ int translateY = (constraints & 0x20) <= 0 ? (constraints & 2) <= 0 ? y : y - imageHeight / 2 : y - imageHeight;
+ g.translate(translateX, translateY);
+ fx.paint(g, image);
+ g.translate(-translateX, -translateY);
+ g.setClip(cx, cy, cw, ch);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/fx/BlindsFx.java b/src/fx/BlindsFx.java
new file mode 100644
index 0000000..b74b647
--- /dev/null
+++ b/src/fx/BlindsFx.java
@@ -0,0 +1,36 @@
+package fx;
+
+import javax.microedition.lcdui.Graphics;
+import javax.microedition.lcdui.Image;
+
+public class BlindsFx extends ImageFx {
+
+ int blinds;
+
+ public BlindsFx(int blinds, int type, int orientation) {
+ this.blinds = blinds;
+ setOrientation(orientation);
+ setFxType(type);
+ assertNotOrientation(0);
+ assertNotFxType(0);
+ }
+
+ protected void paintFx(Graphics g, Image image, long timeDiff) {
+ int perc = getPercentage(timeDiff);
+ int orientation = getOrientation();
+ int imageSize = orientation != 2 ? image.getWidth() : image.getHeight();
+ int pieceSize = imageSize / blinds;
+ int delta = imageSize - pieceSize * blinds;
+ int coord = 0;
+ for (int i = 0; i < blinds; i++) {
+ int size = ((pieceSize + (i >= delta ? 0 : 1)) * (100 - perc)) / 100;
+ if (orientation == 2) {
+ g.setClip(0, coord, image.getWidth(), size);
+ } else {
+ g.setClip(coord, 0, size, image.getHeight());
+ }
+ g.drawImage(image, 0, 0, 20);
+ coord += pieceSize + (i >= delta ? 0 : 1);
+ }
+ }
+}
diff --git a/src/fx/ImageFx.java b/src/fx/ImageFx.java
new file mode 100644
index 0000000..285021a
--- /dev/null
+++ b/src/fx/ImageFx.java
@@ -0,0 +1,119 @@
+package fx;
+
+//~--- JDK imports ------------------------------------------------------------
+import javax.microedition.lcdui.Graphics;
+import javax.microedition.lcdui.Image;
+
+public abstract class ImageFx {
+
+ public static final int ORIENTATION_NONE = 0;
+ public static final int ORIENTATION_VERTICAL = 1;
+ public static final int ORIENTATION_HORIZONTAL = 2;
+ public static final int TYPE_NONE = 0;
+ public static final int TYPE_IN = 1;
+ public static final int TYPE_OUT = 2;
+ private int direction;
+ private long duration;
+ private boolean ended;
+ private int fxType;
+ private boolean looping;
+ private int orientation;
+ private boolean running;
+ private long startTime;
+
+ public ImageFx() {
+ fxType = TYPE_NONE;
+ orientation = ORIENTATION_NONE;
+ direction = 2;
+ looping = false;
+ running = false;
+ ended = false;
+ duration = 0L;
+ startTime = 0L;
+ }
+
+ public void start(long millisecs) {
+ duration = millisecs;
+ startTime = System.currentTimeMillis();
+ ended = false;
+ running = true;
+ }
+
+ public void setOrientation(int orientation) {
+ if ((orientation == ORIENTATION_HORIZONTAL) || (orientation == ORIENTATION_VERTICAL)
+ || (orientation == ORIENTATION_NONE)) {
+ this.orientation = orientation;
+ }
+ }
+
+ public void setFxType(int fxType) {
+ if ((fxType == TYPE_IN) || (fxType == TYPE_OUT) || (fxType == TYPE_NONE)) {
+ this.fxType = fxType;
+ }
+ }
+
+ public void setDirection(int direction) {
+ if ((direction == 1) || (direction == 5) || (direction == 6) || (direction == 2)) {
+ this.direction = direction;
+ }
+ }
+
+ protected void assertNotFxType(int value) {
+ if (fxType != value) {
+ return;
+ }
+ }
+
+ protected void assertNotOrientation(int value) {
+ if (orientation != value) {
+ return;
+ }
+ }
+
+ public int getOrientation() {
+ return orientation;
+ }
+
+ public int getDirection() {
+ return direction;
+ }
+
+ public void paint(Graphics g, Image image) {
+ if (!running) {
+
+ // if(mustNotPaint())
+ // return;
+ // if(mustFullyPaint())
+ g.drawImage(image, 0, 0, 20);
+ } else {
+ long timeDiff = System.currentTimeMillis() - startTime;
+
+ if (timeDiff > duration) {
+ if (looping) {
+ timeDiff -= duration;
+ startTime += duration;
+ } else {
+ timeDiff = duration;
+ ended = true;
+ running = false;
+ }
+ }
+
+ if (fxType == TYPE_IN) {
+ timeDiff = duration - timeDiff;
+ }
+
+ paintFx(g, image, timeDiff);
+ }
+ }
+
+ protected int getPercentage(long timeDiff) {
+ return (int) ((100L * timeDiff) / duration);
+ }
+
+ public boolean isEnded() {
+ return ended;
+ }
+
+ protected abstract void paintFx(Graphics g, Image image, long l);
+}
diff --git a/src/fx/PuzzleFx.java b/src/fx/PuzzleFx.java
new file mode 100644
index 0000000..e58de69
--- /dev/null
+++ b/src/fx/PuzzleFx.java
@@ -0,0 +1,71 @@
+package fx;
+
+import java.util.Random;
+import javax.microedition.lcdui.Graphics;
+import javax.microedition.lcdui.Image;
+
+public class PuzzleFx extends ImageFx {
+
+ int vPieces;
+ int hPieces;
+ int[] pieceOrder;
+ long pieceDelay;
+ long pieceDuration;
+
+ public PuzzleFx(int hPieces, int vPieces, int type) {
+ this.vPieces = 4;
+ this.hPieces = 8;
+ pieceOrder = null;
+ pieceDelay = 0L;
+ pieceDuration = 0L;
+ int normalizedType = type != 1 ? type != 2 ? type : 1 : 2;
+ setFxType(normalizedType);
+ assertNotFxType(0);
+ this.hPieces = hPieces;
+ this.vPieces = vPieces;
+ Random rand = new Random();
+ pieceOrder = new int[hPieces * vPieces];
+ for (int i = 0; i < pieceOrder.length; i++) {
+ pieceOrder[i] = -1;
+ }
+
+ for (int i = 0; i < pieceOrder.length; i++) {
+ int next;
+ for (next = rand.nextInt(pieceOrder.length); pieceOrder[next] != -1; next = (next + 1) % pieceOrder.length);
+ pieceOrder[next] = i;
+ }
+
+ }
+
+ public void start(long millisecs) {
+ super.start(millisecs);
+ pieceDuration = millisecs / 8L;
+ pieceDelay = (millisecs - pieceDuration) / (long) (hPieces * vPieces);
+ }
+
+ protected void paintFx(Graphics g, Image image, long timeDiff) {
+ int imageWidth = image.getWidth();
+ int imageHeight = image.getHeight();
+ int pieceWidth = imageWidth / hPieces;
+ int pieceHeight = imageHeight / vPieces;
+ for (int i = 0; i < hPieces; i++) {
+ for (int j = 0; j < vPieces; j++) {
+ int index = i * vPieces + j;
+ int w = pieceWidth;
+ int h = pieceHeight;
+ long delta = timeDiff - (long) pieceOrder[index] * pieceDelay;
+ if (delta >= 0L) {
+ if (delta - pieceDuration < 0L) {
+ int perc = (int) ((delta * 100L) / pieceDuration);
+ w = (pieceWidth * perc) / 100;
+ h = (pieceHeight * perc) / 100;
+ }
+ g.setClip(i * pieceWidth + (pieceWidth - w) / 2, j * pieceHeight + (pieceHeight - h) / 2, w, h);
+ g.drawImage(image, 0, 0, 20);
+ }
+ }
+
+ }
+
+ }
+}
diff --git a/src/fx/Slide2Fx.java b/src/fx/Slide2Fx.java
new file mode 100644
index 0000000..a5eca65
--- /dev/null
+++ b/src/fx/Slide2Fx.java
@@ -0,0 +1,43 @@
+package fx;
+
+import javax.microedition.lcdui.Graphics;
+import javax.microedition.lcdui.Image;
+
+public class Slide2Fx extends ImageFx {
+
+ public Slide2Fx(int direction, int fxType) {
+ setDirection(direction);
+ setFxType(fxType);
+ assertNotFxType(0);
+ }
+
+ protected void paintFx(Graphics g, Image image, long timeDiff) {
+ int perc = getPercentage(timeDiff);
+ int x = 0;
+ int y = 0;
+ int w = image.getWidth();
+ int h = image.getHeight();
+ switch (getDirection()) {
+ case 1: // '\001'
+ h = (h * (100 - perc)) / 100;
+ y = image.getHeight() - h;
+ break;
+
+ case 6: // '\006'
+ h = (h * (100 - perc)) / 100;
+ y = h - image.getHeight();
+ break;
+
+ case 5: // '\005'
+ w = (w * (100 - perc)) / 100;
+ x = image.getWidth() - w;
+ break;
+
+ case 2: // '\002'
+ w = (w * (100 - perc)) / 100;
+ x = w - image.getWidth();
+ break;
+ }
+ g.drawImage(image, x, y, 20);
+ }
+}
diff --git a/src/fx/SlideFx.java b/src/fx/SlideFx.java
new file mode 100644
index 0000000..db4888f
--- /dev/null
+++ b/src/fx/SlideFx.java
@@ -0,0 +1,67 @@
+package fx;
+
+import javax.microedition.lcdui.Graphics;
+import javax.microedition.lcdui.Image;
+
+public class SlideFx extends ImageFx {
+
+ int pieces;
+ long singleSlideDuration;
+
+ public SlideFx(int pieces, int slideType, int direction) {
+ this.pieces = 4;
+ singleSlideDuration = 0L;
+ setDirection(direction);
+ setFxType(slideType);
+ assertNotFxType(0);
+ this.pieces = pieces;
+ }
+
+ public void start(long millisecs) {
+ super.start(millisecs);
+ singleSlideDuration = millisecs / (long) pieces;
+ }
+
+ protected void paintFx(Graphics g, Image image, long timeDiff) {
+ int cx = g.getClipX();
+ int cy = g.getClipY();
+ int cw = g.getClipWidth();
+ int ch = g.getClipHeight();
+ int imageHeight = image.getHeight();
+ int imageWidth = image.getWidth();
+ int direction = getDirection();
+ int pieceEnd = 0;
+ int pieceCoord = 0;
+ int pieceSize = direction != 2 && direction != 5 ? imageWidth / pieces : imageHeight / pieces;
+ switch (direction) {
+ case 2: // '\002'
+ pieceEnd = cx - imageWidth;
+ break;
+
+ case 5: // '\005'
+ pieceEnd = cx + cw;
+ break;
+
+ case 1: // '\001'
+ pieceEnd = cy - imageHeight;
+ break;
+
+ case 6: // '\006'
+ pieceEnd = cy + ch;
+ break;
+ }
+ for (int i = 0; i < pieces; i++) {
+ if (timeDiff <= (long) (i + 1) * singleSlideDuration) {
+ pieceCoord = (int) (timeDiff >= (long) i * singleSlideDuration ? ((long) pieceEnd * (timeDiff - (long) i * singleSlideDuration)) / singleSlideDuration : 0L);
+ if (direction == 2 || direction == 5) {
+ g.setClip(pieceCoord, i * pieceSize, imageWidth, pieceSize);
+ g.drawImage(image, pieceCoord, 0, 20);
+ } else {
+ g.setClip(i * pieceSize, pieceCoord, pieceSize, imageHeight);
+ g.drawImage(image, 0, pieceCoord, 20);
+ }
+ }
+ }
+
+ }
+}
diff --git a/src/fx/WaveFx.java b/src/fx/WaveFx.java
new file mode 100644
index 0000000..cb2da8c
--- /dev/null
+++ b/src/fx/WaveFx.java
@@ -0,0 +1,60 @@
+package fx;
+
+import javax.microedition.lcdui.Graphics;
+import javax.microedition.lcdui.Image;
+
+public class WaveFx extends ImageFx
+{
+ int pieces;
+ int maxShift;
+ long pieceDuration;
+ long pieceDelay;
+
+ public WaveFx(int pieces, int maxShift, int orientation)
+ {
+ this.pieces = 0;
+ this.maxShift = 0;
+ pieceDuration = 0L;
+ pieceDelay = 0L;
+ setOrientation(orientation);
+ this.pieces = pieces;
+ this.maxShift = maxShift;
+ }
+
+ public void start(long millisecs)
+ {
+ super.start(millisecs);
+ pieceDuration = millisecs / 2L;
+ pieceDelay = (millisecs - pieceDuration) / (long)pieces;
+ }
+
+ protected void paintFx(Graphics g, Image image, long timeDiff)
+ {
+ int imageWidth = image.getWidth();
+ int imageHeight = image.getHeight();
+ int pieceSize = (getOrientation() != 2 ? image.getWidth() : image.getHeight()) / pieces;
+ int shift = 0;
+ for(int i = 0; i < pieces; i++)
+ {
+ long delta = (long)i * pieceDelay - timeDiff;
+ if(delta > 0L || delta + pieceDuration <= 0L)
+ {
+ shift = 0;
+ } else
+ {
+ long perc = (delta * 100L) / pieceDuration;
+ shift = (int)((double)maxShift * Math.sin(((double)(perc * 2L) * 3.1415926535897931D) / 100D));
+ }
+ if(getOrientation() == 2)
+ {
+ g.setClip(0 + shift, i * pieceSize, imageWidth, pieceSize);
+ g.drawImage(image, 0 + shift, 0, 20);
+ } else
+ {
+ g.setClip(i * pieceSize, 0 + shift, pieceSize, imageHeight);
+ g.drawImage(image, 0, 0 + shift, 20);
+ }
+ }
+
+ }
+}
diff --git a/src/fx/WipeFx.java b/src/fx/WipeFx.java
new file mode 100644
index 0000000..8470f3d
--- /dev/null
+++ b/src/fx/WipeFx.java
@@ -0,0 +1,46 @@
+package fx;
+
+import javax.microedition.lcdui.Graphics;
+import javax.microedition.lcdui.Image;
+
+public class WipeFx extends ImageFx
+{
+
+ public WipeFx(int direction, int fxType)
+ {
+ setDirection(direction);
+ setFxType(fxType);
+ assertNotFxType(0);
+ }
+
+ protected void paintFx(Graphics g, Image image, long timeDiff)
+ {
+ int perc = getPercentage(timeDiff);
+ int x = 0;
+ int y = 0;
+ int w = image.getWidth();
+ int h = image.getHeight();
+ switch(getDirection())
+ {
+ case 1: // '\001'
+ h = (h * (100 - perc)) / 100;
+ y = image.getHeight() - h;
+ break;
+
+ case 6: // '\006'
+ h = (h * (100 - perc)) / 100;
+ break;
+
+ case 5: // '\005'
+ w = (w * (100 - perc)) / 100;
+ x = image.getWidth() - w;
+ break;
+
+ case 2: // '\002'
+ w = (w * (100 - perc)) / 100;
+ break;
+ }
+ g.setClip(x, y, w, h);
+ g.drawImage(image, 0, 0, 20);
+ }
+}
diff --git a/src/icon.png b/src/icon.png
deleted file mode 100644
index b0e1f4c..0000000
Binary files a/src/icon.png and /dev/null differ
diff --git a/src/lastfm/HTTPUtil.java b/src/lastfm/HTTPUtil.java
new file mode 100644
index 0000000..bc9eef2
--- /dev/null
+++ b/src/lastfm/HTTPUtil.java
@@ -0,0 +1,264 @@
+/**
+ * HTTPUtil.java
+ *
+ * This program is distributed under the terms of the GNU General Public
+ * License
+ * Copyright 2008 NJ Pearman
+ *
+ * This file is part of MobScrob.
+ *
+ * MobScrob is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MobScrob is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MobScrob. If not, see .
+ */
+package lastfm;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.Enumeration;
+import java.util.Vector;
+
+import javax.microedition.io.Connector;
+import javax.microedition.io.HttpConnection;
+
+/**
+ * @author Neill
+ *
+ */
+public class HTTPUtil {
+
+ private static final String ENC_UTF8 = "UTF-8";
+
+ /**
+ * Returns a Vector of Strings representing the lines present in the byte
+ * array, separated by '\n' return feed.
+ *
+ * @param bytes
+ * @return
+ */
+ public static Vector readLines(byte[] bytes) {
+ Vector lines = new Vector();
+ if (bytes == null || bytes.length == 0) {
+ return lines;
+ }
+ StringBuffer line = new StringBuffer();
+ for (int i = 0; i < bytes.length; i++) {
+ if (bytes[i] == '\n') {
+ lines.addElement(line.toString());
+ line = new StringBuffer();
+ } else {
+ // add to current line
+ line.append((char) bytes[i]);
+ }
+ }
+
+ return lines;
+ }
+
+ /**
+ * Encodes a parameter, also ensuring that it is UTF-8
+ *
+ * @param s
+ * @return
+ * @throws UnsupportedEncodingException
+ */
+ public static String encodeParam(String s) {
+ if (s == null) return null;
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0; i < s.length(); i++) {
+ char ch = s.charAt(i);
+ switch (ch) {
+ default:
+ if (ch < '\200') {
+ sb.append(ch);
+ break;
+ }
+ if (ch > '\177' && ch < '\u0800') {
+ sb.append('%');
+ sb.append(Integer.toHexString((ch >> 6 | 0xc0) + 256).substring(1));
+ sb.append('%');
+ sb.append(Integer.toHexString((ch & 0x3f | 0x80) + 256).substring(1));
+ break;
+ }
+ if (ch > '\u07FF' && ch < '\0') {
+ sb.append('%');
+ sb.append(Integer.toHexString((ch >> 12 | 0xe0) + 256).substring(1));
+ sb.append('%');
+ sb.append(Integer.toHexString((ch >> 6 & 0x3f | 0x80) + 256).substring(1));
+ sb.append('%');
+ sb.append(Integer.toHexString((ch & 0x3f | 0x80) + 256).substring(1));
+ }
+ break;
+ case 0: //'\0'
+ case 32: sb.append("%20"); break;// ' '
+ case 61: sb.append("%3d"); break;// '='
+ case 43: sb.append("%2b"); break;// '+'
+ case 39: sb.append("%27"); break;// '\''
+ case 46: sb.append("%2E"); break;// '.'
+ case 60: sb.append("%3c"); break;// '<'
+ case 62: sb.append("%3e"); break;// '>'
+ case 35: sb.append("%23"); break;// '#'
+ case 37: sb.append("%25"); break;// '%'
+ case 38: sb.append("%26"); break;// '&'
+ case 123:sb.append("%7b"); break;// '{'
+ case 125:sb.append("%7d"); break;// '}'
+ case 92: sb.append("%5c"); break;// '\\'
+ case 94: sb.append("%5e"); break;// '^'
+ case 126:sb.append("%73"); break;// '~'
+ case 91: sb.append("%5b"); break;// '['
+ case 93: sb.append("%5d"); break;// ']'
+ case 58: sb.append("%3A"); break;// ':'
+ case 47: sb.append("%2F"); break;// '/'
+ case 63: sb.append("%3F"); break;// '?'
+ case 45: sb.append("%2D"); break;// '-'
+ case 33: sb.append("%21"); break;// '!'
+ case 59: sb.append("%3B"); break;// ';'
+ }
+ }
+ return sb.toString();
+ /*if (s == null) {
+ return s;
+ }
+
+ // encode as UTF-8
+ String utf8Str;
+ try {
+ utf8Str = new String(s.getBytes(), ENC_UTF8);
+ } catch (UnsupportedEncodingException ex) {
+ utf8Str = s;
+ }
+
+ StringBuffer sb = new StringBuffer(utf8Str.length() * 3);
+ char[] chars = utf8Str.toCharArray();
+ int next;
+
+ // encode the chars in the UTF-8 String
+ for (int i = 0; i < chars.length; i++) {
+ next = chars[i];
+
+ if ((next >= 0x30 && next <= 0x39) || // 0-9
+ (next >= 0x41 && next <= 0x5A) || // A-Z
+ (next >= 0x61 && next <= 0x7A)) { // a-z
+ sb.append((char) next);
+ } else if ((next == 0xA0)) { // ' ' (whitespace)
+ sb.append('+');
+ } else { // encode all other chars
+ sb.append("%");
+ if (next <= 0xf) {
+ sb.append("0");
+ }
+ sb.append(Integer.toHexString(next));
+ }
+ }
+ return sb.toString();*/
+ }
+
+ /**
+ * Attempts to open a URL using the GET method over HTTP and read the
+ * response into a byte array. Any IOExceptions are simply thrown out of
+ * this method to be caught elsewhere.
+ *
+ * @param url
+ * @return
+ * @throws IOException
+ */
+ public static byte[] getUrl(String url, String headerHostname) throws IOException {
+ HttpConnection conn = null;
+ try {
+ conn = (HttpConnection) Connector.open(url);
+
+ // set the compulsory HTTP/1.1 Host: header, as GET
+ conn.setRequestMethod(HttpConnection.GET);
+ //if(!headerHostname.equals(""))
+ conn.setRequestProperty("Host", headerHostname);
+
+ byte[] body = readHttpResponse(conn);
+ return body;
+ } finally {
+ closeHttpConnection(conn);
+ }
+ }
+
+ /**
+ * Reads the response from the specified HTTP connection into a byte array.
+ *
+ * @param conn
+ * @return
+ * @throws IOException
+ */
+ public static byte[] readHttpResponse(HttpConnection conn) throws IOException {
+ int rc = conn.getResponseCode();
+ if (rc != HttpConnection.HTTP_OK) {
+ String msg = "HTTP response code not OK: " + rc;
+ throw new IOException(msg);
+ }
+
+ // connect
+ int len = (int) conn.getLength();
+
+ InputStream is = null;
+
+ try {
+ is = conn.openInputStream();
+
+ // read response
+ if (len > -1) {
+ byte[] body = new byte[len];
+ int actual = 0;
+ int bytesread = 0;
+
+ while ((bytesread != len) && (actual != -1)) {
+ actual = is.read(body, bytesread, len - bytesread);
+ bytesread += actual;
+ }
+ // do something
+ return body;
+ } else {
+ // read byte by byte...?
+
+ Vector bytes = new Vector();
+ Byte byteObj;
+ int next;
+ while ((next = is.read()) > -1) {
+ byteObj = new Byte((byte) next);
+ bytes.addElement(byteObj);
+ }
+
+ byte[] body = new byte[bytes.size()];
+ Enumeration e = bytes.elements();
+ int i = 0;
+ while (e.hasMoreElements()) {
+ byteObj = (Byte) e.nextElement();
+ body[i++] = byteObj.byteValue();
+ }
+
+ return body;
+ }
+ } finally {
+ if (is != null) {
+ try {
+ is.close();
+ } catch (Exception e) {
+ }
+ }
+ }
+ }
+
+ public static void closeHttpConnection(HttpConnection conn) {
+ if (conn != null) {
+ try {
+ conn.close();
+ } catch (Exception e) {}
+ }
+ }
+}
diff --git a/src/lastfm/LastFMScrobbler.java b/src/lastfm/LastFMScrobbler.java
new file mode 100644
index 0000000..d157842
--- /dev/null
+++ b/src/lastfm/LastFMScrobbler.java
@@ -0,0 +1,345 @@
+/**
+ * LastFMScrobbler.java
+ *
+ * This program is distributed under the terms of the GNU General Public
+ * License
+ * Copyright 2008 NJ Pearman
+ *
+ * This file is part of MobScrob.
+ *
+ * MobScrob is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MobScrob is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MobScrob. If not, see .
+ */
+package lastfm;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Vector;
+
+import javax.microedition.io.Connector;
+import javax.microedition.io.HttpConnection;
+import msapi.Track;
+
+/**
+ * Скробблинг LastFM
+ * @author Neill. Modding by aNNiMON
+ */
+public class LastFMScrobbler {
+
+ /** Имя пользователя */
+ private String login;
+ /** Кодированный пароль MD5 */
+ private String passwordMD5;
+ /** ID клиента (tst) */
+ private String clientId;
+ /** версия клиента (1.0) */
+ private String clientVersion;
+
+ /** Класс сессии*/
+ private Session session;
+ /** Число ошибок*/
+ private int failureCount;
+ /** Состояния (работа, завершение) */
+ private boolean processing, shutdown;
+
+ /**
+ * Конфигурация клиента отправителя
+ * @param clientId ID клиента (tst)
+ * @param clientVersion версия клиента (1.0)
+ * @param login имя пользователя
+ * @param passwordMD5 кодированный пароль MD5
+ */
+ public LastFMScrobbler(String clientId, String clientVersion, String login, String passwordMD5) {
+ this.clientId = clientId;
+ this.clientVersion = clientVersion;
+ this.login = login.toLowerCase();
+ this.passwordMD5 = passwordMD5;
+ this.failureCount = 0;
+ }
+
+ /**
+ * Кодирование строки в MD5-хэш
+ * @param string строка
+ * @return String хэшированная строка
+ */
+ public static String md5(String string) {
+ return MD5.getHashString(string);
+ }
+
+ /**
+ * "Рукопожатие". Используется для получение сессии.
+ * Используется протокол 1.2.1
+ * @return true процесс завершен успешно
+ * @throws IOException
+ */
+ public boolean handshake() throws Exception {
+ //Штамп времени
+ long timestamp = System.currentTimeMillis() / 1000;
+ //создаём ссылку handshake
+ StringBuffer urlSB = new StringBuffer();
+
+ urlSB.append("http://post.audioscrobbler.com/?hs=true&p=1.2.1&c=").append(clientId)
+ .append("&v=").append(clientVersion).append("&u=").append(login)
+ .append("&t=").append(timestamp).append("&a=").append( md5(passwordMD5 + timestamp) );
+ String url = urlSB.toString();
+
+ //подключаемся по URL и получаем ответ
+ byte[] answer = HTTPUtil.getUrl(url, "post.audioscrobbler.com");
+ //Считываем строки
+ Vector lines = HTTPUtil.readLines(answer);
+ //Первая строка - состояние (OK, BANNED, BADAUTH, BADTIME, FAILED)
+ String ok = (String) lines.elementAt(0);
+ if(ok.equals("OK")) {
+ //Получаем остальные строки
+ //ID сессии 17E61...
+ String sessionID = (String) lines.elementAt(1);
+ //Ссылка для nowPlaying http://post.audioscrobbler.com:80/np_1.2
+ String nowPlayingUrl = (String) lines.elementAt(2);
+ //Ссылка для скробблинга трека http://post2.audioscrobbler.com:80/protocol_1.2
+ String submitUrl = (String) lines.elementAt(3);
+ //Инициализируем сессию
+ session = new Session(sessionID, nowPlayingUrl, submitUrl);
+ }else throw new Exception(ok);
+ return true;
+ }
+
+ /**
+ * Выполнить скробблинг
+ * @param track трек для скробблинга
+ * @param startTime время начала воспроизведения
+ */
+ public void scrobble(Track track, long startTime) throws Exception {
+ HttpConnection http = null;
+ OutputStream os = null;
+
+ try {
+ if (!validSession()) throw new Exception("Невозможно выполнить handshake");
+
+ processing = true;
+ //Получение данных трека для скробблинга
+ byte[] param = createSubmissionParams(track, startTime);
+
+ //Получение ссылки для выполнения скробблинга
+ String submitUrl = session.submitUrl;
+ //Вырезка из ссылки хоста (без порта и http://)
+ String host = submitUrl.substring(7, submitUrl.lastIndexOf(':'));
+ //Подключение
+ http = (HttpConnection) Connector.open(session.submitUrl);
+ //Конфигурация подключения
+ http.setRequestMethod(HttpConnection.POST);
+ http.setRequestProperty("Host", host);
+ //http.setRequestProperty("User-Agent", "SEPlayerService");
+ http.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
+ http.setRequestProperty("Content-Length", String.valueOf(param.length));
+ http.setRequestProperty("Accept", "*/*");
+ http.setRequestProperty("Accept-Language", "en");
+
+ //Открытие потока для записи
+ os = http.openOutputStream();
+
+ //Запись данных
+ for (int i = 0; i < param.length; i++) {
+ os.write((int) param[i]);
+ }
+
+ //Получение ответа от сервера
+ byte[] answer = HTTPUtil.readHttpResponse(http);
+ String responseStatus = new String(answer);
+ failureCount = 0;
+ //Неверная сессия
+ if (responseStatus.indexOf("BADSESSION") >= 0) {
+ session.invalidate();
+ }
+ } catch (IOException ex) {
+ failureCount++;
+ String msg = "Ошибка скробблинга: " + ex.getMessage();
+ if (failureCount > 2) {
+ session.invalidate();
+ failureCount = 0;
+ }
+ throw new Exception(msg);
+ } finally {
+ if (os != null) {
+ try {
+ os.close();
+ } catch (Exception e) {}
+ }
+ HTTPUtil.closeHttpConnection(http);
+ processing = false;
+ }
+ }
+
+ /**
+ * Завершение работы скробблера
+ */
+ public void shutdown() {
+ shutdown = true;
+ try {
+ while (processing) {
+ //Если выполняется скробблинг - ждём его завершения
+ Thread.sleep(5000);
+ }
+ } catch (InterruptedException e) {}
+ }
+
+ /**
+ * Получение данных трека для скроббблинга
+ * @param track трек для скробблинга
+ * @param startTime время начала воспроизведения
+ * @return массив байт запроса
+ */
+ private byte[] createSubmissionParams(Track track, long startTime) {
+ StringBuffer param = new StringBuffer();
+ //ID сессии
+ param.append("s=").append(HTTPUtil.encodeParam(session.sessionID)).append('&');
+ //Исполнитель
+ param.append("a%5b0%5d=").append(HTTPUtil.encodeParam(track.getArtist())).append('&');
+ //Название трека
+ param.append("t%5b0%5d=").append(HTTPUtil.encodeParam(track.getTitle())).append('&');
+ //Времени начала воспроизведения
+ param.append("i%5b0%5d=").append(startTime).append('&');
+ //Ключ рекомендации
+ param.append("o%5b0%5d=P&");
+ //Рейтинг
+ param.append("r%5b0%5d=&");
+ //Длина трека в секундах
+ param.append("l%5b0%5d=").append((int)track.getDuration()).append('&');
+ //Альбом
+ param.append("b%5b0%5d=").append(HTTPUtil.encodeParam(track.getAlbum())).append('&');
+ //Номер трека
+ param.append("n%5b0%5d=&");//.append(track.getNumber()).append("");
+ //MusicBrainz Track ID
+ param.append("m%5b0%5d=");
+ //Кодируем URL
+ String params = param.toString();
+ byte[] paramBytes = params.getBytes();
+
+ return paramBytes;
+ }
+
+ /**
+ * Проверка правильности сессии
+ * @return true - сессия валидна
+ */
+ private boolean validSession() {
+ if (session == null || session.invalid()) {
+ while ((session == null || session.invalid()) && !shutdown) {
+ int retryTime = (session == null) ? 0 : session.getRetryWaitTime();
+ //Ожидание до следующего handshake
+ //Ожидание 5 секунд при неуспешности
+ try {
+ Thread.sleep(retryTime);
+ } catch (Exception e) {}
+
+ try {
+ if (handshake()) {
+ session.resetWaitTime();
+ break;
+ }
+ } catch (Exception ex) {
+ if (session == null) {
+ session = new Session();
+ }
+ session.increaseWaitTime();
+ }
+ }
+
+ if (session == null || session.invalid()) {
+ //Handshake не выполнен, невозможно заскробблить
+ return false;
+ }
+ }
+ //Сессия валидна
+ return true;
+ }
+
+ /**
+ * Сессия подключения
+ * @author Neill
+ */
+ private static class Session {
+
+ private static final int ONE_MINUTE = 60 * 1000;
+ private static final int MAX_RETRY = 120 * ONE_MINUTE;
+
+ private final String sessionID;
+ private final String nowPlayingUrl;
+ private final String submitUrl;
+ private int retryWaitTime;
+ private boolean invalid;
+
+ /**
+ * Создаёт неправильную сессию с пустыми значениями
+ */
+ public Session() {
+ this(null, null, null);
+ invalid = true;
+ }
+
+ /**
+ * Создаёт сессию со значениями
+ * @param sessionID ID сессии
+ * @param nowPlayingUrl ссылка для nowPlaying
+ * @param submitUrl ссылка для скробблинга
+ */
+ public Session(String sessionID, String nowPlayingUrl, String submitUrl) {
+ this.sessionID = sessionID;
+ this.nowPlayingUrl = nowPlayingUrl;
+ this.submitUrl = submitUrl;
+ this.retryWaitTime = 0;
+ invalid = false;
+ }
+
+ /**
+ * Проверка валидности сессии
+ * @return true сессия неверная
+ */
+ public boolean invalid() {
+ return invalid;
+ }
+
+ /**
+ * Изменение состояния валидности
+ * сессии на неверную
+ */
+ public void invalidate() {
+ invalid = true;
+ }
+
+ /**
+ * Получение времени ожидания реконнекта
+ * @return время в миллисекундах
+ */
+ public int getRetryWaitTime() {
+ return retryWaitTime;
+ }
+
+ /**
+ * Увеличить время ожидания
+ */
+ public void increaseWaitTime() {
+ if (retryWaitTime == 0) {
+ retryWaitTime = ONE_MINUTE;
+ } else if (retryWaitTime < MAX_RETRY) {
+ retryWaitTime *= 2;
+ }
+ }
+
+ /**
+ * Сброс времени ожидания
+ */
+ public void resetWaitTime() {
+ retryWaitTime = 0;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/mobscrob/scrobbler/MD5.java b/src/lastfm/MD5.java
similarity index 76%
rename from src/mobscrob/scrobbler/MD5.java
rename to src/lastfm/MD5.java
index 398f80c..8c9cc5b 100644
--- a/src/mobscrob/scrobbler/MD5.java
+++ b/src/lastfm/MD5.java
@@ -22,7 +22,7 @@
* You should have received a copy of the GNU General Public License
* along with MobScrob. If not, see .
*/
-package mobscrob.scrobbler;
+package lastfm;
import java.io.IOException;
import java.io.InputStream;
@@ -79,88 +79,6 @@ public class MD5 {
return toHex(this.getHash());
}
- /**
- * Gets the MD5 hash of the given byte array.
- *
- * @param b byte array for which an MD5 hash is desired.
- * @return Array of 16 bytes, the hash of all updated bytes.
- *
- * @since ostermillerutils 1.00.00
- */
- public static byte[] getHash(byte[] b) {
- MD5 md5 = new MD5();
- md5.update(b);
- return md5.getHash();
- }
-
- /**
- * Gets the MD5 hash of the given byte array.
- *
- * @param b byte array for which an MD5 hash is desired.
- * @return 32-character hex representation the data's MD5 hash.
- *
- * @since ostermillerutils 1.00.00
- */
- public static String getHashString(byte[] b) {
- MD5 md5 = new MD5();
- md5.update(b);
- return md5.getHashString();
- }
-
- /**
- * Gets the MD5 hash the data on the given InputStream.
- *
- * @param in byte array for which an MD5 hash is desired.
- * @return Array of 16 bytes, the hash of all updated bytes.
- * @throws IOException if an I/O error occurs.
- *
- * @since ostermillerutils 1.00.00
- */
- public static byte[] getHash(InputStream in) throws IOException {
- MD5 md5 = new MD5();
- byte[] buffer = new byte[1024];
- int read;
- while ((read = in.read(buffer)) != -1) {
- md5.update(buffer, read);
- }
- return md5.getHash();
- }
-
- /**
- * Gets the MD5 hash the data on the given InputStream.
- *
- * @param in byte array for which an MD5 hash is desired.
- * @return 32-character hex representation the data's MD5 hash.
- * @throws IOException if an I/O error occurs.
- *
- * @since ostermillerutils 1.00.00
- */
- public static String getHashString(InputStream in) throws IOException {
- MD5 md5 = new MD5();
- byte[] buffer = new byte[1024];
- int read;
- while ((read = in.read(buffer)) != -1) {
- md5.update(buffer, read);
- }
- return md5.getHashString();
- }
-
- /**
- * Gets the MD5 hash of the given String.
- * The string is converted to bytes using the current
- * platform's default character encoding.
- *
- * @param s String for which an MD5 hash is desired.
- * @return Array of 16 bytes, the hash of all updated bytes.
- *
- * @since ostermillerutils 1.00.00
- */
- public static byte[] getHash(String s) {
- MD5 md5 = new MD5();
- md5.update(s);
- return md5.getHash();
- }
-
/**
* Gets the MD5 hash of the given String.
* The string is converted to bytes using the current
@@ -177,38 +95,6 @@ public class MD5 {
return md5.getHashString();
}
- /**
- * Gets the MD5 hash of the given String.
- *
- * @param s String for which an MD5 hash is desired.
- * @param enc The name of a supported character encoding.
- * @return Array of 16 bytes, the hash of all updated bytes.
- * @throws UnsupportedEncodingException If the named encoding is not supported.
- *
- * @since ostermillerutils 1.00.00
- */
- public static byte[] getHash(String s, String enc) throws UnsupportedEncodingException {
- MD5 md5 = new MD5();
- md5.update(s, enc);
- return md5.getHash();
- }
-
- /**
- * Gets the MD5 hash of the given String.
- *
- * @param s String for which an MD5 hash is desired.
- * @param enc The name of a supported character encoding.
- * @return 32-character hex representation the data's MD5 hash.
- * @throws UnsupportedEncodingException If the named encoding is not supported.
- *
- * @since ostermillerutils 1.00.00
- */
- public static String getHashString(String s, String enc) throws UnsupportedEncodingException {
- MD5 md5 = new MD5();
- md5.update(s, enc);
- return md5.getHashString();
- }
-
/**
* Reset the MD5 sum to its initial state.
*
@@ -219,17 +105,6 @@ public class MD5 {
finalState.valid = false;
}
- /**
- * Returns 32-character hex representation of this hash.
- *
- * @return String representation of this object's hash.
- *
- * @since ostermillerutils 1.00.00
- */
- public String toString() {
- return getHashString();
- }
-
/**
* Update this hash with the given data.
*
@@ -300,21 +175,6 @@ public class MD5 {
update(workingState, buffer, offset, length);
}
- /**
- * Update this hash with the given data.
- *
- * If length bytes are not available to be hashed, as many bytes as
- * possible will be hashed.
- *
- * @param buffer Array of bytes to be hashed.
- * @param length number of bytes to hash.
- *
- * @since ostermillerutils 1.00.00
- */
- public void update(byte buffer[], int length) {
- update(buffer, 0, length);
- }
-
/**
* Update this hash with the given data.
*
@@ -326,19 +186,6 @@ public class MD5 {
update(buffer, 0, buffer.length);
}
- /**
- * Updates this hash with a single byte.
- *
- * @param b byte to be hashed.
- *
- * @since ostermillerutils 1.00.00
- */
- public void update(byte b) {
- byte buffer[] = new byte[1];
- buffer[0] = b;
- update(buffer, 1);
- }
-
/**
* Update this hash with a String.
* The string is converted to bytes using the current
@@ -351,19 +198,6 @@ public class MD5 {
public void update(String s) {
update(s.getBytes());
}
-
- /**
- * Update this hash with a String.
- *
- * @param s String to be hashed.
- * @param enc The name of a supported character encoding.
- * @throws UnsupportedEncodingException If the named encoding is not supported.
- *
- * @since ostermillerutils 1.00.00
- */
- public void update(String s, String enc) throws UnsupportedEncodingException {
- update(s.getBytes(enc));
- }
/**
* The current state from which the hash sum
* can be computed or updated.
@@ -399,7 +233,7 @@ public class MD5 {
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,};
+ 0, 0, 0, 0, 0, 0, 0, 0};
/**
* Contains internal state of the MD5 class.
diff --git a/src/mobscrob/scrobbler/AudioScrobbler.java b/src/mobscrob/scrobbler/AudioScrobbler.java
deleted file mode 100644
index 385bd56..0000000
--- a/src/mobscrob/scrobbler/AudioScrobbler.java
+++ /dev/null
@@ -1,276 +0,0 @@
-/*
- * aNNiMON 2011
- * For more info visit http://annimon.com/
- */
-package mobscrob.scrobbler;
-
-import java.io.OutputStream;
-import java.util.Calendar;
-import java.util.Vector;
-import javax.microedition.io.Connector;
-import javax.microedition.io.HttpConnection;
-import javax.microedition.lcdui.Image;
-
-/**
- *
- * @author aNNiMON
- */
-public class AudioScrobbler {
-
- private Image avatarBitmap;
- private String challenge;
- private String clientId;
- private String clientVersion;
- private boolean connected = false;
- private String handshakeUrl;
- private String md5Response;
- private String passwordMD5;
- private String submitUrl;
- private String user;
- private static final String DEFAULT_HOST = "";//"post.audioscrobbler.com";
-
- /*
- * private void SubmitTrack()
- * {
- * if (this.LastFM[2] == string.Empty)
- * {
- * this.LastFM[2] = Audioscrobbler.GetPasswordMD5(this.LastFM[1]);
- * }
- * if (this.audioscrobbler == null)
- * {
- * this.audioscrobbler = new Audioscrobbler("opa", "0.1", this.LastFM[0], this.LastFM[2]);
- * this.audioscrobbler.ConnectionFailed += new EventHandler(audioscrobbler_ConnectionFailed);
- * this.audioscrobbler.Submitted += new EventHandler(this.audioscrobbler_Submitted);
- * this.audioscrobbler.ConnectionEstablished += new EventHandler(audioscrobbler_ConnectionEstablished);
- * }
- * this.audioscrobbler.Connect();
- * }
- *
- * ((Audioscrobbler)sender).Submit(frmMain.CurrentTrackInfo[1], frmMain.CurrentTrackInfo[3], frmMain.CurrentTrackInfo[2],
- * "1", frmMain.CurrentTrackLength / 1000);
- */
-
- //"opa", "0.1", this.LastFM[0], this.LastFM[2]
- public AudioScrobbler(String clientId, String clientVersion, String user, String passwordMD5) {
- this.clientId = clientId;
- this.clientVersion = clientVersion;
- this.user = user;
- this.passwordMD5 = passwordMD5;
- this.handshakeUrl = "http://post.audioscrobbler.com/?hs=true&p=1.1&c=" + this.clientId + "&v=" + this.clientVersion + "&u=" + this.user;
- }
-
- private void connectNow() {
- try {
- this.avatarBitmap = null;
-
- byte[] body = HTTPUtil.getUrl(this.handshakeUrl, DEFAULT_HOST);
- Vector lines = ByteUtil.readLines(body);
-
- // check is OK
- String str = (String) lines.elementAt(0);
- if (str.equals("UPTODATE") || str.startsWith("UPDATE"))
- {
- this.challenge = (String) lines.elementAt(1);
- this.submitUrl = (String) lines.elementAt(2);
- String s = this.passwordMD5 + this.challenge;
- this.md5Response = MD5.getHashString(s).replace('-', '\0').toLowerCase();
- this.connected = true;
- //ConnectionEstablished(this, new EventArgs());
- }
- } catch (Exception ex) {
- //ConnectionFailed(this, new EventArgs());
- }
- }
-
- public void connect() {
- Thread thread = new Thread(new Runnable() {
-
- public void run() {
- connectNow();
- }
- });
- thread.start();
- }
-
- private void downloadAvatar() {
- String str = MD5.getHashString(this.user).replace('-', '\0').toLowerCase();
- try {
- byte[] img = HTTPUtil.getUrl("http://static.last.fm/avatar/" + str + ".jpg/", "");
- this.avatarBitmap = Image.createImage(img, 0, img.length);
- } catch (Exception ex) {
- }
- }
-
- public static String GetPasswordMD5(String password) {
- return MD5.getHashString(password).replace('-', '\0').toLowerCase();
- }
-
- public void Submit(String artist, String song, String album, String musicBrainzId, int length) {
- if (this.connected) {
- final Submittor submittor = new Submittor(this.submitUrl, this.user, this.md5Response, artist, song, album, musicBrainzId, length, 3);
-
- Thread thread = new Thread(new Runnable() {
-
- public void run() {
- submittor.execute();
- }
- });
- thread.start();
- }
- }
-
- public Image AvatarBitmap() {
- return this.avatarBitmap;
- }
-
- private class Submittor {
-
- private String album;
- private String artist;
- private int length;
- private String musicBrainzId;
- private String response;
- private int retry;
- private String song;
- private String url;
- private String user;
-
- public Submittor(String url, String user, String response, String artist, String song, String album, String musicBrainzId, int length, int retry) {
- this.url = url;
- this.user = user;
- this.response = response;
- this.artist = (retry == 0) ? HTTPUtil.encodeParam(artist) : artist;
- this.song = (retry == 0) ? HTTPUtil.encodeParam(song) : song;
- this.album = (retry == 0) ? HTTPUtil.encodeParam(album) : album;
- this.musicBrainzId = musicBrainzId;
- this.length = length;
- this.retry = retry;
- }
-
- private String getTime() {
- StringBuffer sb = new StringBuffer();
- Calendar cal = Calendar.getInstance();
- int tmp;
- //Год 2009-06-15 20:45:30Z
- tmp = cal.get(Calendar.YEAR);
- if (tmp <= 9) {
- sb.append('0');
- }
- sb.append(tmp);
- sb.append('-');
- //Месяц
- tmp = cal.get(Calendar.MONTH) + 1;
- if (tmp <= 9) {
- sb.append('0');
- }
- sb.append(tmp);
- sb.append('-');
- //День
- tmp = cal.get(Calendar.DAY_OF_MONTH);
- if (tmp <= 9) {
- sb.append('0');
- }
- sb.append(tmp);
- sb.append(' ');
- //Час
- tmp = cal.get(Calendar.HOUR_OF_DAY);
- if (tmp <= 9) {
- sb.append('0');
- }
- sb.append(tmp);
- sb.append(':');
- //Минута
- tmp = cal.get(Calendar.MINUTE);
- if (tmp <= 9) {
- sb.append('0');
- }
- sb.append(tmp);
- sb.append(':');
- //Секунда
- tmp = cal.get(Calendar.SECOND);
- if (tmp <= 9) {
- sb.append('0');
- }
- sb.append(tmp);
- return sb.toString();
- }
-
- public void execute() {
- HttpConnection conn = null;
- OutputStream os = null;
- try {
- StringBuffer sb = new StringBuffer();
- sb.append("u=").append(this.user); //User
- sb.append("&s=").append(this.response); //Session
- sb.append("&a[0]=").append(this.artist); //Artist
- sb.append("&t[0]=").append(this.song); //Title
- sb.append("&b[0]=").append(this.album); //Album
- sb.append("&m[0]=").append(this.musicBrainzId); //MusicBrainzId
-
- sb.append("&l[0]=").append(this.length); //Length (Duration)
- sb.append("&i[0]=").append(getTime()); //Current Time
-
- byte[] bytes = sb.toString().getBytes("UTF-8");
-
- // set up HTTP connection
- conn = (HttpConnection) Connector.open(this.url);
- conn.setRequestMethod(HttpConnection.POST);
- conn.setRequestProperty("User-Agent", "SEPlayerService");
- conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
- conn.setRequestProperty("Content-Length", String.valueOf(bytes.length));
- // try opening output stream first
- os = conn.openOutputStream();
- // try writing byte by byte
- try {
- os.write(bytes, 0, bytes.length);
- } finally {
- os.close();
- }
- /*for (int i = 0; i < paramBytes.length; i++) {
- os.write((int) paramBytes[i]);
- }*/
- byte[] resp = HTTPUtil.readHttpResponse(conn);
- Vector lines = ByteUtil.readLines(resp);
-
- try {
- String str2 = (String) lines.elementAt(0);
- int interval = 0;
- String str3 = (String) lines.elementAt(1);
- if ((str3 != null) && str3.startsWith("INTERVAL")) {
- try {
- interval = Integer.parseInt(str3.substring("INTERVAL ".length()));
- } catch (Exception ex) {
- }
- }
- if (str2.startsWith("FAILED")) {
- this.retry(interval);
- } else if (str2.startsWith("BADAUTH")) {
- throw new Exception();
- }
- } finally {
- conn.close();
- }
- } catch (Exception ex) {
- }
- }
-
- private void retry(int interval) {
- if (this.retry <= 3) {
- this.retry++;
- try {
- Thread.sleep((int) ((interval * this.retry) * 0x3e8));
- } catch (InterruptedException ex) {
- }
- final AudioScrobbler.Submittor submittor = new AudioScrobbler.Submittor(this.url, this.user, this.response, this.artist, this.song, this.album, this.musicBrainzId, this.length, this.retry);
-
- Thread thread = new Thread(new Runnable() {
-
- public void run() {
- submittor.execute();
- }
- });
- thread.start();
- }
- }
- }
-}
diff --git a/src/mobscrob/scrobbler/ByteUtil.java b/src/mobscrob/scrobbler/ByteUtil.java
deleted file mode 100644
index cc5d563..0000000
--- a/src/mobscrob/scrobbler/ByteUtil.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/**
- * ByteUtil.java
- * @date 30 Sep 2008
- *
- * This program is distributed under the terms of the GNU General Public
- * License
- * Copyright 2008 NJ Pearman
- *
- * This file is part of MobScrob.
- *
- * MobScrob is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * MobScrob is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with MobScrob. If not, see .
- */
-package mobscrob.scrobbler;
-
-import java.util.Vector;
-
-/**
- *
- */
-/**
- * @author Neill
- *
- */
-public class ByteUtil {
-
- /**
- * Utility class so private constructor
- */
- private ByteUtil() {
- }
-
- /**
- * Returns a Vector of Strings representing the lines present in the byte
- * array, separated by '\n' return feed.
- *
- * @param bytes
- * @return
- */
- public static Vector readLines(byte[] bytes) {
- //final String methodName = "1";
- Vector lines = new Vector();
- if (bytes == null || bytes.length == 0) {
- return lines;
- }
- StringBuffer line = new StringBuffer();
- for (int i = 0; i < bytes.length; i++) {
- if (bytes[i] == '\n') {
- lines.addElement(line.toString());
- line = new StringBuffer();
- } else {
- // add to current line
- line.append((char) bytes[i]);
- }
- }
-
- return lines;
- }
-
- public static void replaceSpaceWithPlus(byte[] bytes) {
- if (bytes != null) {
- for (int i = 0; i < bytes.length; i++) {
- if (bytes[i] == ' ') {
- bytes[i] = '+';
- }
- }
- }
- }
-}
diff --git a/src/mobscrob/scrobbler/HTTPUtil.java b/src/mobscrob/scrobbler/HTTPUtil.java
deleted file mode 100644
index dc6cf52..0000000
--- a/src/mobscrob/scrobbler/HTTPUtil.java
+++ /dev/null
@@ -1,192 +0,0 @@
-/**
- * HTTPUtil.java
- *
- * This program is distributed under the terms of the GNU General Public
- * License
- * Copyright 2008 NJ Pearman
- *
- * This file is part of MobScrob.
- *
- * MobScrob is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * MobScrob is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with MobScrob. If not, see .
- */
-package mobscrob.scrobbler;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.UnsupportedEncodingException;
-import java.util.Enumeration;
-import java.util.Vector;
-
-import javax.microedition.io.Connector;
-import javax.microedition.io.HttpConnection;
-
-
-/**
- * @author Neill
- *
- */
-public class HTTPUtil {
-
- private static final String ENC_UTF8 = "UTF-8";
-
- public static final String HEADER_HOST = "Host";
-
- private HTTPUtil() {}
-
- /**
- * Encodes a parameter, also ensuring that it is UTF-8
- *
- * @param s
- * @return
- * @throws UnsupportedEncodingException
- */
- public static String encodeParam(String s) {
- if (s == null) {
- return s;
- }
-
- // encode as UTF-8
- String utf8Str;
- try {
- utf8Str = new String(s.getBytes(), ENC_UTF8);
- } catch (UnsupportedEncodingException ex) {
- utf8Str = s;
- }
-
- StringBuffer sb = new StringBuffer(utf8Str.length() * 3);
- char[] chars = utf8Str.toCharArray();
- int next;
-
- // encode the chars in the UTF-8 String
- for (int i = 0; i < chars.length; i++) {
- next = chars[i];
-
- if ((next >= 0x30 && next <= 0x39) || // 0-9
- (next >= 0x41 && next <= 0x5A) || // A-Z
- (next >= 0x61 && next <= 0x7A)) { // a-z
- sb.append((char) next);
- } else if ((next == 0xA0)) { // ' ' (whitespace)
- sb.append('+');
- } else { // encode all other chars
- sb.append("%");
- if (next <= 0xf)
- sb.append("0");
- sb.append(Integer.toHexString(next));
- }
- }
- return sb.toString();
- }
-
- /**
- * Attempts to open a URL using the GET method over HTTP and read the
- * response into a byte array. Any IOExceptions are simply thrown out of
- * this method to be caught elsewhere.
- *
- * @param url
- * @return
- * @throws IOException
- */
- public static byte[] getUrl(String url, String headerHostname) throws IOException {
- HttpConnection conn = null;
- try {
- conn = (HttpConnection) Connector.open(url);
-
- // set the compulsory HTTP/1.1 Host: header, as GET
- conn.setRequestMethod(HttpConnection.GET);
- //if(!headerHostname.equals(""))
- // conn.setRequestProperty(HEADER_HOST, headerHostname);
-
- byte[] body = readHttpResponse(conn);
- return body;
- } finally {
- closeHttpConnection(conn);
- }
- }
-
- /**
- * Reads the response from the specified HTTP connection into a byte array.
- *
- * @param conn
- * @return
- * @throws IOException
- */
- public static byte[] readHttpResponse(HttpConnection conn) throws IOException {
- final String methodName = "6";
- int rc = conn.getResponseCode();
- if (rc != HttpConnection.HTTP_OK) {
- String msg = "HTTP response code not OK: " + rc;
- throw new IOException(msg);
- }
-
- String connHeader = conn.getHeaderField("Connection");
-
- // connect
- int len = (int) conn.getLength();
-
- InputStream is = null;
-
- try {
- is = conn.openInputStream();
-
- // read response
- if (len > -1) {
- byte[] body = new byte[len];
- int actual = 0;
- int bytesread = 0;
-
- while ((bytesread != len) && (actual != -1)) {
- actual = is.read(body, bytesread, len - bytesread);
- bytesread += actual;
- }
- // do something
- return body;
- } else {
- // read byte by byte...?
-
- Vector bytes = new Vector();
- Byte byteObj;
- int next;
- while ((next = is.read()) > -1) {
- byteObj = new Byte((byte) next);
- bytes.addElement(byteObj);
- }
-
- byte[] body = new byte[bytes.size()];
- Enumeration e = bytes.elements();
- int i = 0;
- while (e.hasMoreElements()) {
- byteObj = (Byte) e.nextElement();
- body[i++] = byteObj.byteValue();
- }
-
- return body;
- }
- } finally {
- if (is != null) {
- try {
- is.close();
- } catch (Exception e) {
- }
- }
- }
- }
-
- public static void closeHttpConnection(HttpConnection conn) {
- final String methodName = "7";
- if (conn != null) {
- try { conn.close(); }
- catch (Exception e) { } //log.error(methodName, "Unable to close HTTP connecton: " + e.getMessage(), e); }
- }
- }
-}
diff --git a/src/msapi/J2MEPlayer.java b/src/msapi/J2MEPlayer.java
new file mode 100644
index 0000000..082d129
--- /dev/null
+++ b/src/msapi/J2MEPlayer.java
@@ -0,0 +1,57 @@
+/*
+ * aNNiMON 2011
+ * For more info visit http://annimon.com/
+ */
+
+package msapi;
+
+/**
+ *
+ * @author aNNiMON
+ */
+public class J2MEPlayer implements SPlayer {
+
+ public void play() {
+ }
+
+ public void pause() {
+ }
+
+ public void nextTrack() {
+ }
+
+ public void prevTrack() {
+ }
+
+ public void fastForward() {
+ }
+
+ public void rewind() {
+ }
+
+ public void skip(int i) {
+ }
+
+ public void seek(int i) {
+ }
+
+ public void updateTrackInfo() {
+ }
+
+ public long getCurrentTime() {
+ return 10;
+ }
+
+ public void playPause() {
+ }
+
+ public Track getTrack() {
+ Track temp = new Track();
+ temp.setArtist("Unknown artist");
+ temp.setAlbum("Unknown album");
+ temp.setTitle("Unknown title");
+ temp.setDuration(100);
+ return temp;
+ }
+
+}
diff --git a/src/msapi/MSPlayer.java b/src/msapi/MSPlayer.java
new file mode 100644
index 0000000..78f9165
--- /dev/null
+++ b/src/msapi/MSPlayer.java
@@ -0,0 +1,156 @@
+/*
+ * aNNiMON 2011
+ * For more info visit http://annimon.com/
+ */
+
+package msapi;
+
+import com.annimon.StringEncoder;
+import com.sonyericsson.multimedia.ControlEvent;
+import com.sonyericsson.multimedia.ControlException;
+import com.sonyericsson.multimedia.Media;
+import com.sonyericsson.multimedia.MetaData;
+import com.sonyericsson.multimedia.MultimediaService;
+import com.sonyericsson.multimedia.MultimediaServiceManager;
+import com.sonyericsson.multimedia.control.MediaControl;
+import com.sonyericsson.multimedia.control.MediaControlListener;
+import javax.microedition.lcdui.Image;
+
+/**
+ * Стандартный плеер Sony Ericsson. Используется Multimedia Services API.
+ * @author aNNiMON
+ */
+public class MSPlayer implements MediaControlListener, SPlayer {
+
+ private MultimediaService service;
+ private MediaControl mediaControl;
+ private Media media;
+ private Track track;
+
+ public MSPlayer() {
+ service = MultimediaServiceManager.getMultimediaService("MediaPlayer");
+ mediaControl = (MediaControl)service.getControl("MediaControl");
+ mediaControl.addMediaControlListener(MSPlayer.this);
+ }
+
+ public void mediaControlUpdate(int eventId, ControlEvent event) {
+ try {
+ switch (eventId) {
+ case MediaControlListener.PLAY:
+ case MediaControlListener.PAUSE:
+ case MediaControlListener.STOP:
+ case MediaControlListener.ENDPLAY:
+ case MediaControlListener.FASTFORWARD:
+ case MediaControlListener.REWIND:
+ this.media = (Media) event.getData();
+ updateTrackInfo();
+ break;
+
+ case MediaControlListener.ERROR:
+ break;
+ }
+ } catch (Throwable t) {}
+ }
+
+ private String getValue(MetaData metaData, String md) {
+ String data = metaData.getValue(md);
+ StringBuffer sb = new StringBuffer();
+ for(int i=0; i
+ public void play() {
+ try {
+ mediaControl.play();
+ } catch (ControlException ex) {}
+ }
+
+ public void pause() {
+ try {
+ mediaControl.pause();
+ } catch (ControlException ex) {}
+ }
+
+ public void nextTrack() {
+ try {
+ mediaControl.next();
+ } catch (ControlException ex) {}
+ }
+
+ public void prevTrack() {
+ try {
+ mediaControl.prev();
+ } catch (ControlException ex) {}
+ }
+
+ public void fastForward() {
+ try {
+ mediaControl.fastForward();
+ } catch (ControlException ex) {}
+ }
+
+ public void rewind() {
+ try {
+ mediaControl.rewind();
+ } catch (ControlException ex) {}
+ }
+
+ public void skip(int i) {
+ try {
+ mediaControl.skip(i);
+ } catch (ControlException ex) {}
+ }
+
+ public void seek(int i) {
+ try {
+ mediaControl.seek(i);
+ } catch (ControlException ex) {}
+ }
+
+ public void updateTrackInfo() {
+ try {
+ MetaData data = media.getMetaData();
+ if (data != null) {
+
+ if (track == null || !track.getTitle().equals((String) getValue(data, MetaData.TITLE_KEY))) {
+ if (track == null) track = new Track();
+ track.setAlbum((String) getValue(data, MetaData.ALBUM_KEY));
+ track.setArtist((String) getValue(data, MetaData.ARTIST_KEY));
+ track.setTitle((String) getValue(data, MetaData.TITLE_KEY));
+ track.setDuration(media.getDuration());
+
+ byte[] alb = data.getAlbumArt();
+ if (alb != null) {
+ track.setCover(Image.createImage(alb, 0, alb.length));
+ } else {
+ track.setCover(null);
+ }
+ }
+ }
+ } catch (Exception e) {}
+ }
+
+ public Track getTrack() {
+ return track;
+ }
+
+ public long getCurrentTime() {
+ return media.getMediaTime();
+ }
+
+ public void playPause() {
+ try {
+ if (mediaControl.getState() == mediaControl.STATE_PLAY) pause();
+ else play();
+ } catch (ControlException ex) {
+ play();
+ }
+ }
+ //
+
+
+
+}
diff --git a/src/msapi/SPlayer.java b/src/msapi/SPlayer.java
new file mode 100644
index 0000000..f40f37b
--- /dev/null
+++ b/src/msapi/SPlayer.java
@@ -0,0 +1,37 @@
+/*
+ * aNNiMON 2011
+ * For more info visit http://annimon.com/
+ */
+
+package msapi;
+
+/**
+ *
+ * @author aNNiMON
+ */
+public interface SPlayer {
+
+ public abstract void play();
+
+ public abstract void pause();
+
+ public abstract void nextTrack();
+
+ public abstract void prevTrack();
+
+ public abstract void fastForward();
+
+ public abstract void rewind();
+
+ public abstract void skip(int i);
+
+ public abstract void seek(int i);
+
+ public abstract void updateTrackInfo();
+
+ public abstract Track getTrack();
+
+ public abstract long getCurrentTime();
+
+ public abstract void playPause();
+}
diff --git a/src/msapi/Track.java b/src/msapi/Track.java
new file mode 100644
index 0000000..8d5bc78
--- /dev/null
+++ b/src/msapi/Track.java
@@ -0,0 +1,79 @@
+/*
+ * aNNiMON 2011
+ * For more info visit http://annimon.com/
+ */
+
+package msapi;
+
+import javax.microedition.lcdui.Image;
+
+/**
+ * Трек
+ * @author aNNiMON
+ */
+public class Track {
+
+ //
+ /** Название альбома */
+ private String album;
+
+ /** Исполнитель */
+ private String artist;
+
+ /** Картинка альбома */
+ private Image cover;
+
+ /** Длительность */
+ private long duration;
+
+ /** Заголовок */
+ private String title;
+ //
+
+ //
+ public String getAlbum() {
+ return album;
+ }
+
+ public String getArtist() {
+ return artist;
+ }
+
+ public Image getCover() {
+ return cover;
+ }
+
+ public long getDuration() {
+ return duration;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ //
+
+ //
+ public void setAlbum(String album) {
+ this.album = album;
+ }
+
+ public void setArtist(String artist) {
+ this.artist = artist;
+ }
+
+ public void setCover(Image cover) {
+ this.cover = cover;
+ }
+
+ public void setDuration(long duration) {
+ this.duration = duration;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ //
+
+}
diff --git a/src/newfile b/src/newfile
deleted file mode 100644
index 2212995..0000000
--- a/src/newfile
+++ /dev/null
@@ -1,2 +0,0 @@
-визуализация смены громкости
-Быстрая перемотка
\ No newline at end of file
diff --git a/src/res/1.swf b/src/res/1.swf
new file mode 100644
index 0000000..1e65547
Binary files /dev/null and b/src/res/1.swf differ
diff --git a/src/2.swf b/src/res/2.swf
similarity index 100%
rename from src/2.swf
rename to src/res/2.swf
diff --git a/src/3.swf b/src/res/3.swf
similarity index 100%
rename from src/3.swf
rename to src/res/3.swf
diff --git a/src/4.swf b/src/res/4.swf
similarity index 100%
rename from src/4.swf
rename to src/res/4.swf
diff --git a/src/res/5.swf b/src/res/5.swf
new file mode 100644
index 0000000..16ccdbd
Binary files /dev/null and b/src/res/5.swf differ
diff --git a/src/res/6.swf b/src/res/6.swf
new file mode 100644
index 0000000..6bfc419
Binary files /dev/null and b/src/res/6.swf differ
diff --git a/src/about b/src/res/about
similarity index 85%
rename from src/about
rename to src/res/about
index 1a296cf..077404b 100644
--- a/src/about
+++ b/src/res/about
@@ -3,14 +3,13 @@ Sony Ericsson Player Service 7.0
Автор: Виктор aNNiMON Мельник
Сайт разработчика: http://annimon.com/
-Программа - управление стандартным плейером телефонов Sony Ericsson с поддержкой Multimedia Service API и акселерометром.
+Программа - управление стандартным плеером телефонов Sony Ericsson с поддержкой Multimedia Service API и акселерометром.
Управление:
Влево/Вправо/Движение акселерометром - Переключение песен.
Вверх/Вниз - переключение режимов: Всё/Визуализация.
- 1 - Горячая клавиша поиска текста.
3 - установить начало/конец отрезка для повтора или отключить повтор.
- 4/6 - Перемотка назад/вперед.
+ 4/6 - Перемотка назад/вперед. Зажатие активизирует быструю перемотку.
5/Огонь - Пауза.
9 - Спящий режим.
0 - Включение/Отключение текстов песен.
@@ -19,6 +18,13 @@ Sony Ericsson Player Service 7.0
Изменения:
Версия 7.0
+ - Программа полностью переписана с нуля, убраны неработающие и ненужные элементы. Это даёт заметный прирост скорости работы и расширение функционала.
+ - Добавлены новые переходы между экранами.
+ - Добавлены новые визуальные эффекты.
+ - Убран скробблер annimon.com и добавлен скробблер LastFM.
+ - Экран визуализации теперь показывается на весь экран.
+ - Изменена логика доступа к внутренним API.
+ - Доступ к данным акселерометра теперь универсальный.
- При выборе цвета скина, по нажатию кн.0 можно выбрать цвет текста.
Версия 6.0
@@ -33,10 +39,12 @@ Sony Ericsson Player Service 7.0
- Скроллинг длинных названий песен.
- Добавлена быстрая перемотка на зажатие кнопок 4 или 6.
- Добавлена визуализация смены громкости.
+
Версия 5.2
- Добавлен пункт в настройках, при котором переключение треков будет идти только вперед, независимо от направления рывка.
- Поддержка русской кодировки в именах файлов.
- Другие исправления и изменения.
+
Версия 5.0 && 5.1
- Добавлена сортировка списка файлов по рейтингу.
- Добавлен английский язык.
@@ -70,9 +78,6 @@ Sony Ericsson Player Service 7.0
- Режим визуализации. Переключается клавишами Вверх/Вниз,
- Добавил перемотку клавишами 1 и 3.
-Скробблинг:
- В версии 5.0 сделал некое подобие скробблинга, то есть информация о проигруемом файле отсылается на сайт. Потом вы можете смотреть статистику проигрывания музыки.
-
Поддержка lrc:
Lyrics-файл (.lrc) должен быть записан в кодировке WIN-1251, иначе возможны ошибки при чтении.
Имя lrc-файла должно быть либо "[Название группы] - [Название песни].lrc", либо "[Название исходного фудиофайла].ltc".
@@ -87,4 +92,4 @@ Z393537409230
- - - - - - - - - - - - - - - - - -
© aNNiMON (Melnik Software)
-Украина, 2010
\ No newline at end of file
+Украина, 2011
\ No newline at end of file
diff --git a/src/res/album.png b/src/res/album.png
deleted file mode 100644
index 3442b7c..0000000
Binary files a/src/res/album.png and /dev/null differ
diff --git a/src/res/album.xid b/src/res/album.xid
new file mode 100644
index 0000000..8d1d722
Binary files /dev/null and b/src/res/album.xid differ
diff --git a/src/res/artist.png b/src/res/artist.png
deleted file mode 100644
index 4188fff..0000000
Binary files a/src/res/artist.png and /dev/null differ
diff --git a/src/res/artist.xid b/src/res/artist.xid
new file mode 100644
index 0000000..ed60172
Binary files /dev/null and b/src/res/artist.xid differ
diff --git a/src/res/exit.png b/src/res/exit.png
deleted file mode 100644
index 1a2f8dc..0000000
Binary files a/src/res/exit.png and /dev/null differ
diff --git a/src/res/exit.xid b/src/res/exit.xid
new file mode 100644
index 0000000..b683bc6
--- /dev/null
+++ b/src/res/exit.xid
@@ -0,0 +1,3 @@
+$ю'90z}m}wwwz>?3%wwwcwwwbqwww1ў№Яwwvњ>36#ТўёfфР#хKЈЦт5Т,fурY)У№6—W–^懕6ЈFЯ+RЫЯ«…pУX a°nАц`»KёDЁђЊ‹н~s‰’„ЋфПя|hЏЁьWFЛІk№аd·EMрФ•}aІ™4·n#™bї)Iц ;”aµ?~.Є,мђпµ*k„|/ра/°8{s;Ц}ґщ8Ъ»j›Gi•@I–v#а#З5·Чс‹oЁ“¦‡І} WоNќ%№{j’0GулaЪІокz<4I™ЅЙ_4 Є.ыњЄIkЗµOI]Мiм·юМќІ–xQ§тjнL
+т1ВзNjИ]Ийњў„ ђЅћуЇу8•фuЬѓ
qryњ4JX_¬:‰bДќѓ%>ИsrБ€?m B‹CљbџX\j7Щъєн¤wwww>293Щ5х
\ No newline at end of file
diff --git a/src/res/icon.png b/src/res/icon.png
new file mode 100644
index 0000000..67fbfe8
Binary files /dev/null and b/src/res/icon.png differ
diff --git a/src/res/pal.png b/src/res/pal.png
deleted file mode 100644
index ac347c5..0000000
Binary files a/src/res/pal.png and /dev/null differ
diff --git a/src/res/pal.xid b/src/res/pal.xid
new file mode 100644
index 0000000..cfda1f7
Binary files /dev/null and b/src/res/pal.xid differ
diff --git a/src/res/pound.png b/src/res/pound.png
deleted file mode 100644
index c06391c..0000000
Binary files a/src/res/pound.png and /dev/null differ
diff --git a/src/res/pound.xid b/src/res/pound.xid
new file mode 100644
index 0000000..acaf4a8
Binary files /dev/null and b/src/res/pound.xid differ
diff --git a/src/res/sb.png b/src/res/sb.png
deleted file mode 100644
index 195c71e..0000000
Binary files a/src/res/sb.png and /dev/null differ
diff --git a/src/res/sb.xid b/src/res/sb.xid
new file mode 100644
index 0000000..923439f
Binary files /dev/null and b/src/res/sb.xid differ
diff --git a/src/res/sbl.png b/src/res/sbl.png
deleted file mode 100644
index 8e50f2b..0000000
Binary files a/src/res/sbl.png and /dev/null differ
diff --git a/src/res/sbl.xid b/src/res/sbl.xid
new file mode 100644
index 0000000..03ee851
Binary files /dev/null and b/src/res/sbl.xid differ
diff --git a/src/res/slp.xid b/src/res/slp.xid
new file mode 100644
index 0000000..9784bb6
Binary files /dev/null and b/src/res/slp.xid differ
diff --git a/src/res/star.png b/src/res/star.png
deleted file mode 100644
index 4269fd3..0000000
Binary files a/src/res/star.png and /dev/null differ
diff --git a/src/res/star.xid b/src/res/star.xid
new file mode 100644
index 0000000..9c6d828
Binary files /dev/null and b/src/res/star.xid differ
diff --git a/src/res/t.png b/src/res/t.png
deleted file mode 100644
index 9bf6eb1..0000000
Binary files a/src/res/t.png and /dev/null differ
diff --git a/src/res/t.xid b/src/res/t.xid
new file mode 100644
index 0000000..7590044
Binary files /dev/null and b/src/res/t.xid differ
diff --git a/src/res/tl.png b/src/res/tl.png
deleted file mode 100644
index 2568a4d..0000000
Binary files a/src/res/tl.png and /dev/null differ
diff --git a/src/res/tl.xid b/src/res/tl.xid
new file mode 100644
index 0000000..7f3bd1c
Binary files /dev/null and b/src/res/tl.xid differ
diff --git a/src/res/track.png b/src/res/track.png
deleted file mode 100644
index 8d5761e..0000000
Binary files a/src/res/track.png and /dev/null differ
diff --git a/src/res/track.xid b/src/res/track.xid
new file mode 100644
index 0000000..26169e6
Binary files /dev/null and b/src/res/track.xid differ
diff --git a/src/res/zero.png b/src/res/zero.png
deleted file mode 100644
index 39bbcf2..0000000
Binary files a/src/res/zero.png and /dev/null differ
diff --git a/src/res/zero.xid b/src/res/zero.xid
new file mode 100644
index 0000000..2a101cb
Binary files /dev/null and b/src/res/zero.xid differ
diff --git a/src/seps/Canv.java b/src/seps/Canv.java
new file mode 100644
index 0000000..6d4b68a
--- /dev/null
+++ b/src/seps/Canv.java
@@ -0,0 +1,692 @@
+package seps;
+
+/*
+ * aNNiMON 2011
+ * For more info visit http://annimon.com/
+ */
+
+import accel.*;
+import com.annimon.GraphicsUtil;
+import com.annimon.Util;
+import com.nokia.mid.ui.DeviceControl;
+import fx.*;
+import javax.microedition.lcdui.*;
+import lastfm.LastFMScrobbler;
+import msapi.*;
+import visual.*;
+
+/**
+ * @author aNNiMON
+ */
+public class Canv extends Canvas implements Runnable {
+
+ //Экран
+ private Image I;
+ private Graphics G;
+ private int w,h;
+
+ //Модули (интерфейсы)
+ private SensorData sensor; //Акселерометр
+ private SPlayer player; //MultimediaServices API
+ private Visual visual; //Visualization
+ //Переходы
+ private AnimatedImage animated = null;
+ private ImageFx imgfx;
+ private Image old;
+
+ //Прочие классы
+ private Images im; //Изображения
+ private Lang lang; //Текстовые метки
+ private FWCashe mfwc; //Кэш размеров шрифта
+ private Lyrics lrc; //Тексты песен
+ private Thread thr; //Поток
+ //Изображение альбома
+ private Image album;
+
+ //Функция повтора
+ private byte repeat;
+ private int a,b;
+
+ //Режимы и состояния
+ private static final byte
+ PLAYER_MODE = 0,
+ VISUAL_MODE = 1;
+ private static final byte MAX_VISUALS = 16;
+ private static final int MENU_Y_STEP = 25;
+ private static final int VOLUME_Y_STEP = 10;
+ private byte mode;
+ private int volumeplus, volumeminus; //визуализация изменения громкости
+ private boolean fastF, fastR; //быстрая перемотка
+ private int cx, cy, thisskin; //выбор скина
+ private int accelPrevDelta; //Предыдущее состояние акселерометра
+ private boolean rspressed;
+
+ //Скролллинг текста (исп, трек, альб, текст)
+ private int char_A_width;
+ private int[] scrollPos = {0,0,0,0};
+ private int[] sleepPos = {0,0,0,0};
+ private boolean[] scrolldirection = {false, false, false, false};
+ private int textWidth, lyricWidth;
+
+ //Меню
+ private String[] m;
+ private int menuwidth, menuheight, mcur, menuy, menuup;
+ private boolean menu, skin, vis;
+
+
+ public Canv(Images im, Lang lang) {
+ setFullScreenMode(true);
+ w = getWidth();
+ h = getHeight();
+ this.im = im;
+ this.lang = lang;
+ //Инициализация API
+ try {
+ if(!Rms.api_mserv) player = new J2MEPlayer();
+ else player = new MSPlayer();
+ } catch (Exception e) {
+ player = new J2MEPlayer();
+ }
+ if(Rms.api_accel) sensor = new AccelData();
+ else sensor = new NoData();
+ thr = new Thread(this);
+ thr.start();
+ //Модули
+ initVisual();
+ //Инициализация экрана
+ I = Image.createImage(w, h);
+ G = I.getGraphics();
+ //Режимы
+ mode = PLAYER_MODE;
+ fastF = fastR = menu = skin = vis = rspressed = false;
+ accelPrevDelta = volumeplus = volumeminus = menuup = mcur = repeat = 0;
+ //Размеры
+ char_A_width = GraphicsUtil.getFont(GraphicsUtil.SMALL_BOLD_FONT).charWidth('a'); //размер буквы а жирного шрифта
+ lyricWidth = w/(char_A_width+1);
+ textWidth = lyricWidth - 1;
+ cx = w/2;
+ cy = 4*im.statusBarHeight+im.pal.getHeight()/2;
+ initMenu(lang);
+ menuy = 2*im.statusBarHeight-menuheight;
+
+ if(Rms.startPlayer) getPlayer().play();
+ getPlayer().updateTrackInfo();
+ }
+
+ /**
+ * Инициализация меню
+ * @param lang
+ */
+ public final void initMenu(Lang lang) {
+ m = new String[] {
+ lang.sleepmode,
+ lang.visual,
+ lang.skin,
+ lang.options,
+ lang.about,
+ lang.minimise,
+ lang.exit
+ };
+ mfwc = FWCashe.getCache(GraphicsUtil.getFont(GraphicsUtil.MEDIUM_BOLD_FONT));
+ menuwidth = mfwc.stringWidth(m[0]);
+ menuheight = m.length * (GraphicsUtil.getHeightFont(GraphicsUtil.MEDIUM_BOLD_FONT)+2);
+ for(int i=1; imenuwidth) menuwidth = mfwc.stringWidth(m[i]);
+ }
+ menuwidth+=6;
+ }
+
+ public void paint(Graphics g) {
+ //Выбор визуализации
+ if(vis) choiceVisual(g, Rms.visid);
+ else if(skin) choiceSkin(g, cx, cy);
+ //Переключение режимов (all, visual)
+ else if (animated != null && old != null) {
+ g.drawImage(old, w/2, h/2, Graphics.HCENTER | Graphics.VCENTER);
+ animated.paint(g, w/2, h/2, Graphics.HCENTER | Graphics.VCENTER);
+ if (animated.isEnded()) animated = null;
+ }else drawCanvas(g);
+ repaint();
+ }
+
+ public void drawCanvas(Graphics g) {
+ if(mode==PLAYER_MODE) drawPlayerCanvas(G);
+ else if(mode==VISUAL_MODE) drawVisual(G);
+ g.drawImage(I, 0, 0, 20);
+ //Меню
+ if(menuup!=0) {
+ if(menuup>0) {
+ menuy-=MENU_Y_STEP;
+ if(menuy<=2*im.statusBarHeight-menuheight) {
+ menu = false;
+ menuup=0;
+ }
+ } else {
+ menuy+=MENU_Y_STEP;
+ if(menuy>=2*im.statusBarHeight) {
+ menu = true;
+ menuup=0;
+ }
+ }
+ drawMenu(g, mcur, menuy);
+ }else if(menu) drawMenu(g, mcur, menuy);
+ //Визуализации изменения громкости
+ if(volumeplus>0) {
+ GraphicsUtil.drawRect(g, Skin.volumeUp, Skin.volumeDn, 0, volumeplus-20, w, 20);
+ GraphicsUtil.drawRect(g, Skin.volumeDn, Skin.volumeUp, 0, volumeplus, w, 20);
+ volumeplus-=VOLUME_Y_STEP;
+ }
+ if(volumeminusih) album = Effects.Resize(album, ih*album.getWidth()/album.getHeight(), ih);
+ g.drawImage(album, w/2, h/2, 3);
+ }else if(Rms.vis){
+ visual.setDimension(w, ih);
+ g.drawImage(visual.getImage(), w/2, h/2, 3);
+ }
+ if(Rms.isLyric && lrc!=null) {
+ try {
+ GraphicsUtil.drawCenter(g, lrc.get5Lines((int) getPlayer().getCurrentTime()));
+ } catch (Exception e) {}
+ }
+ g.setColor(Skin.valuet);
+ g.drawString(current.getTitle(), 9, 2, 20);
+ //drawSoft(g);
+ }
+
+ private void drawPlayerCanvas(Graphics g) {
+ g.setColor(Skin.background);
+ g.fillRect(0, 0, w, h);
+ GraphicsUtil.drawTitle(g, Util.getTime(), im, mode==PLAYER_MODE);
+ int fh = GraphicsUtil.getHeightFont(GraphicsUtil.SMALL_BOLD_FONT)+2;
+ int py = fh+fh/2;
+ g.setFont(GraphicsUtil.getFont(GraphicsUtil.MEDIUM_BOLD_FONT));
+ //Данные о треке
+ Track current = getPlayer().getTrack();
+ //Исполнитель
+ String data = current.getArtist();
+ g.drawImage(im.artist, 2, py, 20);
+ if (data != null) py = GraphicsUtil.drawText(g, scrollText(data, 0), py, 0);
+ //Спящий режим
+ if(Rms.slpmode) g.drawImage(im.sleep, w-2, py+2, Graphics.RIGHT | Graphics.TOP);//g.drawString("S", 2, py+15+3*fh, 20);
+ //Заголовок
+ data = current.getTitle();
+ g.drawImage(im.track, 1, py, 20);
+ if (data != null) py = GraphicsUtil.drawText(g, scrollText(data, 1), py, 1);
+ //Альбом
+ data = current.getAlbum();
+ g.drawImage(im.album, 2, py, 20);
+ if (data != null) py = GraphicsUtil.drawText(g, scrollText(data, 2), py, 2);
+
+ if(Rms.isLyric && lrc!=null) py = GraphicsUtil.drawText(g, scrollText(lrc.getLine((int) getPlayer().getCurrentTime()), 3), py, 3);
+ //Индикатор прогресса
+ float div = ((float)w - 10) / (float)current.getDuration();
+ g.setColor(Skin.valuet);
+ int mgt = (int) getPlayer().getCurrentTime();
+ int k = im.statusBarleftWidth+3;
+ GraphicsUtil.drawRect(g, Skin.softUp1, Skin.softUp2, 5, py, (int)(mgt * div), im.statusBarHeight);
+ for(int i=k; iih) album = Effects.Resize(album, ih*album.getWidth()/album.getHeight(), ih);
+ g.drawImage(album, w/2, py+15, 17);
+ }else if(Rms.vis){
+ int ih = h-fh-2-py-20;
+ visual.setDimension(ih, ih);
+ g.drawImage(visual.getImage(), w/2, py+15, 17);
+ }
+ drawSoft(g);
+ }
+
+ /**
+ * Отрисовка меню
+ * @param g
+ * @param cur
+ * @param y
+ */
+ private void drawMenu(Graphics g, int cur, int y) {
+ GraphicsUtil.ACLS(g, 180, 0x00);
+ int fh = GraphicsUtil.getHeightFont(GraphicsUtil.MEDIUM_BOLD_FONT)+2;
+ int x = w/2-menuwidth/2;
+ for(int i=0; i=m.length) mcur=0;
+ break;
+ case FIRE:
+ menuAction(mcur);
+ break;
+ }
+ }else if(vis) {
+ switch (ga) {
+ case UP:
+ case LEFT:
+ Rms.visid--;
+ if(Rms.visid<0) Rms.visid=MAX_VISUALS;
+ initVisual();
+ break;
+ case DOWN:
+ case RIGHT:
+ Rms.visid++;
+ if(Rms.visid>MAX_VISUALS) Rms.visid=0;
+ initVisual();
+ break;
+ }
+ if(ga==FIRE || key==-6) vis = false;
+ }else if(skin) {
+ if(ga==UP) {cy--;if(cy<4*im.statusBarHeight) cy=4*im.statusBarHeight+im.pal.getHeight()-1;}
+ else if(ga==DOWN) {cy++;if(cy>=4*im.statusBarHeight+im.pal.getHeight()) cy=4*im.statusBarHeight+1;}
+ else if(ga==LEFT) {cx--;if(cx=w/2+im.pal.getWidth()/2) cx=w/2-im.pal.getWidth()/2;}
+ else if(key==KEY_NUM0) {
+ int x = w/2-im.pal.getWidth()/2;
+ Skin.valuet = Rms.valuet = Effects.get(im.pal, cx-x, cy-4*im.statusBarHeight);
+ }
+ else if(ga==FIRE || key==-6) {
+ Rms.skinid = thisskin;
+ Skin.initSkin(Rms.skinid);
+ skin = false;
+ }
+ else if(key==-7) skin = false;
+ }else{
+ if(key==-7) rspressed = true;
+ else if(key==KEY_POUND) Rms.accel=!Rms.accel;
+ else if(key==KEY_STAR) Rms.vis=!Rms.vis;
+ else if(key==KEY_NUM0) Rms.isLyric=!Rms.isLyric;
+ else if(key== -36) volumeplus = h;//vol+;
+ else if(key== -37) volumeminus = 0;//vol-;
+ }
+ repaint();
+ }
+
+ protected void keyReleased(int key) {
+ if(menuup!=0 || menu) return;
+ int ga=getGameAction(key);
+ if(key==-7) {
+ rspressed = false;
+ if(Rms.closePlayer) getPlayer().pause();
+ Main.midlet.destroyApp(true);
+ }else if(key==KEY_NUM9) Main.midlet.dsp.setCurrent(new SetSleepMode());
+ if(key==KEY_NUM4) {
+ if(fastR) {
+ fastR = false;
+ getPlayer().play();
+ }else getPlayer().skip(-10);
+ }
+ else if(key==KEY_NUM6) {
+ if(fastF) {
+ fastF = false;
+ getPlayer().play();
+ }else getPlayer().skip(10);
+ }
+ if(ga==LEFT && key!=KEY_NUM4) newTrack(false);
+ else if(ga==RIGHT && key!=KEY_NUM6) newTrack(true);
+ if(key==KEY_NUM3) ABRepeat();
+ switch(ga) {
+ case UP:
+ case DOWN:
+ upMode();
+ break;
+ case FIRE:
+ getPlayer().playPause();
+ break;
+ }
+ repaint();
+ }
+
+ protected void keyRepeated(int key) {
+ if(key==KEY_NUM4) {
+ if(!fastR) {
+ getPlayer().rewind();
+ fastR = true;
+ }
+ }else if(key==KEY_NUM6) {
+ if(!fastF) {
+ getPlayer().fastForward();
+ fastF = true;
+ }
+ }else keyPressed(key);
+ }
+
+ public void run() {
+ while (true) {
+ try {
+ if(Rms.light) DeviceControl.setLights(0, 100);
+ final int delta = sensor.getDelta(0, Rms.sensetivity);
+ if (delta != 0) {
+ if (accelPrevDelta != 0 && (delta * accelPrevDelta) < 0) {
+ accelPrevDelta = 0;
+ } else {
+ accelPrevDelta = delta;
+
+ Runnable runnable = new Runnable() {
+
+ public void run() {
+ if (delta > 0 && Rms.accel) {
+ newTrack(true);
+ } else if (delta < 0 && Rms.accel) {
+ newTrack(Rms.listfw);
+ }
+ }
+ };
+ (new Thread(runnable)).start();
+ }
+ }
+ /*if(Rms.vis) {
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException ex) {}
+ }*/
+ if(Rms.slpmode) {
+ if(Util.checkTime()) {
+ getPlayer().pause();
+ Main.midlet.destroyApp(true);
+ }
+ }
+ if(repeat==2) {
+ int mgt = (int) getPlayer().getCurrentTime();
+ int sk = Math.abs(b-a);
+ if(mgt>=b) getPlayer().skip(-sk);
+ }
+
+ if(Rms.isLyric && getPlayer().getCurrentTime() < 3) {
+ lrc = null;
+ //Данные о треке
+ Track current = getPlayer().getTrack();
+ String at = current.getArtist()+" - "+current.getTitle();
+ if(Lyrics.isExists(at)) lrc = new Lyrics(at);
+ }
+
+ if(Rms.lastFM) {
+ //Данные о треке
+ Track current = getPlayer().getTrack();
+ String thisSong = current.getArtist()+" - "+current.getTitle();
+ if(!thisSong.equalsIgnoreCase(Rms.lastSong)) {
+ int thisTime = (int) getPlayer().getCurrentTime();
+ int allTime = (int) (current.getDuration()*50/*% проиграно*//100);
+ if(thisTime>allTime && (current.getDuration()>30) /*если трек больше 30 секунд*/) {
+ try {
+ if (Rms.md5pass.equals("")) {
+ Rms.md5pass = LastFMScrobbler.md5(Rms.password);
+ }
+ // //if (audioscrobbler == null)
+ // AudioScrobbler audioscrobbler = new AudioScrobbler("tst", "1.0", Rms.username, Rms.md5pass);
+ // audioscrobbler.connect();
+ // Thread.sleep(3000);
+ // audioscrobbler.Submit(
+ // current.getArtist(),
+ // current.getTitle(),
+ // current.getAlbum(),
+ // "1", (int)current.getDuration()
+ // );
+ long startTime = (System.currentTimeMillis()/1000)-thisTime;
+ LastFMScrobbler ms = new LastFMScrobbler("tst", "1.0", Rms.username, Rms.md5pass);
+ ms.handshake();
+ ms.scrobble(current, startTime);
+ }catch(Exception ex) {
+ Main.midlet.dsp.setCurrent(new Alert("Ошибка", ex.getMessage(), null, AlertType.INFO));
+ }
+ Rms.lastSong = thisSong;
+ }
+ }
+ }
+ }catch(Exception ex) {
+ ex.printStackTrace();
+ repaint();
+ }
+ }
+ }
+
+ private void menuAction(int i) {
+ if(m[i].equals(lang.sleepmode)) Main.midlet.dsp.setCurrent(new SetSleepMode());
+ else if(m[i].equals(Main.midlet.lang.options)) Main.midlet.dsp.setCurrent(new OptionsForm());
+ else if(m[i].equals(Main.midlet.lang.about)) Main.midlet.dsp.setCurrent(new Info(im));
+ else if(m[i].equals(Main.midlet.lang.minimise)) Main.midlet.dsp.setCurrent(null);
+ else if(m[i].equals(Main.midlet.lang.exit)) Main.midlet.destroyApp(true);
+ else if(m[i].equals(Main.midlet.lang.skin)) skin = true;
+ else if(m[i].equals(Main.midlet.lang.visual)) vis = true;
+ }
+
+ public final SPlayer getPlayer() {
+ return player;
+ }
+
+ private void upMode() {
+ mode = (byte) (1-mode);
+ initFx();
+ }
+
+ private void choiceVisual(Graphics g, int cur) {
+ g.setColor(0);
+ g.fillRect(0, 0, w, h);
+ Image kdr;
+ int ww = w-w/4;
+ visual.setDimension(ww, ww);
+ kdr = visual.getImage();
+ g.drawImage(Effects.reflection(kdr, 0.5D), w/2, 2*im.statusBarHeight, 17);
+ GraphicsUtil.drawTitle(g, Integer.toString(cur), im, mode==PLAYER_MODE);
+ }
+
+ private void choiceSkin(Graphics g, int cx, int cy) {
+ g.setColor(0);
+ int x = w/2-im.pal.getWidth()/2;
+ g.fillRect(0, 0, w, h);
+ g.drawImage(im.pal, x, 4*im.statusBarHeight, 20);
+ //cursor
+ g.setColor(0x00);
+ int dcur = 4;
+ g.drawLine(cx + 1, cy, cx + dcur, cy);
+ g.drawLine(cx - dcur, cy, cx - 1, cy);
+ g.drawLine(cx, cy - dcur, cx, cy - 1);
+ g.drawLine(cx, cy + 1, cx, cy + dcur);
+ //
+ thisskin=Effects.get(im.pal, cx-x, cy-4*im.statusBarHeight);
+ GraphicsUtil.drawTitle(g,Integer.toHexString(thisskin), im, false);
+ }
+
+ /**
+ * Инициализация смен экранов
+ */
+ private void initFx() {
+ old = Image.createImage(I.getWidth(), I.getHeight());
+ old.getGraphics().drawImage(I, 0, 0, 20);
+ if(mode==PLAYER_MODE) drawPlayerCanvas(G);
+ else if(mode==VISUAL_MODE) drawVisual(G);
+
+ int type = Util.random(0, 5);
+ animated = new AnimatedImage(I);
+ int direction = (new int[] {Canvas.UP, Canvas.DOWN, Canvas.LEFT, Canvas.RIGHT})[Util.random(0, 3)];
+ switch(type) {
+ case 1:
+ imgfx = new BlindsFx(Util.random(4,15), 1, direction);
+ break;
+ case 2:
+ imgfx = new WaveFx(Util.random(6,30), Util.random(10,95), direction);
+ break;
+ case 3:
+ imgfx = new PuzzleFx(Util.random(4,20), Util.random(4,20), 1);
+ break;
+ case 4:
+ imgfx = new WipeFx(direction, 1);
+ break;
+ case 5:
+ imgfx = new Slide2Fx(direction, 1);
+ break;
+ default:
+ imgfx = new SlideFx(Util.random(4,15), 1, direction);
+
+ }
+ animated.setFx(imgfx);
+ animated.start(1400);
+ }
+
+ /**
+ * Инициализация визуализаций
+ */
+ private void initVisual() {
+ if(Rms.visid<=5) visual = new Stars(w, h, Rms.visid-1);
+ else if(Rms.visid==6) visual = new VisualME(w, h);
+ else if(Rms.visid<=10) visual = new Plasma(w, h, Rms.visid-7);
+ else visual = new Capuchin(w, h, Rms.visid-10);
+ }
+
+ private String scrollText(String text, int id) {
+ int count = (id==3) ? lyricWidth : textWidth;
+ String tmp = text;
+ int lent = text.length();
+ int scr = lent - count;
+ try {
+ if (lent > count) {
+ tmp = text.substring(scrollPos[id], scrollPos[id] + count);
+ if(sleepPos[id] scr) {
+ scrollPos[id]--;
+ scrolldirection[id] = !scrolldirection[id];
+ } else if (scrollPos[id] < 0) {
+ scrollPos[id] = 0;
+ scrolldirection[id] = !scrolldirection[id];
+ }
+ sleepPos[id] = 0;
+ }
+ }
+ }catch(Exception ex) {tmp = text;}
+ return tmp;
+ }
+
+ /**
+ * Переключение трека
+ */
+ private void newTrack(boolean next) {
+ a=b=0; repeat = 0;
+ Main.midlet.dsp.vibrate(Rms.vibrlen);
+ if (Rms.flash) {
+ DeviceControl.setLights(0, 0);
+ DeviceControl.setLights(0, 100);
+ }
+ if(next) getPlayer().nextTrack();
+ else getPlayer().prevTrack();
+ }
+
+ private void ABRepeat() {
+ try {
+ repeat++;
+ switch (repeat) {
+ case 1: // ставим A
+ a = (int) getPlayer().getCurrentTime();
+ break;
+ case 2: // ставим B
+ b = (int) getPlayer().getCurrentTime();
+ if(a>b) {
+ int t = b; b=a; a=t;
+ }
+ break;
+ case 3: // конец повтора
+ a = b = 0;
+ repeat = 0;
+ break;
+ }
+ } catch (Exception e) {
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/Effects.java b/src/seps/Effects.java
similarity index 92%
rename from src/Effects.java
rename to src/seps/Effects.java
index 07ffd32..0c6b008 100644
--- a/src/Effects.java
+++ b/src/seps/Effects.java
@@ -1,3 +1,5 @@
+package seps;
+
import javax.microedition.lcdui.*;
/**
@@ -87,7 +89,7 @@ public class Effects {
return temp2;
}
- public static Image HSV(Image img, float hh) {
+ /*public static Image HSV(Image img, float hh) {
float[] hsb = new float[3];
int w = img.getWidth();
int h = img.getHeight();
@@ -101,12 +103,12 @@ public class Effects {
hsb = Effects.RGBtoHSV(qr, qg, qb, hsb);
hsb[0] += hh;
while(hsb[0]>360) hsb[0]-=360;
- /*if(c=='S' || c == 's') hsb[1] = hsb[1] + (float) (ch/256);
- if(c=='B' || c == 'b') hsb[2] = hsb[2] + (float) (ch/256);*/
+ //if(c=='S' || c == 's') hsb[1] = hsb[1] + (float) (ch/256);
+ //if(c=='B' || c == 'b') hsb[2] = hsb[2] + (float) (ch/256);
pixel[io] = (qa << 24) | Effects.HSVtoRGB(hsb[0], hsb[1], hsb[2]);
}
return Image.createRGBImage(pixel, w, h, true);
- }
+ }*/
public static float getHSV(int color, int c) {//0-h, 1-s, 2-v
float[] hsb = new float[3];
@@ -133,7 +135,7 @@ public class Effects {
return (qa << 24) | Effects.HSVtoRGB(hsb[0], hsb[1], hsb[2]);
}
- private static int HSVtoRGB(float h, float s, float v) {
+ public static int HSVtoRGB(float h, float s, float v) {
float qr = 0, qg = 0, qb = 0;
int r = 0, g = 0, b = 0;
if(s==0.0 && h==-1.0) return ((int)v << 16) | ((int)v << 8) | (int)v;
@@ -166,10 +168,12 @@ public class Effects {
if (b < min) min = b;
// hue
if(v==min) h=0;
- if(v==r && g>=b) h = 60 * ((g-b)/(v-min));
- if(v==r && g 0) {
+ g.drawString(strLines.elementAt(i).toString(), 1, fontHeight + 5 + y1, Graphics.LEFT | Graphics.TOP);
+ }
+ y1 = y1 + defHeight;
+ if (y1 > mh) {
+ break;
+ }
+ }
+ g.setClip(0, 0, w, h);
+ GraphicsUtil.drawTitle(g, Main.midlet.lang.about, im, false);
+ }
+
+ protected void keyPressed(int key) {
+ int ga = getGameAction(key);
+ if(ga==UP) MoveUp();
+ else if(ga==DOWN) MoveDown();
+ else if(ga==LEFT) PageUp();
+ else if(ga==RIGHT) PageDown();
+ else if(ga==FIRE || key==-6 || key==-7)
+ Main.midlet.dsp.setCurrent(Main.midlet.cnv);
+ else if(key==-6) {
+ try {
+ String url = "http://annimon.com/";
+ if(url.length()!=19) return;
+ Main.midlet.platformRequest(url);
+ } catch (ConnectionNotFoundException ex) {
+ Main.midlet.dsp.setCurrent(Main.midlet.cnv);
+ }
+ }
+ repaint();
+ }
+
+ protected void keyRepeated(int keyCode) {
+ keyPressed(keyCode);
+ }
+
+
+ protected void pointerPressed(int x, int y) {
+ int w3 = w/3;
+ int h3 = h/3;
+ if(yw3 && x<(w-w3))) keyPressed(UP);
+ else if(y>(h-h3) && (x>w3 && x<(w-w3))) keyPressed(DOWN);
+
+ if(xh3 && y<(h-h3))) keyPressed(LEFT);
+ else if(x>(w-w3) && (y>h3 && y<(h-h3))) keyPressed(RIGHT);
+
+ else if(x(h-h3)) keyPressed(-6);
+ else if(x>(w-w3) && y>(h-h3)) keyPressed(-7);
+ else if( (x>w3 && x<(w-w3)) && (y>h3 && y<(h-h3)) ) keyPressed(FIRE);
+ }
+
+ private void SetTextPar() {
+ //Разбиваем строку на массив строк
+ strLines = null;
+ strLines = new Vector();
+ String[] arr = Util.splitString(str, "\n");
+ for(int i=0; i w) {//Слово полностью не умещается в строке
+ space = i0;
+ while (jw > w) {
+ j = 0;
+ while (j < w) {
+ space++;
+ j = def.stringWidth(substr.substring(in, space));
+ }
+ space = space - 1;
+ j = def.stringWidth(substr.substring(in, space));
+ strLines.addElement(substr.substring(in, space));
+ jw = jw - j;
+ i0 = space;
+ in = space;
+ }
+ jw = 0;
+ } else {
+ i0 = space;
+ }
+ }
+ }
+ strLines.addElement(substr.substring(in, imax));
+ }
+ textheight = strLines.size() * defHeight;
+ }
+
+ private String getText(String path) {
+ DataInputStream dis = new DataInputStream(getClass().getResourceAsStream(path));
+ StringBuffer strBuff = new StringBuffer();
+ int ch = 0;
+ try {
+ while ((ch = dis.read()) != -1) {
+ strBuff.append(StringEncoder.decodeCharCP1251((byte)ch));
+ }
+ dis.close();
+ } catch (Exception e) {e.printStackTrace();}
+ return strBuff.toString();
+ }
+
+ private void MoveDown() {
+ if (textheight > mh) {
+ y0 = y0 - dy;
+ if (mh - y0 > textheight) {
+ y0 = mh - textheight;
+ }
+ }
+ }
+
+ private void MoveUp() {
+ if (textheight > mh) {
+ y0 = y0 + dy;
+ if (y0 > 0) {
+ y0 = 0;
+ }
+ }
+
+ }
+
+ private void PageUp() {
+ if (textheight > mh) {
+ y0 = y0 + mh;
+ if (y0 > 0) {
+ y0 = 0;
+ }
+ }
+ }
+
+ private void PageDown() {
+ if (textheight > mh) {
+ y0 = y0 - mh;
+ if (mh - y0 > textheight) {
+ y0 = mh - textheight;
+ }
+ }
+ }
+}
diff --git a/src/seps/Lang.java b/src/seps/Lang.java
new file mode 100644
index 0000000..3917d7e
--- /dev/null
+++ b/src/seps/Lang.java
@@ -0,0 +1,82 @@
+package seps;
+
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+/**
+ *
+ * @author aNNiMON
+ */
+public class Lang {
+
+ String back, exit, ok, no;
+ String about, sleepmode, options, minimise;
+ String sensetivity, textfolder, vibro, skin, visual,
+ light, start, stop, flashlight, tooff, accel, msapi,
+ api, scrobbling, listforward, login, pass;
+
+ public Lang(int id) {
+ // Общие
+ msapi = "MultimediaServices";
+ api = " API";
+ ok = "Ok";
+ //English
+ if(id==0) {
+ back = "Back";
+ no = "No";
+ accel = "Accelerometer";
+ //Menu
+ sleepmode = "Sleep Mode";
+ visual = "Visualization";
+ skin = "Skin";
+ options = "Options";
+ about = "About";
+ minimise = "Minimize";
+ exit = "Exit";
+ //SleepMode
+ tooff = "Time to turn off (in minutes):";
+ //Options
+ sensetivity = "Sensetivity to switch:";
+ textfolder = "Folder with the text:";
+ vibro = "Vibration switch (in ms):";
+ light = "Backlight";
+ start = "Launch player when program start";
+ stop = "Close player when program exit";
+ flashlight = "Flash backlight";
+ listforward = "List Forward";
+ scrobbling = "LastFM scrobbling";
+ login = "Login LastFM";
+ pass = "Password";
+
+ }else{
+ back = "Назад";
+ exit = "Выход";
+ no = "Нет";
+
+ accel = "Акселерометр";
+
+ about = "О программе";
+ sleepmode = "Спящий режим";
+ options = "Настройки";
+ minimise = "Свернуть";
+ sensetivity = "Чувствительность к переключению:";
+ textfolder = "Папка с текстами:";
+ vibro = "Вибрация при переключении (в мс):";
+ skin = "Скин";
+ visual = "Визуализации";
+ light = "Постоянная подсветка";
+ start = "Запускать плеер при старте программы";
+ stop = "Закрывать плеер при выходе из программы";
+ flashlight = "Мигание подсветкой";
+ scrobbling = "LastFM скробблинг";
+ tooff = "Врямя до выключения (в минутах):";
+ listforward = "Листать вперед";
+ login = "Логин LastFM";
+ pass = "Пароль";
+ }
+ }
+
+
+}
diff --git a/src/Lyrics.java b/src/seps/Lyrics.java
similarity index 60%
rename from src/Lyrics.java
rename to src/seps/Lyrics.java
index f1dd213..b48545e 100644
--- a/src/Lyrics.java
+++ b/src/seps/Lyrics.java
@@ -1,4 +1,7 @@
+package seps;
+
+import com.annimon.StringEncoder;
import java.io.*;
import java.util.Vector;
import javax.microedition.io.*;
@@ -61,8 +64,8 @@ public class Lyrics {
}
return l5;
}
-
- public static final boolean isExists(String lyricsname) {
+
+ public static boolean isExists(String lyricsname) {
boolean r = false;
FileConnection fc;
try {
@@ -92,7 +95,6 @@ public class Lyrics {
is.close();
fc.close();
} catch (Exception e) {
- e.printStackTrace();
return null;
}
return sb.toString();
@@ -143,7 +145,7 @@ public class Lyrics {
* @return
*/
private boolean isNumChar(char ch) {
- return ch >= '0' && ch <= '9';
+ return Character.isDigit(ch);//ch >= '0' && ch <= '9';
}
/**
@@ -170,65 +172,4 @@ public class Lyrics {
//int ms = Integer.parseInt(in.substring(in.indexOf('.')+1, in.indexOf(']')));
return ss+(mm*60);
}
-
- /**
- * Преобразовывает все неинтернет ссылки в нормальные, например убирая пробелы или лишние символы.
- * @param url - исходный адрес
- * @return - правильный адрес на выходе
-
- private String urlName(String url) {
- if (url == null) return null;
- StringBuffer sb = new StringBuffer();
- for (int i = 0; i < url.length(); i++) {
- char ch = url.charAt(i);
- switch (ch) {
- default:
- if (ch < '\200') {
- sb.append(ch);
- break;
- }
- if (ch > '\177' && ch < '\u0800') {
- sb.append('%');
- sb.append(Integer.toHexString((ch >> 6 | 0xc0) + 256).substring(1));
- sb.append('%');
- sb.append(Integer.toHexString((ch & 0x3f | 0x80) + 256).substring(1));
- break;
- }
- if (ch > '\u07FF' && ch < '\0') {
- sb.append('%');
- sb.append(Integer.toHexString((ch >> 12 | 0xe0) + 256).substring(1));
- sb.append('%');
- sb.append(Integer.toHexString((ch >> 6 & 0x3f | 0x80) + 256).substring(1));
- sb.append('%');
- sb.append(Integer.toHexString((ch & 0x3f | 0x80) + 256).substring(1));
- }
- break;
- case 0: //'\0'
- case 32: sb.append("%20"); break;// ' '
- case 61: sb.append("%3d"); break;// '='
- case 43: sb.append("%2b"); break;// '+'
- case 39: sb.append("%27"); break;// '\''
- case 46: sb.append("%2E"); break;// '.'
- case 60: sb.append("%3c"); break;// '<'
- case 62: sb.append("%3e"); break;// '>'
- case 35: sb.append("%23"); break;// '#'
- case 37: sb.append("%25"); break;// '%'
- case 38: sb.append("%26"); break;// '&'
- case 123:sb.append("%7b"); break;// '{'
- case 125:sb.append("%7d"); break;// '}'
- case 92: sb.append("%5c"); break;// '\\'
- case 94: sb.append("%5e"); break;// '^'
- case 126:sb.append("%73"); break;// '~'
- case 91: sb.append("%5b"); break;// '['
- case 93: sb.append("%5d"); break;// ']'
- case 58: sb.append("%3A"); break;// ':'
- case 47: sb.append("%2F"); break;// '/'
- case 63: sb.append("%3F"); break;// '?'
- case 45: sb.append("%2D"); break;// '-'
- case 33: sb.append("%21"); break;// '!'
- case 59: sb.append("%3B"); break;// ';'
- }
- }
- return sb.toString();
- }*/
}
diff --git a/src/seps/Main.java b/src/seps/Main.java
new file mode 100644
index 0000000..61f13b3
--- /dev/null
+++ b/src/seps/Main.java
@@ -0,0 +1,51 @@
+package seps;
+
+/*
+ * aNNiMON 2011
+ * For more info visit http://annimon.com/
+ */
+
+import javax.microedition.lcdui.*;
+import javax.microedition.midlet.*;
+
+/**
+ * @author aNNiMON
+ */
+public class Main extends MIDlet {
+
+ public Display dsp;
+ public Canv cnv;
+ public Lang lang;
+ public Images im;
+ public static Main midlet;
+
+ public Main() {
+ midlet = Main.this;
+ dsp = Display.getDisplay(Main.this);
+ }
+
+ public void startApp() {
+ Rms.restoreOptions();
+ im = new Images();
+ lang = new Lang(Rms.lngid);
+ Skin.initSkin(Rms.skinid);
+ Displayable object;
+ //При первом запуске отображаем настройки
+ if(Rms.firstStart) {
+ object = new FirstStartForm(lang);
+ }else{
+ object = cnv = new Canv(im, lang);
+ }
+ dsp = Display.getDisplay(this);
+ dsp.setCurrent(object);
+ }
+
+ public void pauseApp() {
+ }
+
+ public void destroyApp(boolean ex) {
+ Rms.saveOptions();
+ if(Rms.closePlayer) cnv.getPlayer().pause();
+ notifyDestroyed();
+ }
+}
diff --git a/src/seps/OptionsForm.java b/src/seps/OptionsForm.java
new file mode 100644
index 0000000..1f474cd
--- /dev/null
+++ b/src/seps/OptionsForm.java
@@ -0,0 +1,102 @@
+package seps;
+
+import javax.microedition.lcdui.*;
+
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+/**
+ * Экран настроек
+ * @author aNNiMON
+ */
+public class OptionsForm extends Form implements CommandListener {
+
+ private Command ok, back;
+ private TextField sensetivityTF, lyricFolderTF, vibroLenTF, loginTF, passTF;
+ private ChoiceGroup optionsCG, languageCG;
+
+ public OptionsForm() {
+ super(Main.midlet.lang.options);
+ //Инициализция команд
+ ok = new Command(Main.midlet.lang.ok, Command.OK, 1);
+ back = new Command(Main.midlet.lang.back, Command.BACK, 2);
+ //Инициализация элементов
+ sensetivityTF = new TextField(Main.midlet.lang.sensetivity, String.valueOf(Rms.sensetivity), 4, TextField.NUMERIC);
+ lyricFolderTF = new TextField(Main.midlet.lang.textfolder, Rms.lrcpath, 256, TextField.ANY);
+ vibroLenTF = new TextField(Main.midlet.lang.vibro, String.valueOf(Rms.vibrlen), 4, TextField.NUMERIC);
+ loginTF = new TextField(Main.midlet.lang.login, Rms.username, 64, TextField.ANY);
+ passTF = new TextField(Main.midlet.lang.pass, Rms.password, 64, TextField.PASSWORD);
+ languageCG = new ChoiceGroup ("Language / Язык", ChoiceGroup.EXCLUSIVE);
+ optionsCG = new ChoiceGroup ("", ChoiceGroup.MULTIPLE);
+ //Инициализация ChoiceGroup
+ initCG();
+ //Добавление всех элементов на форму
+ addAll();
+ }
+
+ /**
+ * Инициализация ChoiceGroup
+ */
+ private void initCG() {
+ languageCG.append("English", null);
+ languageCG.append("Русский", null);
+ languageCG.setSelectedIndex(Rms.lngid, true);
+
+ optionsCG.append(Main.midlet.lang.light, null);
+ optionsCG.append(Main.midlet.lang.start, null);
+ optionsCG.append(Main.midlet.lang.stop, null);
+ optionsCG.append(Main.midlet.lang.flashlight, null);
+ optionsCG.append(Main.midlet.lang.listforward, null);
+ optionsCG.append(Main.midlet.lang.scrobbling, null);
+
+ optionsCG.setSelectedIndex(0, Rms.light);
+ optionsCG.setSelectedIndex(1, Rms.startPlayer);
+ optionsCG.setSelectedIndex(2, Rms.closePlayer);
+ optionsCG.setSelectedIndex(3, Rms.flash);
+ optionsCG.setSelectedIndex(4, Rms.listfw);
+ optionsCG.setSelectedIndex(5, Rms.lastFM);
+ }
+
+ /**
+ * Добавление всех элементов на форму
+ */
+ private void addAll() {
+ append(languageCG);
+ append(sensetivityTF);
+ append(lyricFolderTF);
+ append(vibroLenTF);
+ append(optionsCG);
+ append(loginTF);
+ append(passTF);
+ addCommand(ok);
+ addCommand(back);
+ setCommandListener(this);
+ Main.midlet.dsp.setCurrent(this);
+ }
+
+ public void commandAction(Command c, Displayable d) {
+ if (c==back) Main.midlet.dsp.setCurrent(Main.midlet.cnv);
+
+ if ((c==ok || c==List.SELECT_COMMAND)) {
+ Rms.lngid = languageCG.getSelectedIndex();
+ Main.midlet.lang = new Lang(Rms.lngid);
+ Rms.sensetivity = Integer.parseInt(sensetivityTF.getString());
+ Rms.vibrlen = Integer.parseInt(vibroLenTF.getString());
+ Rms.lrcpath = lyricFolderTF.getString();
+ Rms.light = optionsCG.isSelected(0);
+ Rms.startPlayer = optionsCG.isSelected(1);
+ Rms.closePlayer = optionsCG.isSelected(2);
+ Rms.flash = optionsCG.isSelected(3);
+ Rms.listfw = optionsCG.isSelected(4);
+ Rms.lastFM = optionsCG.isSelected(5);
+ Rms.username = loginTF.getString();
+ Rms.password = passTF.getString();
+ Rms.md5pass = "";
+ Main.midlet.cnv.initMenu(Main.midlet.lang);
+ Main.midlet.dsp.setCurrent(Main.midlet.cnv);
+ }
+ }
+
+}
diff --git a/src/Rms.java b/src/seps/Rms.java
similarity index 52%
rename from src/Rms.java
rename to src/seps/Rms.java
index 312bf5a..db0d98b 100644
--- a/src/Rms.java
+++ b/src/seps/Rms.java
@@ -1,3 +1,5 @@
+package seps;
+
import java.io.*;
import javax.microedition.rms.*;
@@ -8,33 +10,47 @@ import javax.microedition.rms.*;
*/
public class Rms {
- private static final String rmsName = "SEPS";
+ private static final String rmsName = "SEPlayerService";
private static RecordStore rmsStore;
+
public static boolean firstStart = true; // первый старт
- public static int sensetivity = 800;
- public static int skinid = 0;//x820000;//0;
- public static boolean isLyric = true;
- public static String lrcpath = "c:/music/Lyrics/";
- public static boolean light = false;
- public static boolean startPlayer = true;//запускать плейер при старте программы
- public static boolean closePlayer = true;//закрывать плейер при выходе из программы
- public static int vibrlen = 200;
- public static boolean flash = true;//мигание при переключении
- public static int visid = 0;
- public static boolean statGo = false; //переключатель статистики
- public static boolean stat = false;//вести статистику
- public static boolean urlstat = true;
- public static boolean actmenu = false;
- public static boolean listfw = false;
- public static boolean vis = true;
- public static boolean accel = true;
- public static String lastSong = "";
- public static int id = 0;
- public static int lngid = 0;
-
-
- public static int dh,dm;
- public static boolean slpmode = false;
+
+ // -= Настройки API =- \\
+ public static boolean api_accel = true; //акселерометр
+ public static boolean api_mserv = true; //multimedia services
+
+ // -= Настройки запуска плеера =- \\
+ public static boolean startPlayer = true;//при старте программы
+ public static boolean closePlayer = true;//при выходе из программы
+
+ // -= Настройки режимов и опций =- \\
+ public static boolean lastFM = false; //скробблинг Last.FM
+ public static String username = ""; //Логин
+ public static String password = ""; //Пароль
+ public static String md5pass = ""; //Пароль в MD5
+
+ public static boolean vis = true; //показ визуализации
+ public static boolean isLyric = true; //тексты песен
+ public static boolean accel = true; //акселерометр
+
+ public static boolean flash = true; //мигание при переключении
+ public static boolean listfw = false; //листать вперёд
+ public static boolean light = false; //постоянная подсветка
+
+
+ public static int sensetivity = 800; //Чувствительность акселерометра
+ public static int vibrlen = 200; //Время вибрации переключения треков
+ public static int skinid = 0; //Скин
+ public static int valuet = 0xFFFFFFFF;//Цвет текста
+ public static int lngid = 0; //Язык
+ public static int visid = 0; //Тип визуализации
+
+ public static String lrcpath = "c:/music/Lyrics/";
+ public static String lastSong = "";
+
+ public static boolean slpmode = false; //Спящий режим
+ public static int dh,dm; //Время выключения при спящем режиме
+
/**
* Сохранение настроек
*/
@@ -45,25 +61,33 @@ public class Rms {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
dos.writeBoolean(firstStart);
- dos.writeInt(sensetivity);
- dos.writeInt(skinid);
- dos.writeBoolean(isLyric);
- dos.writeUTF(lrcpath);
- dos.writeBoolean(light);
+ dos.writeBoolean(api_accel);
+ dos.writeBoolean(api_mserv);
dos.writeBoolean(startPlayer);
dos.writeBoolean(closePlayer);
- dos.writeInt(vibrlen);
- dos.writeBoolean(flash);
- dos.writeInt(visid);
- dos.writeBoolean(stat);
- dos.writeUTF(lastSong);
- dos.writeInt(id);
- dos.writeBoolean(urlstat);
- dos.writeInt(lngid);
- dos.writeBoolean(actmenu);
- dos.writeBoolean(listfw);
+ //LastFM
+ dos.writeBoolean(lastFM);
+ dos.writeUTF(username);
+ dos.writeUTF(password);
+ dos.writeUTF(md5pass);
+ //Main modes
dos.writeBoolean(vis);
+ dos.writeBoolean(isLyric);
dos.writeBoolean(accel);
+ //Modes
+ dos.writeBoolean(flash);
+ dos.writeBoolean(listfw);
+ dos.writeBoolean(light);
+ //Values
+ dos.writeInt(sensetivity);
+ dos.writeInt(vibrlen);
+ dos.writeInt(skinid);
+ dos.writeInt(valuet);
+ dos.writeInt(lngid);
+ dos.writeInt(visid);
+ //Lyrics
+ dos.writeUTF(lrcpath);
+ dos.writeUTF(lastSong);
dos.flush();
options = baos.toByteArray();
dos.close();
@@ -98,28 +122,35 @@ public class Rms {
try {
DataInputStream dis = new DataInputStream(new ByteArrayInputStream(rmsStore.getRecord(1)));
firstStart = dis.readBoolean();
- sensetivity = dis.readInt();
- skinid = dis.readInt();
- isLyric = dis.readBoolean();
- lrcpath = dis.readUTF();
- light = dis.readBoolean();
+ api_accel = dis.readBoolean();
+ api_mserv = dis.readBoolean();
startPlayer = dis.readBoolean();
closePlayer = dis.readBoolean();
- vibrlen = dis.readInt();
- flash = dis.readBoolean();
- visid = dis.readInt();
- stat = dis.readBoolean();
- lastSong = dis.readUTF();
- id = dis.readInt();
- urlstat = dis.readBoolean();
- lngid = dis.readInt();
- actmenu = dis.readBoolean();
- listfw = dis.readBoolean();
+ //LastFM
+ lastFM = dis.readBoolean();
+ username = dis.readUTF();
+ password = dis.readUTF();
+ md5pass = dis.readUTF();
+ //Main modes
vis = dis.readBoolean();
+ isLyric = dis.readBoolean();
accel = dis.readBoolean();
+ //Modes
+ flash = dis.readBoolean();
+ listfw = dis.readBoolean();
+ light = dis.readBoolean();
+ //Values
+ sensetivity = dis.readInt();
+ vibrlen = dis.readInt();
+ skinid = dis.readInt();
+ valuet = dis.readInt();
+ lngid = dis.readInt();
+ visid = dis.readInt();
+ //Lyrics
+ lrcpath = dis.readUTF();
+ lastSong = dis.readUTF();
dis.close();
- } catch (Exception ex) {
- }
+ } catch (Exception ex) {}
}
}
}
diff --git a/src/SetSleepMode.java b/src/seps/SetSleepMode.java
similarity index 65%
rename from src/SetSleepMode.java
rename to src/seps/SetSleepMode.java
index e2231d1..032703f 100644
--- a/src/SetSleepMode.java
+++ b/src/seps/SetSleepMode.java
@@ -1,3 +1,5 @@
+package seps;
+
import java.util.Calendar;
import javax.microedition.lcdui.*;
@@ -7,7 +9,7 @@ import javax.microedition.lcdui.*;
* and open the template in the editor.
*/
/**
- *
+ * Класс установки спящего режима
* @author aNNiMON
*/
public class SetSleepMode extends Form implements CommandListener {
@@ -16,23 +18,20 @@ public class SetSleepMode extends Form implements CommandListener {
private TextField zw;
public SetSleepMode() {
- super(SEPS.midlet.lang.sleepmode);
- back = new Command(SEPS.midlet.lang.back, Command.BACK, 2);
- ok = new Command(SEPS.midlet.lang.ok, Command.OK, 1);
- zw = new TextField(SEPS.midlet.lang.tooff, String.valueOf(10), 2, TextField.NUMERIC);
+ super(Main.midlet.lang.sleepmode);
+ ok = new Command(Main.midlet.lang.ok, Command.OK, 1);
+ back = new Command(Main.midlet.lang.back, Command.BACK, 2);
+ zw = new TextField(Main.midlet.lang.tooff, String.valueOf(10), 2, TextField.NUMERIC);
append(zw);
addCommand(ok);
addCommand(back);
- setCommandListener(this);
- SEPS.midlet.dsp.setCurrent(this);
+ setCommandListener(SetSleepMode.this);
+ Main.midlet.dsp.setCurrent(SetSleepMode.this);
}
public void commandAction(Command c, Displayable d) {
- if (c == back) {
- SEPS.midlet.dsp.setCurrent(SEPS.midlet.cnv);
- }
-
- if (c == ok) {
+ if (c == back) Main.midlet.dsp.setCurrent(Main.midlet.cnv);
+ else if (c == ok) {
int time = Integer.parseInt(zw.getString());
if(time == 0) Rms.slpmode=false;
else {
@@ -48,9 +47,10 @@ public class SetSleepMode extends Form implements CommandListener {
}
if(dh>=24) dh=dh-24;
Rms.slpmode=true;
- Rms.dh=dh; Rms.dm=dm;
+ Rms.dh=dh;
+ Rms.dm=dm;
}
- SEPS.midlet.dsp.setCurrent(SEPS.midlet.cnv);
+ Main.midlet.dsp.setCurrent(Main.midlet.cnv);
}
}
}
diff --git a/src/seps/Skin.java b/src/seps/Skin.java
new file mode 100644
index 0000000..015b511
--- /dev/null
+++ b/src/seps/Skin.java
@@ -0,0 +1,60 @@
+package seps;
+
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+/**
+ * Скин
+ * @author aNNiMON
+ */
+public class Skin {
+
+ public static int softUp1, softUp2, softDn1, softDn2, background, line, text, valuet, inf,
+ volumeUp, volumeDn;
+
+ public static void initSkin(int skin) {
+ if(skin==1) skin = Rms.skinid = 0xFF3477d5;
+ else if(skin==2) skin = Rms.skinid = 0xFF181818;
+ else if(skin==3) skin = Rms.skinid = 0xFFCE6BA6;
+ else if(skin==4) skin = Rms.skinid = 0;
+ else if(skin==5) skin = Rms.skinid = 0xFFFFFF99;
+ background = 0xFF2F8400;
+ valuet = Rms.valuet;
+ if(skin!=0) {
+ softUp1 = Effects.changeHSV(background, 2, 0.4352941f);
+ softUp2 = Effects.changeHSV(background, 2, 0.19215685f);
+ softDn1 = Effects.changeHSV(background, 2, -0.007843137f);
+ softDn2 = Effects.changeHSV(background, 2, -0.16862747f);
+ line = Effects.changeHSV(background, 0, 22);
+ line = Effects.changeHSV(line, 2, 0.21568626f);
+ text = Effects.changeHSV(background, 0, 22);
+ text = Effects.changeHSV(text, 2, 0.082352936f);
+ inf = Effects.changeHSV(background, 2, -0.16078433f);
+ for(int i=0; i<=2; i++) {
+ float delta = Effects.getHSV(skin, i) - Effects.getHSV(background, i);
+ if(delta>-0.05 && delta<0.05) continue;
+ softUp1 = Effects.changeHSV(softUp1, i, delta);
+ softUp2 = Effects.changeHSV(softUp2, i, delta);
+ softDn1 = Effects.changeHSV(softDn1, i, delta);
+ softDn2 = Effects.changeHSV(softDn2, i, delta);
+ line = Effects.changeHSV(line, i, delta);
+ text = Effects.changeHSV(text, i, delta);
+ inf = Effects.changeHSV(inf, i, delta);
+ }
+ background = skin;
+ }else{
+ softUp1 = 0xFF57f300;
+ softUp2 = 0xFF41b500;
+ softDn1 = 0xFF2e8200;
+ softDn2 = 0xFF205900;
+ line = 0x00BB00;
+ text = 0x009900;
+ inf = 0x215B00;
+ }
+ //Цвета громкостей
+ volumeUp = (0x33 << 24) | (softDn2 & 0x00FFFFFF);
+ volumeDn = (0xAA << 24) | (softDn2 & 0x00FFFFFF);
+ }
+}
diff --git a/src/seps/TestScrobbler.java b/src/seps/TestScrobbler.java
new file mode 100644
index 0000000..552c5e9
--- /dev/null
+++ b/src/seps/TestScrobbler.java
@@ -0,0 +1,52 @@
+/*
+ * aNNiMON 2011
+ * For more info visit http://annimon.com/
+ */
+package seps;
+
+import javax.microedition.lcdui.*;
+import javax.microedition.midlet.*;
+import lastfm.LastFMScrobbler;
+import msapi.Track;
+
+/**
+ * @author aNNiMON
+ */
+public class TestScrobbler extends MIDlet {
+
+ public Display dsp;
+ public static TestScrobbler midlet;
+
+ public TestScrobbler() {
+ midlet = TestScrobbler.this;
+ dsp = Display.getDisplay(TestScrobbler.this);
+ }
+
+ public void startApp() {
+ try {
+ String user = "User";
+ String pass = "Pass";
+ String md5pass = LastFMScrobbler.md5(pass);
+ System.out.println(md5pass);
+
+ Track test = new Track();
+ test.setTitle("Blood Brothers");
+ test.setArtist("Papa Roach");
+ test.setAlbum("Infest");
+ test.setDuration(274);
+ long startTime = (System.currentTimeMillis()/1000)-180;
+ LastFMScrobbler ms = new LastFMScrobbler("tst", "1.0", user, md5pass);
+ ms.handshake();
+ ms.scrobble(test, startTime);
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+ }
+
+ public void pauseApp() {
+ }
+
+ public void destroyApp(boolean ex) {
+ notifyDestroyed();
+ }
+}
diff --git a/src/visual/Capuchin.java b/src/visual/Capuchin.java
new file mode 100644
index 0000000..dc12994
--- /dev/null
+++ b/src/visual/Capuchin.java
@@ -0,0 +1,30 @@
+package visual;
+
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+import com.sonyericsson.capuchin.*;
+import javax.microedition.lcdui.*;
+
+/**
+ * @author aNNiMON
+ */
+public class Capuchin extends Visual {
+
+ private FlashImage flashImage;
+
+ public Capuchin(int w, int h, int mode) {
+ super(w, h);
+ flashImage = null;
+ try {
+ flashImage = FlashImage.createImage(getClass().getResourceAsStream("/res/" + String.valueOf(mode) + ".swf"), null);
+ } catch (Exception ex) {}
+ }
+
+ protected void paint(Graphics g) {
+ if (flashImage != null) {
+ flashImage.render(g, 0, 0, w, h);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/visual/Plasma.java b/src/visual/Plasma.java
new file mode 100644
index 0000000..5949d82
--- /dev/null
+++ b/src/visual/Plasma.java
@@ -0,0 +1,86 @@
+/*
+ * aNNiMON 2011
+ * For more info visit http://annimon.com/
+ */
+
+package visual;
+
+import seps.Effects;
+import java.util.Random;
+import javax.microedition.lcdui.Graphics;
+import javax.microedition.lcdui.Image;
+
+/**
+ * Визуализация "Плазма"
+ * @author aNNiMON
+ */
+public class Plasma extends Visual {
+
+ private int mode;
+
+ /**
+ * Инициализация плазмы
+ * @param w - ширина области
+ * @param h - высота области
+ */
+ public Plasma(int w, int h, int mode) {
+ super(w, h);
+ this.mode = mode;
+ }
+
+ protected void paint(Graphics g) {
+ //g.drawImage(db, 0, 0, 20);
+ db = Image.createRGBImage(visual(), w, h, false);
+ }
+
+ private int[] visual() {
+ int[] pix = new int[w*h];
+ int color = 0;
+ int paletteShift =(int) (System.currentTimeMillis() / 10);
+ double ddr = (2 * Math.PI / 255);
+ for (int x = 0; x < w; x+=5) {
+ for (int y = 0; y < h; y+=5) {
+
+ switch(mode) {
+ case 0:
+ double xx = (x - w / 2D);
+ double yy = (y - h / 2D);
+ color = (int) (128 + (128 * Math.sin(Math.sqrt(xx*xx + yy*yy) / 8.0))); break;
+ case 1: color = (int) ((128 + (128 * Math.sin(x / 8D)) + 128 + (128 * Math.sin(y / 8D))) / 2); break;
+ case 2:
+ color = (int) ((
+ 128 + (128 * Math.sin(x / 16D))
+ + 128 + (128 * Math.sin(y / 8D))
+ + 128 + (128 * Math.sin((x + y) / 16D))
+ + 128 + (128 * Math.sin(Math.sqrt((x * x + y * y)) / 8D))
+ ) / 4);
+ break;
+ default:
+ color = (int) ( (64 * (1 + Math.sin(x * ddr))) +
+ 64 * (1 + Math.sin(y * ddr)) );
+ break;
+ }
+ //grf.setColor((palette((color + paletteShift) % 360) ));
+ //grf.fillRect(x, y, 5, 5);
+
+ try {
+ pix[y * w + x] = pix[y * w + x + 1] = pix[y * w + x + 2] =
+ pix[(y + 1) * w + x] = pix[(y + 1) * w + x + 1] = pix[(y + 1) * w + x + 2] =
+ pix[(y + 2) * w + x] = pix[(y + 2) * w + x + 1] = pix[(y + 2) * w + x + 2] = 0xFF000000 | (palette((color + paletteShift) % 360));
+ } catch (Exception e) {
+ }
+ }
+ }
+ return pix;
+ }
+
+
+ private int palette(int color) {
+ /*return (
+ (color << 16) |//((255-color) << 16) |
+ ((2*color) << 8) |//((((color*2) > 255) ? 255 : (color*2)) << 8) |
+ (255-color)//(((128+color) > 255) ? 255 : (128+color))
+ );*/
+ return Effects.HSVtoRGB(color, 1.0f, 1.0f);
+ }
+}
diff --git a/src/visual/Stars.java b/src/visual/Stars.java
new file mode 100644
index 0000000..332675f
--- /dev/null
+++ b/src/visual/Stars.java
@@ -0,0 +1,196 @@
+/*
+ * aNNiMON 2011
+ * For more info visit http://annimon.com/
+ */
+
+package visual;
+
+import com.annimon.GraphicsUtil;
+import java.util.Random;
+import javax.microedition.lcdui.Graphics;
+
+/**
+ * Визуализация "Звёзды"
+ * @author aNNiMON
+ */
+public class Stars extends Visual {
+
+ /** Массивы координат звёзд */
+ private int[] starx, stary, starz;
+
+ private int K,i,mode;
+ private int max, spd, cf;
+ private long time, dt;
+ private boolean up,dn, update;
+
+ /**
+ * Инициализация звёзд
+ * @param w - ширина области
+ * @param h - высота области
+ */
+ public Stars(int w, int h, int mode) {
+ super(w, h);
+ this.mode = mode;
+ update = (mode<0);
+ max = 300;
+ spd = 200;
+ K = 60;
+ rnd = new Random();
+ init(max);
+ time = System.currentTimeMillis();
+ }
+
+ protected void paint(Graphics g) {
+ g.drawImage(db, 0, 0, 20);
+ paint();
+ updateParams();
+ }
+
+ private void paint() {
+ dt = System.currentTimeMillis() - time;
+ time = System.currentTimeMillis();
+ if(K>=3) GraphicsUtil.ACLS(G, 100-K);
+ else GraphicsUtil.CLS(G);
+ for (i = 1; i0) {
+ if (starz[i] <= -200) {
+ initStar();
+ }
+ setPix((255 - 255 * (starz[i] + 200) / 2100));
+ }else{
+ if (starz[i] > 2000) {
+ initStar();
+ }
+ setPix((255-255 * (starz[i]%2100) / 2100));
+ }
+ }
+ }
+
+ /**
+ * Инициализация текущей звезды
+ */
+ private void initStar() {
+ starx[i] = rnd.nextInt(w * 4) - w * 2;
+ stary[i] = rnd.nextInt(h * 4) - h * 2;
+ starz[i] = rnd.nextInt(1900);
+ }
+
+ /**
+ * Инициализация звёзд
+ * @param max максимальное количество звёзд
+ */
+ private void init(int max) {
+ starx = new int[max];
+ stary = new int[max];
+ starz = new int[max];
+ for (i = 0; i11) max-=10; break;
+ case 13: if(update) if(max<1000) init(max+=100); break;
+ case 4: if(K<84) K+=15; break;
+ case 14: if(K>16) K-=15; break;
+ case 6: if(update) mode = rnd.nextInt(4); break;
+ }
+ try {
+ if(spd<25 && spd>-25) Thread.sleep(10);
+ else Thread.sleep(40);
+ } catch (InterruptedException ex) {}
+ }
+
+ /**
+ * Отрисовка точки (звезды)
+ * @param c - цвет
+ */
+ private void setPix(int c) {
+ int sx, sy, sx1 = 0, sy1 = 0;
+ sx = (w / 2 + starx[i] * 200 / (starz[i] + 200));
+ sy = (h / 2 - stary[i] * 200 / (starz[i] + 200));
+ if(c>255) c=255;
+ else if(c<0) c=0;
+ switch(mode) {
+ case 1:
+ G.setColor(c, c, c);
+ int u = (starz[i]==0) ? 1 : starz[i];
+ G.fillArc(sx, sy, c/u, c/u, 0, 360);
+ break;
+ case 2:
+ u=rnd.nextInt(6);
+ switch(u) {
+ case 0: G.setColor(255-c, c, c); break;
+ case 1: G.setColor(c, 255-c, c); break;
+ case 2: G.setColor(c, c, 255-c); break;
+ case 3: G.setColor(255-c, 255-c, c); break;
+ case 4: G.setColor(255-c, c, 255-c); break;
+ case 5: G.setColor(c, 255-c, 255-c); break;
+ case 6: G.setColor(255-c, 255-c, 255-c); break;
+ }
+ if(i!=22) G.drawLine(sx, sy, sx, sy);
+ else try{G.fillRoundRect(sx, sy, starz[i]/(255-c), starz[i]/(255-c), i, i);}catch(Exception ex) {}; break;
+ case 3:
+ u=rnd.nextInt(6);
+ switch(u) {
+ case 0: G.setColor(255-c, c, c); break;
+ case 1: G.setColor(c, 255-c, c); break;
+ case 2: G.setColor(c, c, 255-c); break;
+ case 3: G.setColor(255-c, 255-c, c); break;
+ case 4: G.setColor(255-c, c, 255-c); break;
+ case 5: G.setColor(c, 255-c, 255-c); break;
+ case 6: G.setColor(255-c, 255-c, 255-c); break;
+ }
+ u=starz[i]==0?1:starz[i];
+ G.fillArc(sx, sy, c/u, c/u, 0, 360);
+ break;
+ case 4:
+ u=rnd.nextInt(6);
+ switch(u) {
+ case 0: G.setColor(255-c, c, c); break;
+ case 1: G.setColor(c, 255-c, c); break;
+ case 2: G.setColor(c, c, 255-c); break;
+ case 3: G.setColor(255-c, 255-c, c); break;
+ case 4: G.setColor(255-c, c, 255-c); break;
+ case 5: G.setColor(c, 255-c, 255-c); break;
+ case 6: G.setColor(255-c, 255-c, 255-c); break;
+ }
+ if(i>1) {
+ sx1 = (w / 2 + starx[i-1] * 200 / (starz[i-1] + 200));
+ sy1 = (h / 2 - stary[i-1] * 200 / (starz[i-1] + 200));
+ }
+ G.drawLine(sx1, sy1, sx, sy);
+ break;
+ default:
+ G.setColor(c, c, c);
+ if(i!=22) G.drawLine(sx, sy, sx, sy);
+ else try{G.fillRoundRect(sx, sy, starz[i]/(255-c), starz[i]/(255-c), i, i);}catch(Exception ex) {};
+ break;
+ }
+ }
+
+}
diff --git a/src/visual/Visual.java b/src/visual/Visual.java
new file mode 100644
index 0000000..35b045e
--- /dev/null
+++ b/src/visual/Visual.java
@@ -0,0 +1,70 @@
+/*
+ * aNNiMON 2011
+ * For more info visit http://annimon.com/
+ */
+
+package visual;
+
+import java.util.Random;
+import javax.microedition.lcdui.Graphics;
+import javax.microedition.lcdui.Image;
+
+/**
+ *
+ * @author aNNiMON
+ */
+public abstract class Visual {
+
+ /** Изображение хранит содержимое визуализации */
+ Image db;
+ /** Графика изображения */
+ Graphics G;
+ /** Размеры рисуемой области */
+ int w, h;
+ /** Генератор псевдослучайных чисел */
+ Random rnd;
+
+ /**
+ * Инициализация визуализации
+ * @param w - ширина области
+ * @param h - высота области
+ */
+ public Visual(int w, int h) {
+ this.w = w;
+ this.h = h;
+ db = Image.createImage(w, h);
+ G = db.getGraphics();
+ }
+
+ /**
+ * Отрисовка визуализации
+ * @param g Graphics
+ */
+ protected abstract void paint(Graphics g);
+
+ /**
+ * Получение изображения визуализации
+ * @return Image
+ */
+ public Image getImage() {
+ paint(G);
+ return db;
+ }
+
+ /**
+ * Изменение размера визуализации
+ * @param w - ширина области
+ * @param h - высота области
+ */
+ public void setDimension(int w, int h) {
+ if(this.w != w && this.h != h) {
+ this.w = w;
+ this.h = h;
+ db = Image.createImage(w, h);
+ G = db.getGraphics();
+ G.setColor(0);
+ G.fillRect(0, 0, w, h);
+ }
+ }
+
+}
diff --git a/src/Engine2.java b/src/visual/VisualME.java
similarity index 57%
rename from src/Engine2.java
rename to src/visual/VisualME.java
index 0c02377..892f882 100644
--- a/src/Engine2.java
+++ b/src/visual/VisualME.java
@@ -1,74 +1,54 @@
+/*
+ * aNNiMON 2011
+ * For more info visit http://annimon.com/
+ */
-//import com.nokia.mid.ui.DeviceControl;
-import javax.microedition.lcdui.*;
+package visual;
+
+import com.annimon.GraphicsUtil;
import java.util.Random;
+import javax.microedition.lcdui.Graphics;
-public class Engine2 implements Runnable {
+/**
+ * Визуализация "Щупальца"
+ * @author aNNiMON
+ */
+public class VisualME extends Visual {
- private Graphics G;
- private Image db;
private int S = 15;//ветви
private int N = 20;//гибкость
private int K = 60;
- private float L = (float) 1/1;
private int T = 0; //0-4 //line,time,rect
private int U = 9;
- private int w,h;
-
+ private float L = (float) 1/1;
+
private boolean rb, gb, bb;
private float x, y, tx, ty, k, d, len;
private int rc, gc, bc, rgb, fr, ar;
private float[] a = new float[40];
- private Random rnd;
- private Thread thr;
- public boolean run;
-
- public Engine2(int w, int h) {
- this.w=w;
- this.h=h;
- db = Image.createImage(w, h);
- G = db.getGraphics();
+
+ /**
+ * Инициализация щупалец
+ * @param w - ширина области
+ * @param h - высота области
+ */
+ public VisualME(int w, int h) {
+ super(w, h);
rnd = new Random();
rc = gc = bc = 0;
- ar=(rnd.nextInt() >>> 1) % 14;
- fr=((rnd.nextInt()>>>1)%6)+1;
+ ar=rnd.nextInt(14);
+ fr=rnd.nextInt(6)+1;
rgb = 1;
- thr = new Thread(this);
- thr.start();
}
-
- public void run() {
- while (run) {
- int r = (rnd.nextInt() >>> 1) % 26;
- switch(r) {
- case 3: ar=(rnd.nextInt() >>> 1) % 14; break;//color
- case 4: if(K<84) K+=15; break;
- case 5: fr=((rnd.nextInt()>>>1)%6)+1; break;//formula
- case 6: T = (rnd.nextInt() >>> 1) % 3; break;//фигуры
- case 7: S += 4; break;
- case 8: N += 5; if(N>=40) N=40; break;
- case 9: N -= 5; if(N<5) N=5; break;
- case 10: L = (float) 1/((rnd.nextInt() >>> 1)%8); break;
- case 11: U=(rnd.nextInt() >>> 1) % 9; break;
- case 14: if(K>16) K-=15; break;
- }
- try {
- Thread.sleep(2000L);
- } catch (InterruptedException ex) {}
- }
- }
-
- public void setRun(boolean run) {
- this.run=run;
- }
-
- public Image MainCanvas() {
- rgb(G);
+
+ protected void paint(Graphics g) {
+ g.drawImage(db, 0, 0, 20);
+ rgb();
visual(G);
- return db;
+ updateParams();
}
-
- private void rgb(Graphics grf) {
+
+ private void rgb() {
switch(rgb) {
case 1:
rc++;
@@ -114,7 +94,7 @@ public class Engine2 implements Runnable {
break;
}
}
-
+
private void visual(Graphics grf) {
len = (float) (w>h?h:w) / L / N;
k = (float) (Math.abs(rnd.nextFloat() * 360) * Math.PI / 180);
@@ -131,36 +111,38 @@ public class Engine2 implements Runnable {
for (int j = 0; j < S; j++) {
x = (float) (0.5 * w);
y = (float) (0.5 * h);
+ float temp1 = j * d + a[1];
for (int i = 1; i < N; i++) {
+ float temp2 = j * d + a[i];
grf.setColor(rc, gc, bc);
if (fr == 1) {
- tx = (float) (x + Math.cos(j * d + a[1]) * len);
- ty = (float) (y + Math.sin(j * d + a[i]) * len);
- x = x + (float) (Math.cos(j * d + a[i]) * len);
+ tx = (float) (x + Math.cos(temp1) * len);
+ ty = (float) (y + Math.sin(temp2) * len);
+ x = x + (float) (Math.cos(temp2) * len);
}else if (fr == 2) {
- tx = (float) (x + Math.sin(j * d + a[i]) * len);
- ty = (float) (y + Math.cos(j * d + a[i]) * len);
+ tx = (float) (x + Math.sin(temp2) * len);
+ ty = (float) (y + Math.cos(temp2) * len);
}else if (fr == 3) {
- tx = (float) (x + Math.tan(j * d + a[1]) * len);
- ty = (float) (y + Math.cos(j * d + a[i]) * len);
- y = y - (float) (Math.sin(j * d + a[i]) * len);
+ tx = (float) (x + Math.tan(temp1) * len);
+ ty = (float) (y + Math.cos(temp2) * len);
+ y = y - (float) (Math.sin(temp2) * len);
}else if (fr == 4) {
- tx = (float) (x + Math.tan(j * d + a[1]) * len);
- ty = (float) (y + Math.cos(j * d + a[i]) * len);
- x = y - (float) (Math.sin(j * d + a[i]) * len);
+ tx = (float) (x + Math.tan(temp1) * len);
+ ty = (float) (y + Math.cos(temp2) * len);
+ x = y - (float) (Math.sin(temp2) * len);
}else if (fr == 5) {
- tx = (float) (x + Math.tan(j * d + a[1]) * len);
- ty = (float) (y + Math.cos(j * d + a[i]) * len);
- x = (float) (x * ty * d + a[i] - (float) (Math.sin(j * d + a[i]) * len));
+ tx = (float) (x + Math.tan(temp1) * len);
+ ty = (float) (y + Math.cos(temp2) * len);
+ x = (float) (x * ty * d + a[i] - (float) (Math.sin(temp2) * len));
}else if (fr == 6) {
- tx = (float) (x + Math.cos(j * d + a[1]) * len);
- ty = (float) (y + Math.sin(j * d + a[1]) * len);
- x = x + (float) (Math.sin(j * d + a[i]) * len);
- y = y + (float) (Math.cos(j * d + a[i]) * len);
- tx = (float) (x + Math.cos(j * d + a[1]) * len);
- ty = (float) (y + Math.sin(j * d + a[1]) * len);
- x = x + (float) (Math.sin(j * d + a[i]) * len);
- y = y + (float) (Math.cos(j * d + a[i]) * len);
+ tx = (float) (x + Math.cos(temp1) * len);
+ ty = (float) (y + Math.sin(temp1) * len);
+ x = x + (float) (Math.sin(temp2) * len);
+ y = y + (float) (Math.cos(temp2) * len);
+ tx = (float) (x + Math.cos(temp1) * len);
+ ty = (float) (y + Math.sin(temp1) * len);
+ x = x + (float) (Math.sin(temp2) * len);
+ y = y + (float) (Math.cos(temp2) * len);
}
if (ar == 2) {
grf.setColor(255, (255 - 255 * i / N), 0);
@@ -196,20 +178,33 @@ public class Engine2 implements Runnable {
y = ty;
}
}
- if(K>=3) ACLS(grf);
- else CLS(grf);
+ if(K>=3) GraphicsUtil.ACLS(grf, 100-K);
+ else GraphicsUtil.CLS(grf);
}
- private void CLS(Graphics g) {
- g.setColor(Canv.background);
- g.fillRect(0, 0, w, h);
- }
-
- private void ACLS(Graphics g) {
- int[] pixelArray = new int[w * h];
- for (int io = 0; io < pixelArray.length; io++) {
- pixelArray[io] = (int)(100-K << 24) | Canv.background & 0x00ffffff;
+
+ /**
+ * Обновление параметров
+ */
+ private void updateParams() {
+ int r = rnd.nextInt(26);
+ switch(r) {
+ case 3: ar = rnd.nextInt(14); break;//color
+ case 4: if(K<84) K+=15; break;
+ case 5: fr = rnd.nextInt(6)+1; break;//formula
+ case 6: T = rnd.nextInt(3); break;//фигуры
+ case 7: S += 4; break;
+ case 8: N += 5; if(N>=40) N=40; break;
+ case 9: N -= 5; if(N<5) N=5; break;
+ case 10: L = (float) 1/rnd.nextInt(8); break;
+ case 11: U=rnd.nextInt(9); break;
+ case 14: if(K>16) K-=15; break;
}
- g.drawRGB(pixelArray, 0, w, 0, 0, w, h, true);
+ try {
+ Thread.sleep(25);
+ } catch (InterruptedException ex) {}
}
+
+
+
}