diff --git a/src/4.swf b/src/4.swf index 079d0a7..60b3f77 100644 Binary files a/src/4.swf and b/src/4.swf differ diff --git a/src/5.swf b/src/5.swf deleted file mode 100644 index 60b3f77..0000000 Binary files a/src/5.swf and /dev/null differ diff --git a/src/6.swf b/src/6.swf deleted file mode 100644 index 6773efc..0000000 Binary files a/src/6.swf and /dev/null differ diff --git a/src/Canv.java b/src/Canv.java index 629b9c1..db8f84d 100644 --- a/src/Canv.java +++ b/src/Canv.java @@ -2,10 +2,11 @@ import com.nokia.mid.ui.DeviceControl; import com.sonyericsson.multimedia.*; import com.sonyericsson.multimedia.control.*; import java.io.IOException; -import java.util.Calendar; +import java.util.*; import javax.microedition.io.Connector; import javax.microedition.lcdui.*; import javax.microedition.sensor.*; +import mobscrob.scrobbler.AudioScrobbler; /* * To change this template, choose Tools | Templates @@ -18,25 +19,47 @@ import javax.microedition.sensor.*; */ public class Canv extends Canvas implements Runnable, MediaControlListener { - //public static int softUp1 = 0xFF242424, softUp2 = 0x87282828, softDn1 = 0x87151515, softDn2 = 0xFF181818, background = 0x00, - // line = 0x00BB00, text = 0x009900, valuet = 0x0000E6, inf = 0x992235; public static int softUp1, softUp2, softDn1, softDn2, background, line, text, valuet, inf; + private boolean rspressed; + + //Меню + private String[] m = new String[] {SEPS.midlet.lang.sleepmode, + SEPS.midlet.lang.findtext, SEPS.midlet.lang.visual, SEPS.midlet.lang.skin, SEPS.midlet.lang.options, SEPS.midlet.lang.about, + SEPS.midlet.lang.minimise, SEPS.midlet.lang.exit}; + private int menuwidth, menuheight, mcur, menuy, menuup; + private boolean menu, skin, vis; + private int volumeplus, volumeminus; //визуализация изменения громкости + private boolean fastF, fastR; //быстрая перемотка + private int cx, cy, thisskin;//выбор скина + private int chngx, chngmode;//переключение mode (all, visual) + private int accelPrevDelta = 0; + + //Скролллинг текста (исп, трек, альб, текст) + 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 Image old; private int w,h; - private boolean lite; private int mode; - private int accelPrevDelta = 0; private Lyrics lrc; public RateImpl ri; + private Engine1 e1, tmpe1; + private Engine2 e2, tmpe2; + private Object tmpswf; + private Images im; + private FWCashe mfwc; private byte repeat;//функция повтора private int a,b; public Object swf; + private boolean updateAlbum; private Image I, album; - private Engine2 e2; private Graphics G; private Thread thr; private final Font medFont = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_BOLD, Font.SIZE_MEDIUM); @@ -51,22 +74,36 @@ public class Canv extends Canvas implements Runnable, MediaControlListener { private SensorConnection sensor; private String URL; - public Canv() { + public Canv(Images im) { setFullScreenMode(true); - thr = new Thread(this); - thr.start(); - lite = false; - repeat = 0; - mode = 0; //Режим плейера w = getWidth(); - h = getHeight(); + volumeminus = h = getHeight(); I = Image.createImage(w, h); G = I.getGraphics(); + this.im = im; + thr = new Thread(this); + thr.start(); + lyricWidth = w/(smallFont_b.charWidth('a')+1); + textWidth = lyricWidth - 3; + mfwc = FWCashe.getCache(medFont); + menuwidth = mfwc.stringWidth(m[0]); + menuheight = m.length * (medFont.getHeight()+2); + for(int i=1; imenuwidth) menuwidth = mfwc.stringWidth(m[i]); + } + menuwidth+=6; + menuy = 2*im.statusBarHeight-menuheight; + updateAlbum = menu = rspressed = false; + volumeplus = menuup = mcur = chngx = repeat = 0; + mode = 0; //Режим плейера getInfo(); service = MultimediaServiceManager.getMultimediaService("MediaPlayer"); mediaControl = (MediaControl)service.getControl("MediaControl"); mediaControl.addMediaControlListener(this); - if(Rms.visid!=0) swf = new Capuchin(Rms.visid); + cx = w/2; + cy = 4*im.statusBarHeight+im.pal.getHeight()/2; + if(Rms.visid>=6) Rms.visid = 1; + if(Rms.visid>1) swf = new Capuchin(Rms.visid); if(Rms.stat) { ri = new RateImpl(); ri.open(); @@ -74,34 +111,134 @@ public class Canv extends Canvas implements Runnable, MediaControlListener { if(Rms.startPlayer) playTrack(); } + protected void sizeChanged(int w, int h) { + w = getWidth(); + h = getHeight(); + volumeminus = h = getHeight(); + I = Image.createImage(w, h); + G = I.getGraphics(); + lyricWidth = w/(smallFont_b.charWidth('a')+1); + textWidth = lyricWidth - 3; + cx = w/2; + super.sizeChanged(w, h); + } + protected void paint(Graphics g) { - if(mode==0) drawPlayerCanvas(G); - else if(mode==1) drawVisual(G); - g.drawImage(I, 0, 0, 20); + setFullScreenMode(true); + //Выбор визуализации + if(vis) {choiceVisual(g, Rms.visid); return;} + if(skin) {choiceSkin(g, cx, cy); return;} + //Переключение режимов (all, visual) + if(chngx>0) { + if(old==null) { + old = Image.createImage(I.getWidth(), I.getHeight()); + old.getGraphics().drawImage(I, 0, 0, 20); + if(mode==0) drawPlayerCanvas(G); + else if(mode==1) drawVisual(G); + if(chngmode<3) chngx = h; + else chngx = w; + } + switch(chngmode) { + case 0: + g.drawImage(I, 0, -chngx, 20); + g.drawImage(old, 0, h-chngx, 20); + break; + case 1: + g.drawImage(I, 0, chngx, 20); + g.drawImage(old, 0, chngx-h, 20); + break; + case 2: + g.drawImage(old, 0, 0, 20); + g.drawRegion(I, 0, 0, w, h/2, 0, 0, -chngx/2, 20); + g.drawRegion(I, 0, h/2, w, h/2, 0, 0, h/2+chngx/2, 20); + break; + case 3: + g.drawImage(I, 0, 0, 20); + g.drawRegion(old, 0, 0, w, h/2, 0, 0, chngx/2-h/2, 20); + g.drawRegion(old, 0, h/2, w, h/2, 0, 0, -chngx/2+h, 20); + break; + case 4: + g.drawImage(I, -chngx, 0, 20); + g.drawImage(old, w-chngx, 0, 20); + break; + case 5: + g.drawImage(I, chngx, 0, 20); + g.drawImage(old, chngx-w, 0, 20); + break; + case 6: + g.drawImage(old, 0, 0, 20); + g.drawRegion(I, 0, 0, w/2, h, 0, -chngx/2, 0, 20); + g.drawRegion(I, w/2, 0, w/2, h, 0, w/2+chngx/2, 0, 20); + break; + default: + g.drawImage(I, 0, 0, 20); + g.drawRegion(old, 0, 0, w/2, h, 0, chngx/2-w/2, 0, 20); + g.drawRegion(old, w/2, 0, w/2, h, 0, -chngx/2+w, 0, 20); + break; + } + chngx-=4; + repaint(); + }else{ + if(mode==0) drawPlayerCanvas(G); + else if(mode==1) drawVisual(G); + g.drawImage(I, 0, 0, 20); + //Меню + if(menuup!=0) { + if(menuup>0) { + menuy-=25; + if(menuy<=2*im.statusBarHeight-menuheight) {menu = false; menuup=0;} + } else { + menuy+=25; + if(menuy>=2*im.statusBarHeight) {menu = true; menuup=0;} + } + drawMenu(g, mcur, menuy); + }else if(menu) drawMenu(g, mcur, menuy); + //Визуализации изменения громкости + if(volumeplus>0) { + drawRect(g, 0x33000000, 0xAA000000, 0, volumeplus-20, w, 20); + drawRect(g, 0xAA000000, 0x33000000, 0, volumeplus, w, 20); + volumeplus-=10; + } + if(volumeminusih) album = Effects.Resize(album, ih*album.getWidth()/album.getHeight(), ih); g.drawImage(album, w/2, h/2, 3); }else if(Rms.vis){ - int ih = h-(2*medFont.getHeight())-6; if(Rms.visid==0) { if(e2==null) { - e2 = new Engine2(w-6, ih); + e2 = new Engine2(w, ih); e2.setRun(true); } g.drawImage(e2.MainCanvas(), w/2, h/2, 3); + } else if(Rms.visid==1) { + if(e1==null) { + e1 = new Engine1(w, ih); + e1.setRun(true); + } + g.drawImage(e1.MainCanvas(), w/2, h/2, 3); } else{ ((Capuchin) swf).drawFlash(g, 3, h/2-(ih/2), w-6, ih); } @@ -113,7 +250,7 @@ public class Canv extends Canvas implements Runnable, MediaControlListener { } } } - drawSoft(g, SEPS.midlet.lang.menu, SEPS.midlet.lang.exit); + drawSoft(g); } private String getValue(MetaData metaData, String md) { @@ -128,40 +265,52 @@ public class Canv extends Canvas implements Runnable, MediaControlListener { private void drawPlayerCanvas(Graphics g) { g.setColor(background); g.fillRect(0, 0, w, h); - drawTitle(g, "SEPS by aNNiMON"); + drawTitle(g, getTime()); int fh = smallFont_b.getHeight()+2; int py = fh+fh/2; g.setFont(medFont); if (media != null) { MetaData metaData = media.getMetaData(); if (metaData != null) { - Object data = getValue(metaData, MetaData.ARTIST_KEY); - if (data != null) py = drawText(g, (String) data, py); + String data = getValue(metaData, MetaData.ARTIST_KEY); + g.drawImage(im.artist, 2, py, 20); + if (data != null) py = drawText(g, scrollText(data, 0), py, 0); data = getValue(metaData, MetaData.TITLE_KEY); - if (data != null) py = drawText(g, (String) data, py); + g.drawImage(im.track, 1, py, 20); + if (data != null) py = drawText(g, scrollText(data, 1), py, 1); data = getValue(metaData, MetaData.ALBUM_KEY); - if (data != null) py = drawText(g, (String) data, py); + g.drawImage(im.album, 2, py, 20); + if (data != null) py = drawText(g, scrollText(data, 2), py, 2); - if(Rms.isLyric && lrc!=null) py = drawText(g, lrc.getLine(media.getMediaTime()), py); + if(Rms.isLyric && lrc!=null) py = drawText(g, scrollText(lrc.getLine(media.getMediaTime()), 3), py, 3); //else if(lrc==null) py = drawText(g, String.valueOf(media.getMediaTime()), "", py); //data = metaData.getValue(metaData.FILE_URI_KEY); //if (data != null) float div = ((float)w - 10) / (float)media.getDuration(); g.setColor(valuet); int mgt = media.getMediaTime(); - g.fillRect(5, py, (int)(mgt * div), 10); + int k = im.statusBarleftWidth+3; + drawRect(g, softUp1, softUp2, 5, py, (int)(mgt * div), im.statusBarHeight); + for(int i=k; iih) album = Effects.Resize(album, ih*album.getWidth()/album.getHeight(), ih); @@ -174,32 +323,100 @@ public class Canv extends Canvas implements Runnable, MediaControlListener { e2.setRun(true); } g.drawImage(e2.MainCanvas(), w/2, py+15, 17); - } else{ + } else if(Rms.visid==1) { + if(e1==null) { + e1 = new Engine1(ih, ih); + e1.setRun(true); + } + g.drawImage(e1.MainCanvas(), w/2, py+15, 17); + }else{ ((Capuchin) swf).drawFlash(g, w/2-ih/2, py+15, ih, ih); } } g.setColor(inf); - if(Rms.vis) g.drawString("*-V", 2, py+15, 20); - if(Rms.isLyric) g.drawString("0-L", 2, py+15+(smallFont_b.getHeight()+2), 20); - if(Rms.accel) g.drawString("#-A", 2, py+15+2*(smallFont_b.getHeight()+2), 20); if(Rms.slpmode) g.drawString("S", 2, py+15+3*(smallFont_b.getHeight()+2), 20); - drawSoft(g, SEPS.midlet.lang.menu, SEPS.midlet.lang.exit); + drawSoft(g); } public void keyPressed(int key) { + if(key==-6 && !menu) { + menuup = menu?1:-1; + } + if((menuup!=0 || menu) && !vis && !skin) { + if(key==-6) { + menuup = menu?1:-1; + } + int ga=getGameAction(key); + switch (ga) { + case UP: + mcur--; + if(mcur<0) mcur=m.length-1; + break; + case DOWN: + mcur++; + if(mcur>=m.length) mcur=0; + break; + case FIRE: + menuAction(mcur); + break; + } + }else if(vis) { + int ga=getGameAction(key); + switch (ga) { + case UP: + case LEFT: + Rms.visid--; + if(Rms.visid<0) Rms.visid=5; + tmpswf=null; + break; + case DOWN: + case RIGHT: + Rms.visid++; + if(Rms.visid>=6) Rms.visid=0; + tmpswf=null; + break; + } + if(ga==FIRE || key==-6) { + tmpe2=null; tmpe1=null; tmpswf=null; + if(Rms.visid>1) swf = new Capuchin(Rms.visid); + vis = false; + } + }else if(skin) { + int ga=getGameAction(key); + 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(ga==FIRE || key==-6) { + Rms.skinid = thisskin; + new Skin(Rms.skinid); + 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(); + } + + public void keyReleased(int key) { + if(menuup!=0 || menu) return; int ga=getGameAction(key); if(key==-7) { + rspressed = false; if(Rms.closePlayer) pauseTrack(); SEPS.midlet.destroyApp(true); - } - if(key==-6) new Menu(); - if(key==KEY_POUND) Rms.accel=!Rms.accel; - if(key==KEY_STAR) Rms.vis=!Rms.vis; - if(key==KEY_NUM0) Rms.isLyric=!Rms.isLyric; + }else if(key==KEY_NUM9) new SetSleepMode(); if(key==KEY_NUM4) rewind(); - if(key==KEY_NUM6) fastForward(); + else if(key==KEY_NUM6) fastForward(); + if(ga==LEFT && key!=KEY_NUM4) prevTrack(); + else if(ga==RIGHT && key!=KEY_NUM6) nextTrack(); if(key==KEY_NUM3) ABRepeat(); - if(key==KEY_NUM1) { + else if(key==KEY_NUM1) { String art="",tit=""; try{ MetaData metaData = SEPS.midlet.cnv.media.getMetaData(); @@ -209,9 +426,6 @@ public class Canv extends Canvas implements Runnable, MediaControlListener { FindLyrics fl = new FindLyrics(); fl.find(art, tit);//SEPS.midlet.dsp.setCurrent(SEPS.midlet.cnv); } - if(key==KEY_NUM9) new SetSleepMode();//SEPS.midlet.dsp.setCurrent(); - if(ga==LEFT && key!=KEY_NUM4) prevTrack(); - if(ga==RIGHT && key!=KEY_NUM6) nextTrack(); switch(ga) { case UP: upMode(); @@ -231,7 +445,26 @@ public class Canv extends Canvas implements Runnable, MediaControlListener { } public void keyRepeated(int key) { - keyPressed(key); + if(key==KEY_NUM4) { + try { + if(!fastR) { + mediaControl.rewind(); + fastR = true; + } + } catch (ControlException ex) { + ex.printStackTrace(); + } + }else if(key==KEY_NUM6) { + try { + if(!fastF) { + mediaControl.fastForward(); + fastF = true; + } + } catch (ControlException ex) { + ex.printStackTrace(); + } + + }else keyPressed(key); } public int getDelta(int channel, int threshold) { @@ -285,7 +518,7 @@ public class Canv extends Canvas implements Runnable, MediaControlListener { } if(!Rms.vis) Thread.sleep(100); if(Rms.slpmode) { - if(getTime()) { + if(checkTime()) { pauseTrack(); SEPS.midlet.destroyApp(true); } @@ -307,9 +540,41 @@ public class Canv extends Canvas implements Runnable, MediaControlListener { thisSong = thisSong+" - "+ (String) data; if(!thisSong.equalsIgnoreCase(Rms.lastSong)) { int thisTime = media.getMediaTime(); - int allTime = media.getDuration()*20/*% проиграно*//100; + int allTime = media.getDuration()*50/*% проиграно*//100; if(thisTime>allTime) { int cn = 1; + + try { + //GetPass + String username = "aNMCore"; //[0] + String password = "abcdcba"; //[1] + String md5pass = ""; //[2] + if (md5pass.equals("")) { + md5pass = AudioScrobbler.GetPasswordMD5(password); + } + //if (audioscrobbler == null) + AudioScrobbler audioscrobbler = new AudioScrobbler("tst", "1.0", username, md5pass); + audioscrobbler.connect(); + Thread.sleep(3000); + audioscrobbler.Submit( + (String) getValue(metaData, MetaData.ARTIST_KEY), + (String) getValue(metaData, MetaData.TITLE_KEY), + (String) getValue(metaData, MetaData.ALBUM_KEY), + "1", media.getDuration() + ); + + /*MobScrobblerImpl ms = new MobScrobblerImpl(); + ms.scrobble( + (String) getValue(metaData, MetaData.ARTIST_KEY), + (String) getValue(metaData, MetaData.TITLE_KEY), + (String) getValue(metaData, MetaData.ALBUM_KEY), + media.getDuration(), + thisTime + );*/ + }catch(Exception ex) { + SEPS.midlet.dsp.setCurrent(new Alert("Ahtung", ex.getMessage(), null, AlertType.INFO)); + } + if(Rms.stat) { Rms.lastSong = thisSong; cn = ri.update(thisSong); @@ -444,7 +709,11 @@ public class Canv extends Canvas implements Runnable, MediaControlListener { private void fastForward() { try { - mediaControl.skip(10); + if(fastF) { + fastF = false; + mediaControl.play(); + } + else mediaControl.skip(10); } catch (ControlException ex) { ex.printStackTrace(); } @@ -452,20 +721,16 @@ public class Canv extends Canvas implements Runnable, MediaControlListener { private void rewind() { try { - mediaControl.skip(-10); + if(fastR) { + fastR = false; + mediaControl.play(); + } + else mediaControl.skip(-10); } catch (ControlException ex) { ex.printStackTrace(); } } - private boolean getTime() { - 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 void mediaControlUpdate(int eventId, ControlEvent event) { try { switch (eventId) { @@ -488,11 +753,8 @@ public class Canv extends Canvas implements Runnable, MediaControlListener { MetaData data = this.media.getMetaData(); if (data != null) { byte[] alb = data.getAlbumArt(); - if (alb != null) { - album = Image.createImage(alb, 0, alb.length); - } else { - album = null; - } + if (alb != null) album = Image.createImage(alb, 0, alb.length); + else album = null; } a = b = 0; repeat = 0; if(Rms.isLyric) initLyric(this.media); @@ -502,63 +764,135 @@ public class Canv extends Canvas implements Runnable, MediaControlListener { } + private void upMode() { + old = null; + chngmode = random(0,8); + chngx = 2; + mode = 1-mode; + e2=null; + e1=null; + if(album!=null) updateAlbum = true; + } + + private void menuAction(int i) { + if(m[i].equals(SEPS.midlet.lang.sleepmode)) SEPS.midlet.dsp.setCurrent(new SetSleepMode()); + else if(m[i].equals(SEPS.midlet.lang.findtext)) { + MetaData metaData = this.media.getMetaData(); + String all = getValue(metaData, MetaData.ARTIST_KEY) + " - " + getValue(metaData, MetaData.TITLE_KEY); + SEPS.midlet.dsp.setCurrent(new FindText(all)); + } + else if(m[i].equals(SEPS.midlet.lang.options)) SEPS.midlet.dsp.setCurrent(new Options()); + else if(m[i].equals(SEPS.midlet.lang.about)) SEPS.midlet.dsp.setCurrent(new Info()); + else if(m[i].equals(SEPS.midlet.lang.minimise)) SEPS.midlet.dsp.setCurrent(null); + else if(m[i].equals(SEPS.midlet.lang.exit)) SEPS.midlet.destroyApp(true); + else if(m[i].equals(SEPS.midlet.lang.skin)) skin = true; + else if(m[i].equals(SEPS.midlet.lang.visual)) vis = true; + } + + //GUI - GRAPHICAL USER INTERFACE + + private int drawText(Graphics g, String value, int y, int id) { + g.setColor(line); + g.drawLine(3, y-1, w-3, y-1); + g.setColor(valuet); + g.setFont(smallFont_b); + g.drawString(value, (id!=3?im.track.getWidth()+4:w/2), y, (id!=3?20:17)); + return y+(smallFont_b.getHeight()+2); + } + + private void drawMenu(Graphics g, int cur, int y) { + ACLS(g,180,0x00); + int fh = medFont.getHeight()+2; + int x = w/2-menuwidth/2; + for(int i=0; i(h-2*im.statusBarHeight)) ww = h-2*im.statusBarHeight; + if(cur==0) { + if(tmpe2==null) tmpe2 = new Engine2(ww, ww); + kdr = tmpe2.MainCanvas(); + }else if(cur==1) { + if(tmpe1==null) tmpe1 = new Engine1(ww, ww); + kdr = tmpe1.MainCanvas(); + }else { + if(tmpswf==null) tmpswf = new Capuchin(Rms.visid); + kdr = ((Capuchin)tmpswf).getImage(ww, ww); + } + g.drawImage(Effects.reflection(kdr, 0.5D), w/2, 2*im.statusBarHeight, 17); + drawTitle(g, getTime()); + } + + 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); + drawTitle(g, Integer.toHexString(thisskin)); + } + + private void drawSoft(Graphics g) { + int fh = medFont.getHeight()+2; + int wsoft = 26; + int msoft = (w-wsoft*2)/3; + g.setFont(medFont); + //Линия + g.setColor(0); + g.drawLine(0, h-fh-1, w, h-fh-1); + //Меню + drawRect(g, (menuup!=0 || menu)?softUp1:softDn1, (menuup!=0 || menu)?softUp2:softDn2, 0, h-fh, wsoft, fh); + g.setColor(valuet); + g.fillTriangle(wsoft/2, h-5, 3, h-fh+7, wsoft-3, h-fh+7); + //Выход + drawRect(g, rspressed?softUp1:softDn1, rspressed?softUp2:softDn2, w-wsoft, h-fh, wsoft, fh); + g.drawImage(im.exit, w-2, h-fh, 24); + //* - Визуализация + drawRect(g, Rms.vis?softUp1:softDn1, Rms.vis?softUp2:softDn2, wsoft, h-fh, msoft, fh); + g.drawChar('*', wsoft+msoft/6, h-fh+2, 20); + g.drawImage(im.star, wsoft+msoft-msoft/6, h-fh+fh/2, 10); + //0 - Тексты Песен + drawRect(g, Rms.isLyric?softUp1:softDn1, Rms.isLyric?softUp2:softDn2, wsoft+msoft, h-fh, w-2*(wsoft+msoft), fh); + g.drawChar('0', w/2-msoft/4, h-fh+2, 17); + g.drawImage(im.zero, w/2+msoft/4, h-fh+fh/2, 3); + // - Акселерометр + drawRect(g, Rms.accel?softUp1:softDn1, Rms.accel?softUp2:softDn2, w-wsoft-msoft, h-fh, msoft, fh); + g.drawChar('#', w-wsoft-msoft+msoft/6, h-fh+2, 20); + g.drawImage(im.pound, w-wsoft-msoft/6, h-fh+fh/2, 10); + } + private void drawTitle(Graphics g, String text) { - int fh = medFont.getHeight()+4; g.setColor(valuet); g.setFont(medFont); - if(Rms.skinid==3) {text=toEmo(text);} - g.drawString(text, w/2, 2, 17); - drawRect(g, softUp1, softUp2, 0, 0, w, fh/2); - drawRect(g, softDn1, softDn2, 0, fh/2, w, fh/2); - } - - public void drawRect(Graphics g, int color1, int color2, int x1, int y1, int w, int h) { - int a1 = (color1 >> 24) & 0xff; - int r1 = ((color1 & 0xFF0000) >> 16); - int g1 = ((color1 & 0x00FF00) >> 8); - int b1 = (color1 & 0x0000FF); - int a2 = (color2 >> 24) & 0xff; - int r2 = ((color2 & 0xFF0000) >> 16); - int g2 = ((color2 & 0x00FF00) >> 8); - int b2 = (color2 & 0x0000FF); - - int count = h / 3; - if (count < 0) { - count = -count; - } - if (count < 8) { - count = 8; - } - int crd1, crd2; - - for (int i = count - 1; i >= 0; i--) { - crd1 = i * h / count + y1; - crd2 = (i + 1) * h / count + y1; - if (crd1 == crd2) { - continue; - } - if(lite) { - g.setColor(i * (r2 - r1) / (count - 1) + r1, i * (g2 - g1) / (count - 1) + g1, i * (b2 - b1) / (count - 1) + b1); - g.fillRect(x1, crd1, w, crd2 - crd1); - }else{ - int[] pixelArray = new int[w * (crd2 - crd1)]; - for(int zi = 0; zi < pixelArray.length; zi++) - pixelArray[zi] = (int) ((i * (a2 - a1) / (count - 1) + a1) << 24) | - ((i * (r2 - r1) / (count - 1) + r1) << 16) | - ((i * (g2 - g1) / (count - 1) + g1) << 8) | (i * (b2 - b1) / (count - 1) + b1); - g.drawRGB(pixelArray, 0, w, x1, crd1, w, crd2 - crd1, true); - } - } - } - - private void drawSoft(Graphics g, String lsoft, String rsoft) { - int fh = medFont.getHeight()+2; - g.setColor(text); - g.setFont(medFont); - g.drawString(lsoft, 2, h-2, 36); - g.drawString(rsoft, w-2, h-2, 40); - drawRect(g, softUp1, softUp2, 0, h-fh, w, fh/2); - drawRect(g, softDn1, softDn2, 0, h-fh/2, w, fh/2); + int k = im.titleleft.getWidth(); + for(int i=k; i> 24) & 0xff; + int r1 = (color1 >> 16) & 0xff; + int g1 = (color1 >> 8) & 0xff; + int b1 = color1 & 0xff; + int a2 = (color2 >> 24) & 0xff; + int r2 = (color2 >> 16) & 0xff; + int g2 = (color2 >> 8) & 0xff; + int b2 = color2 & 0xff; + int beforecolor = g.getColor(); + int crd1, crd2; + int count = h/3; + if (count < 0) count = -count; + if (count < 8) count = 8; + boolean lite = false; + if(a1==0xff && a2==0xff) lite = true; + for (int i=count-1; i>=0; i--) { + crd1 = i*h/count+y1; + crd2 = (i+1)*h/count+y1; + if (crd1 == crd2) continue; + if(lite) { + g.setColor(i * (r2 - r1) / (count - 1) + r1, i * (g2 - g1) / (count - 1) + g1, i * (b2 - b1) / (count - 1) + b1); + g.fillRect(x1, crd1, w, crd2 - crd1); + }else{ + int[] pixelArray = new int[w * (crd2 - crd1)]; + for(int zi = 0; zi < pixelArray.length; zi++) + pixelArray[zi] = (int) ((i * (a2 - a1) / (count - 1) + a1) << 24) | + ((i * (r2 - r1) / (count - 1) + r1) << 16) | + ((i * (g2 - g1) / (count - 1) + g1) << 8) | (i * (b2 - b1) / (count - 1) + b1); + g.drawRGB(pixelArray, 0, w, x1, crd1, w, crd2 - crd1, true); + } } + g.setColor(beforecolor); + } + + private void ACLS(Graphics g, int a1, int color) { + int[] pixelArray = new int[g.getClipWidth() * g.getClipHeight()]; + for(int i = 0; i < pixelArray.length; i++) + pixelArray[i] = (int) (a1 << 24| color & 0x00ffffff); + g.drawRGB(pixelArray, 0, g.getClipWidth(), 0, 0, g.getClipWidth(), g.getClipHeight(), true); + } + + //Methods + + private 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); + } + + private 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(); } - private void upMode() { - mode = 1-mode; - e2=null; - album = null; + private int random(int min, int max) { + return min + ((new Random().nextInt() >>> 1)%(max-min)); } private void ABRepeat() { @@ -640,4 +1008,32 @@ public class Canv extends Canvas implements Runnable, MediaControlListener { } catch (Exception e) { } } + + private String scrollText(String text, int id) { + int count; + if(id==3) count = lyricWidth; + else count = 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; + } } \ No newline at end of file diff --git a/src/Capuchin.java b/src/Capuchin.java index db558ea..007c457 100644 --- a/src/Capuchin.java +++ b/src/Capuchin.java @@ -10,23 +10,13 @@ import javax.microedition.lcdui.*; */ public class Capuchin { - //public FlashPlayer flashPlayer; public FlashImage flashImage; - //public FlashCanvas flashCanvas; public Capuchin(int i) { -// flashPlayer = null; flashImage = null; -// flashCanvas = null; try { - flashImage = FlashImage.createImage(getClass().getResourceAsStream("/"+String.valueOf(i)+".swf"), null); -// if(flashImage != null) -// { -// flashCanvas = new FlashCanvas(flashImage); -// flashPlayer = FlashPlayer.createFlashPlayer(flashImage, flashCanvas); -// flashCanvas.setFullScreenMode(true); -// } + flashImage = FlashImage.createImage(getClass().getResourceAsStream("/"+String.valueOf(i-1)+".swf"), null); } catch(Exception ex) {} } @@ -34,4 +24,11 @@ public class Capuchin { public void drawFlash(Graphics g, int x, int y, int w, int h) { if(flashImage!=null) flashImage.render(g, x, y, w, h); } + + public Image getImage(int w, int h) { + Image img = Image.createImage(w, h); + Graphics g = img.getGraphics(); + if(flashImage!=null) flashImage.render(g, 0, 0, w, h); + return img; + } } \ No newline at end of file diff --git a/src/Effects.java b/src/Effects.java index 046bd80..07ffd32 100644 --- a/src/Effects.java +++ b/src/Effects.java @@ -6,6 +6,41 @@ import javax.microedition.lcdui.*; */ public class Effects { + + public static Image reflection(Image img, double percent) { + int w = img.getWidth(); + int h = img.getHeight(); + int[] rgb = new int[w * h]; + int[] newRgb = new int[w * (h * 2 + 1)]; + img.getRGB(rgb, 0, w, 0, 0, w, h); + double column = 255D / ((double)h * percent); + System.arraycopy(rgb, 0, newRgb, 0, rgb.length); + + for(int i=0; i=h-h*percent; j--) + { + int alpha = (rgb[j*w+i] >> 24) & 0xff; + int red = (rgb[j*w+i] >> 16) & 0xff; + int green = (rgb[j*w+i] >> 8) & 0xff; + int blue = rgb[j*w+i] & 0xff; + int alp = (int)(255D - column * (double)(h - 1 - j)); + if(alp > alpha) alp = alpha; + newRgb[(2*h-j)*w+i] = (alp << 24) | (red << 16) | (green << 8) | blue; + } + } + Image image = Image.createRGBImage(newRgb, w, h*2+1, true); + rgb = null; + newRgb = null; + return image; + } + + public static int get(Image img, int x, int y) { + int[] pixel = new int[1]; + img.getRGB(pixel, 0, img.getWidth(), x, y, 1, 1); + return pixel[0]; + } + public static Image createScaledImage(Image image, int screenWidth, int screenHeight) { int sourceWidth = image.getWidth(); int sourceHeight = image.getHeight(); @@ -51,4 +86,97 @@ public class Effects { } return temp2; } + + public static Image HSV(Image img, float hh) { + float[] hsb = new float[3]; + int w = img.getWidth(); + int h = img.getHeight(); + int[] pixel = new int[w * h]; + img.getRGB(pixel, 0, w, 0, 0, w, h); + for (int io = 0; io < pixel.length; io++) { + int qa = (pixel[io] >> 24) & 0xff; + int qr = (pixel[io] >> 16) & 0xff; + int qg = (pixel[io] >> 8) & 0xff; + int qb = pixel[io] & 0xff; + 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);*/ + 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]; + int qr = (color >> 16) & 0xff; + int qg = (color >> 8) & 0xff; + int qb = color & 0xff; + hsb = Effects.RGBtoHSV(qr, qg, qb, hsb); + return hsb[c]; + } + + public static int changeHSV(int color, int c, float value) {//0-h, 1-s, 2-v + float[] hsb = new float[3]; + int qa = (color >> 24) & 0xff; + int qr = (color >> 16) & 0xff; + int qg = (color >> 8) & 0xff; + int qb = color & 0xff; + hsb = Effects.RGBtoHSV(qr, qg, qb, hsb); + hsb[c]+=value; + if(c==0) while(hsb[0]>360) hsb[0]-=360; + else { + if(hsb[c]>1.0) hsb[c]=hsb[c]-1.0f; + else if(hsb[c]<0) hsb[c]=-hsb[c]; + } + return (qa << 24) | Effects.HSVtoRGB(hsb[0], hsb[1], hsb[2]); + } + + private 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; + int Hi = (int) ((h / 60) % 6); + float f = (float) (h / 60 - (float)Math.floor(h/60)); + float p = (float) ((float)v*(1.0f - (float)s)); + float q = (float) ((float)v*(1.0f - (float)f*(float)s)); + float t = (float) ((float)v*(1.0f - (s*(1.0-f)))); + switch(Hi) { + case 0: qr = v; qg = t; qb = p; break; + case 1: qr = q; qg = v; qb = p; break; + case 2: qr = p; qg = v; qb = t; break; + case 3: qr = p; qg = q; qb = v; break; + case 4: qr = t; qg = p; qb = v; break; + case 5: qr = v; qg = p; qb = q; break; + } + r = (int) (255 * qr); g = (int) (255 * qg); b = (int) (255 * qb); + return (r << 16) | (g << 8) | b; + } + + private static float[] RGBtoHSV(int qr, int qg, int qb, float[] hsv) { + float h = 0, s, v; + if (hsv == null) { + hsv = new float[3]; + } + float r = (float) qr/255; float g = (float) qg/255; float b = (float) qb/255; + v = (r > g) ? r : g; + if (b > v) v = b; + float min = (r < g) ? r : g; + 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>> 1) % 4; + init(max); + time = System.currentTimeMillis(); + thr = new Thread(this); + thr.start(); + } + + public void run() { + while (run) { + if(up) { + while(cf!=0) { + spd++; cf--; + try { Thread.sleep(25L);} catch (InterruptedException ex) {ex.printStackTrace();} + } + up=false; + } + if(dn) { + while(cf!=0) { + spd--; cf--; + try { Thread.sleep(25L);} catch (InterruptedException ex) {ex.printStackTrace();} + } + dn=false; + } + int r = (rnd.nextInt() >>> 1) % 20; + switch(r) { + case 5: up=true; cf=100; break; + case 15: up=true; cf=400; break; + case 8: dn=true; cf=100; break; + case 18: dn=true; cf=400; break; + case 3: if(max>11) max-=10; break; + case 13: 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: mode = (rnd.nextInt() >>> 1) % 4; break; + } + try { + if(spd<25 && spd>-25) Thread.sleep(500L); + else Thread.sleep(2000L); + } catch (InterruptedException ex) { + ex.printStackTrace(); + } + } + } + + public void setRun(boolean run) { + this.run=run; + } + + public Image MainCanvas() { + dt = System.currentTimeMillis() - time; + time = System.currentTimeMillis(); + if(K>=3) ACLS(G); + else CLS(G); + for (i = 1; i0) { + if (starz[i] <= -200) { + starx[i] = (rnd.nextInt()>>>1)%(w * 4) - w * 2; + stary[i] = (rnd.nextInt()>>>1)%(h * 4) - h * 2; + starz[i] = (rnd.nextInt()>>>1)%1900; + } + SetPix((255 - 255 * (starz[i] + 200) / 2100)); + }else{ + if (starz[i] > 2000) { + starx[i] = (rnd.nextInt()>>>1)%(w * 4) - w * 2; + stary[i] = (rnd.nextInt()>>>1)%(h * 4) - h * 2; + starz[i] = (rnd.nextInt()>>>1)%1900; + } + SetPix((255-255 * (starz[i]%2100) / 2100)); + } + } + return db; + } + + private void CLS(Graphics g) { + g.setColor(0); + 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) | 0; + } + g.drawRGB(pixelArray, 0, w, 0, 0, w, h, true); + } + + 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; if(c<0) c=0; + switch(mode) { + case 0: + 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; + 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()>>>1)%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; + } + + } + + + + private void init(int max) { + starx = new int[max];stary = new int[max];starz = new int[max]; + for (i = 0; i>>1)%(w * 4) - w * 2; + stary[i] = (rnd.nextInt()>>>1)%(h * 4) - h * 2; + starz[i] = (rnd.nextInt()>>>1)%1900; + } + CLS(G); + } +} diff --git a/src/Engine2.java b/src/Engine2.java index 7fe967c..0c02377 100644 --- a/src/Engine2.java +++ b/src/Engine2.java @@ -17,7 +17,7 @@ public class Engine2 implements Runnable { private boolean rb, gb, bb; private float x, y, tx, ty, k, d, len; - private int rc = 0, gc = 0, bc = 0, rgb = 1, fr = 1, ar = 1; + private int rc, gc, bc, rgb, fr, ar; private float[] a = new float[40]; private Random rnd; private Thread thr; @@ -29,6 +29,10 @@ public class Engine2 implements Runnable { db = Image.createImage(w, h); G = db.getGraphics(); rnd = new Random(); + rc = gc = bc = 0; + ar=(rnd.nextInt() >>> 1) % 14; + fr=((rnd.nextInt()>>>1)%6)+1; + rgb = 1; thr = new Thread(this); thr.start(); } @@ -48,7 +52,6 @@ public class Engine2 implements Runnable { case 11: U=(rnd.nextInt() >>> 1) % 9; break; case 14: if(K>16) K-=15; break; } - try { Thread.sleep(2000L); } catch (InterruptedException ex) {} @@ -63,7 +66,6 @@ public class Engine2 implements Runnable { rgb(G); visual(G); return db; - } private void rgb(Graphics grf) { @@ -114,11 +116,7 @@ public class Engine2 implements Runnable { } private void visual(Graphics grf) { - if (w > h) { - len = (float) (h / L / N); - } else { - len = (float) (w / L / N); - } + len = (float) (w>h?h:w) / L / N; k = (float) (Math.abs(rnd.nextFloat() * 360) * Math.PI / 180); float r50 = (float) (Math.abs(rnd.nextFloat()) * 50); d = (float) (Math.PI * 2 / S); @@ -139,27 +137,22 @@ public class Engine2 implements Runnable { 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); - } - if (fr == 2) { + }else if (fr == 2) { tx = (float) (x + Math.sin(j * d + a[i]) * len); ty = (float) (y + Math.cos(j * d + a[i]) * len); - } - if (fr == 3) { + }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); - } - if (fr == 4) { + }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); - } - if (fr == 5) { + }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)); - } - if (fr == 6) { + }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); @@ -171,46 +164,34 @@ public class Engine2 implements Runnable { } if (ar == 2) { grf.setColor(255, (255 - 255 * i / N), 0); - } - if (ar == 3) { + }else if (ar == 3) { grf.setColor(rc, (255 - 255 * i / N), 255); - } - if (ar == 4) { + }else if (ar == 4) { grf.setColor((255 - 255 * i / N), 255, 0); - } - if (ar == 5) { + }else if (ar == 5) { grf.setColor((255 - 255 * i / N), (255 - 255 * i / N), 255); - } - if (ar == 6) { + }else if (ar == 6) { grf.setColor((255 - 255 * i / N), 255, 255); - } - if (ar == 7) { + }else if (ar == 7) { grf.setColor(0, 255, (255 - 255 * i / N)); - } - if (ar == 8) { + }else if (ar == 8) { grf.setColor(255, gc, (255 - 255 * i / N)); - } - if (ar == 9) { + }else if (ar == 9) { grf.setColor(255, (255 - 255 * i / N), (255 - 255 * i / N)); - } - if (ar == 10) { + }else if (ar == 10) { grf.setColor(rc, (255 - 255 * i / N), 0); - } - if (ar == 11) { + }else if (ar == 11) { grf.setColor(255, (255 - 255 * i / N), 255); - } - if (ar == 12) { + }else if (ar == 12) { grf.setColor((255 - 255 * i / N), 0, 255); - } - if (ar == 13) { + }else if (ar == 13) { grf.setColor((255 - 255 * i / N), 255 * i / N, 0); - } - if (ar == 14) { + }else if (ar == 14) { grf.setColor(bc, 255, (255 - 255 * i / N)); } if (T==0) grf.drawLine((int) x, (int) y, (int) tx, (int) ty); - if (T==1) grf.fillArc((int) tx, (int) ty, (int) x, (int) y, 0, 360); - if (T==2) grf.fillRect((int) tx, (int) ty, (int) x, (int) y); + else if (T==1) grf.fillArc((int) tx, (int) ty, (int) x, (int) y, 0, 360); + else if (T==2) grf.fillRect((int) tx, (int) ty, (int) x, (int) y); x = tx; y = ty; } @@ -227,7 +208,7 @@ public class Engine2 implements Runnable { 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; + pixelArray[io] = (int)(100-K << 24) | Canv.background & 0x00ffffff; } g.drawRGB(pixelArray, 0, w, 0, 0, w, h, true); } diff --git a/src/FWCashe.java b/src/FWCashe.java new file mode 100644 index 0000000..d498fc5 --- /dev/null +++ b/src/FWCashe.java @@ -0,0 +1,51 @@ + + +import javax.microedition.lcdui.Font; +import java.util.Vector; + +public class FWCashe +{ + + public static FWCashe getCache (Font font) + { + Vector fwc = new Vector (); + Vector fwc_f = new Vector (); + for (int i = 0; i < fwc.size (); i++) + if (fwc_f.elementAt(i).equals (font)) + return (FWCashe)fwc.elementAt(i); + fwc_f.addElement (font); + FWCashe f; + fwc.addElement (f = new FWCashe (font)); + return f; + } + protected Font font; + protected byte caches [][]; + + protected FWCashe (Font font) + { + this.font = font; + caches = new byte [256][]; + for (int i = 0; i < 256; i++) + caches [i] = null; + } + + public int charWidth (char ch) { + int hi = (ch >> 8)&0xFF, lo = (ch)&0xFF; + if (caches[hi] == null) { + caches[hi] = new byte [256]; + for (int i = 0; i < 256; i++) + caches [hi][i] = -1; + } + if (caches [hi][lo] == -1) + caches [hi][lo] = (byte) font.charWidth(ch); + return caches [hi][lo]; + } + + public int stringWidth(String s) + { + int l = s.length (), i, r; + for (r = 0, i = 0; i < l; i++) + r += charWidth(s.charAt(i)); + return r; + } +} diff --git a/src/FindLyrics.java b/src/FindLyrics.java index a87c343..8c824c3 100644 --- a/src/FindLyrics.java +++ b/src/FindLyrics.java @@ -24,7 +24,7 @@ public class FindLyrics { String url = "http://www.lyricsplugin.com/winamp03/plugin/?artist="+urlName(artist)+"&title="+urlName(title); try { byte[] res = send(url); - int lr1 = MSG.indexOf("
"); + int lr1 = MSG.indexOf("
"); int lr2 = MSG.indexOf("
", lr1); if((lr2-lr1)>30) { FileConnection fc; @@ -47,7 +47,7 @@ public class FindLyrics { String artist = song.substring(0, song.lastIndexOf('-')).trim(); String title = song.substring(song.lastIndexOf('-')+1).trim(); MSG = ""; - String url = "http://annimon.z83.ru/nowplaying.php?id="+Rms.id+"&a="+urlName(artist)+"&t="+urlName(title); + String url = "http://annimon.com/seps/seps.php?id="+Rms.id+"&a="+urlName(artist)+"&t="+urlName(title); try { send(url); } catch (Exception e) { diff --git a/src/FindText.java b/src/FindText.java index aeb6936..0105e55 100644 --- a/src/FindText.java +++ b/src/FindText.java @@ -1,5 +1,3 @@ - -import com.sonyericsson.multimedia.MetaData; import javax.microedition.lcdui.*; /* @@ -13,45 +11,31 @@ import javax.microedition.lcdui.*; public class FindText extends Form implements CommandListener { private Command back, ok; - public TextField artist, title; + public TextField all_tb; - public FindText() { + public FindText(String all) { super(SEPS.midlet.lang.findtext); back = new Command(SEPS.midlet.lang.back, Command.BACK, 2); ok = new Command(SEPS.midlet.lang.ok, Command.OK, 1); - String ar="",ti=""; - try{ - MetaData metaData = SEPS.midlet.cnv.media.getMetaData(); - ti = getValue(metaData, MetaData.TITLE_KEY); - ar = getValue(metaData, MetaData.ARTIST_KEY); - }catch(Exception ex){} - artist = new TextField(SEPS.midlet.lang.artist, ar, 255, TextField.ANY); - title = new TextField(SEPS.midlet.lang.title, ti, 255, TextField.ANY); - append(artist); - append(title); + all_tb = new TextField(SEPS.midlet.lang.artist, all, 512, TextField.ANY); + append(all_tb); addCommand(ok); addCommand(back); setCommandListener(this); SEPS.midlet.dsp.setCurrent(this); } - private String getValue(MetaData metaData, String md) { - String data = metaData.getValue(md); - StringBuffer sb = new StringBuffer(); - for(int i=0; i>> 1) % 10000000; } new Skin(Rms.skinid); - cnv = new Canv(); + cnv = new Canv(im); dsp = Display.getDisplay(this); dsp.setCurrent(cnv); } diff --git a/src/SetSleepMode.java b/src/SetSleepMode.java index 320adb6..e2231d1 100644 --- a/src/SetSleepMode.java +++ b/src/SetSleepMode.java @@ -33,19 +33,23 @@ public class SetSleepMode extends Form implements CommandListener { } if (c == ok) { - Calendar cal = Calendar.getInstance(); - //текущее время - int ch = cal.get(Calendar.HOUR_OF_DAY); - int cm = cal.get(Calendar.MINUTE); - //время выключения - int dh = ch; - int dm = cm + Integer.parseInt(zw.getString()); - while(dm>=60) { - dm=dm-60; dh++; + int time = Integer.parseInt(zw.getString()); + if(time == 0) Rms.slpmode=false; + else { + Calendar cal = Calendar.getInstance(); + //текущее время + int ch = cal.get(Calendar.HOUR_OF_DAY); + int cm = cal.get(Calendar.MINUTE); + //время выключения + int dh = ch; + int dm = cm + time; + while(dm>=60) { + dm=dm-60; dh++; + } + if(dh>=24) dh=dh-24; + Rms.slpmode=true; + Rms.dh=dh; Rms.dm=dm; } - if(dh>=24) dh=dh-24; - Rms.slpmode=true; - Rms.dh=dh; Rms.dm=dm; SEPS.midlet.dsp.setCurrent(SEPS.midlet.cnv); } } diff --git a/src/Skin.java b/src/Skin.java index bbebf1e..8cfdcab 100644 --- a/src/Skin.java +++ b/src/Skin.java @@ -10,97 +10,44 @@ public class Skin { public Skin(int skin) { - switch(skin) { - case 0: //default - setSEPS(); - break; - case 1: //PPM - setPPM(); - break; - case 2: //Gothic - setGothic(); - break; - case 3: //Emo - setEmo(); - break; - case 4: //SEclub - setSEclub(); - break; - case 5: //SEclub - setaNM(); - break; + 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; + Canv.background = 0xFF2F8400; + Canv.valuet = 0xFFFFFFFF; + if(skin!=0) { + Canv.softUp1 = Effects.changeHSV(Canv.background, 2, 0.4352941f); + Canv.softUp2 = Effects.changeHSV(Canv.background, 2, 0.19215685f); + Canv.softDn1 = Effects.changeHSV(Canv.background, 2, -0.007843137f); + Canv.softDn2 = Effects.changeHSV(Canv.background, 2, -0.16862747f); + Canv.line = Effects.changeHSV(Canv.background, 0, 22); + Canv.line = Effects.changeHSV(Canv.line, 2, 0.21568626f); + Canv.text = Effects.changeHSV(Canv.background, 0, 22); + Canv.text = Effects.changeHSV(Canv.text, 2, 0.082352936f); + Canv.inf = Effects.changeHSV(Canv.background, 2, -0.16078433f); + for(int i=0; i<=2; i++) { + float delta = Effects.getHSV(skin, i) - Effects.getHSV(Canv.background, i); + if(delta>-0.05 && delta<0.05) continue; + Canv.softUp1 = Effects.changeHSV(Canv.softUp1, i, delta); + Canv.softUp2 = Effects.changeHSV(Canv.softUp2, i, delta); + Canv.softDn1 = Effects.changeHSV(Canv.softDn1, i, delta); + Canv.softDn2 = Effects.changeHSV(Canv.softDn2, i, delta); + Canv.line = Effects.changeHSV(Canv.line, i, delta); + Canv.text = Effects.changeHSV(Canv.text, i, delta); + Canv.inf = Effects.changeHSV(Canv.inf, i, delta); + } + Canv.background = skin; + }else{ + Canv.softUp1 = 0xFF57f300; + Canv.softUp2 = 0xFF41b500; + Canv.softDn1 = 0xFF2e8200; + Canv.softDn2 = 0xFF205900; + Canv.line = 0x00BB00; + Canv.text = 0x009900; + Canv.inf = 0x215B00; } - } - - private void setSEPS() { - Canv.softUp1 = 0xFF242424; - Canv.softUp2 = 0x87282828; - Canv.softDn1 = 0x87151515; - Canv.softDn2 = 0xFF181818; - Canv.background = 0x00; - Canv.line = 0x00BB00; - Canv.text = 0x009900; - Canv.valuet = 0x0000E6; - Canv.inf = 0x992235; - } - - private void setPPM() { - Canv.softUp1 = 0xFF3477d5; - Canv.softUp2 = 0x883477d5; - Canv.softDn1 = 0x8812396f; - Canv.softDn2 = 0xFF12396f; - Canv.background = 0xFFFFFF; - Canv.line = 0x0064A8; - Canv.text = 0x282828; - Canv.valuet = 0x296321; - Canv.inf = 0xA2DBF9; - } - - private void setGothic() { - Canv.softUp1 = 0xFF141414; - Canv.softUp2 = 0x87181818; - Canv.softDn1 = 0x87151515; - Canv.softDn2 = 0xFF181818; - Canv.background = 0x00; - Canv.line = 0x6D6D6D; - Canv.text = 0x595959; - Canv.valuet = 0x666666; - Canv.inf = 0x474747; - } - - private void setEmo() { - Canv.softUp1 = 0xFF1E1012; - Canv.softUp2 = 0x8887466D; - Canv.softDn1 = 0x88512C31; - Canv.softDn2 = 0xFFCE6BA6; - Canv.background = 0xFF879B; - Canv.line = 0xFF28A9; - Canv.text = 0x00; - Canv.valuet = 0x60204A; - Canv.inf = 0xD17DDB; - } - - private void setSEclub() { - Canv.softUp1 = 0xFF295723; - Canv.softUp2 = 0x88295723; - Canv.softDn1 = 0x8834EB5E; - Canv.softDn2 = 0xFF34EB5E; - Canv.background = 0x295723; - Canv.line = 0xDFFFFF; - Canv.text = 0x2ED45E; - Canv.valuet = 0x34EB5E; - Canv.inf = 0xCAC410; - } - - private void setaNM() { - Canv.softUp1 = 0xFF99AACC; - Canv.softUp2 = 0x7599AACC; - Canv.softDn1 = 0x75CCFF99; - Canv.softDn2 = 0xFFCCFF99; - Canv.background = 0xFFFF99; - Canv.line = 0x002B55; - Canv.text = 0x333399; - Canv.valuet = 0x640022; - Canv.inf = 0x008000; + } } diff --git a/src/about b/src/about index 593cdca..1a296cf 100644 --- a/src/about +++ b/src/about @@ -1,15 +1,15 @@ -Sony Ericsson Player Service 5.2 +Sony Ericsson Player Service 7.0 Автор: Виктор aNNiMON Мельник -Сайт разработчика: http://annimon.z83.ru/ +Сайт разработчика: http://annimon.com/ -Программа - управление родным плейером для телефонов Sony Ericsson с поддержкой MultimediaService API и датчиком движения. +Программа - управление стандартным плейером телефонов Sony Ericsson с поддержкой Multimedia Service API и акселерометром. Управление: Влево/Вправо/Движение акселерометром - Переключение песен. - Вверх/Вниз - переключение режимов: Всё/Визуализация/Текст. + Вверх/Вниз - переключение режимов: Всё/Визуализация. 1 - Горячая клавиша поиска текста. - 3 - установить начало/конец отрезка или отключить повтор. + 3 - установить начало/конец отрезка для повтора или отключить повтор. 4/6 - Перемотка назад/вперед. 5/Огонь - Пауза. 9 - Спящий режим. @@ -18,6 +18,21 @@ Sony Ericsson Player Service 5.2 # - Включение/Отключение акселерометра. Изменения: + Версия 7.0 + - При выборе цвета скина, по нажатию кн.0 можно выбрать цвет текста. + + Версия 6.0 + - Перерисован интерфейс. Огромное спасибо за идею EviGL. + - Выбор цвета скина. Принципиально новая технология - весь интерфейс строиться всего-лишь на одном цвете - цвете фона. Остальные цвета генерируются при помощи некоторой системы преобразований. + - Добавил еще одну программную визуализацию - звезды. + - Выбор визуализации теперь доступен из отдельного пункта меню, при этом есть возможность её предпросмотра. Кнопки 4/6 - переключить визуализацию. + - Визуализация переключения режимов (показ всех данных / визуализация). + - Скробблинг теперь успешно перенесен на сайт annimon.com. + - Обновление скрипта скробблера: теперь вместо текстового режима будет выдаваться html-страница; в списке проигранных треков, теперь будет выдаваться ссылка на просмотр текста песен; сортировка по последним обновленным записям; некоторые другие исправления. Теперь скрипт доступен по адресу http://annimon.com/seps/seps.php. + - Отключение таймера при вводе 0 в спящем режиме. + - Скроллинг длинных названий песен. + - Добавлена быстрая перемотка на зажатие кнопок 4 или 6. + - Добавлена визуализация смены громкости. Версия 5.2 - Добавлен пункт в настройках, при котором переключение треков будет идти только вперед, независимо от направления рывка. - Поддержка русской кодировки в именах файлов. diff --git a/src/mobscrob/scrobbler/AudioScrobbler.java b/src/mobscrob/scrobbler/AudioScrobbler.java new file mode 100644 index 0000000..385bd56 --- /dev/null +++ b/src/mobscrob/scrobbler/AudioScrobbler.java @@ -0,0 +1,276 @@ +/* + * 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 new file mode 100644 index 0000000..cc5d563 --- /dev/null +++ b/src/mobscrob/scrobbler/ByteUtil.java @@ -0,0 +1,79 @@ +/** + * 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 new file mode 100644 index 0000000..dc6cf52 --- /dev/null +++ b/src/mobscrob/scrobbler/HTTPUtil.java @@ -0,0 +1,192 @@ +/** + * 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/mobscrob/scrobbler/MD5.java b/src/mobscrob/scrobbler/MD5.java new file mode 100644 index 0000000..398f80c --- /dev/null +++ b/src/mobscrob/scrobbler/MD5.java @@ -0,0 +1,648 @@ +/** + * MD5.java + * @author NJ Pearman + * @date 7 Oct 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.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; + +/** + * @author Neill + * + */ +public class MD5 { + + /** + * Class constructor + * + * @since ostermillerutils 1.00.00 + */ + public MD5() { + reset(); + } + + /** + * Gets this hash sum as an array of 16 bytes. + * + * @return Array of 16 bytes, the hash of all updated bytes. + * + * @since ostermillerutils 1.00.00 + */ + public byte[] getHash() { + if (!finalState.valid) { + finalState.copy(workingState); + long bitCount = finalState.bitCount; + // Compute the number of left over bits + int leftOver = (int) (((bitCount >>> 3)) & 0x3f); + // Compute the amount of padding to add based on number of left over bits. + int padlen = (leftOver < 56) ? (56 - leftOver) : (120 - leftOver); + // add the padding + update(finalState, padding, 0, padlen); + // add the length (computed before padding was added) + update(finalState, encode(bitCount), 0, 8); + finalState.valid = true; + } + // make a copy of the hash before returning it. + return encode(finalState.state, 16); + } + + /** + * Returns 32-character hex representation of this hash. + * + * @return String representation of this object's hash. + * + * @since ostermillerutils 1.00.00 + */ + public String getHashString() { + 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 + * platform's default character encoding. + * + * @param s String 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(String s) { + MD5 md5 = new MD5(); + md5.update(s); + 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. + * + * @since ostermillerutils 1.00.00 + */ + public void reset() { + workingState.reset(); + 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. + *

+ * A state may be passed into this method so that we can add padding + * and finalize a md5 hash without limiting our ability to update + * more data later. + *

+ * If length bytes are not available to be hashed, as many bytes as + * possible will be hashed. + * + * @param state Which state is updated. + * @param buffer Array of bytes to be hashed. + * @param offset Offset to buffer array. + * @param length number of bytes to hash. + * + * @since ostermillerutils 1.00.00 + */ + private void update(MD5State state, byte buffer[], int offset, int length) { + + finalState.valid = false; + + // if length goes beyond the end of the buffer, cut it short. + if ((length + offset) > buffer.length) { + length = buffer.length - offset; + } + + // compute number of bytes mod 64 + // this is what we have sitting in a buffer + // that have not been hashed yet + int index = (int) (state.bitCount >>> 3) & 0x3f; + + // add the length to the count (translate bytes to bits) + state.bitCount += length << 3; + + int partlen = 64 - index; + + int i = 0; + if (length >= partlen) { + System.arraycopy(buffer, offset, state.buffer, index, partlen); + transform(state, decode(state.buffer, 64, 0)); + for (i = partlen; (i + 63) < length; i += 64) { + transform(state, decode(buffer, 64, i)); + } + index = 0; + } + + // buffer remaining input + if (i < length) { + for (int start = i; i < length; i++) { + state.buffer[index + i - start] = buffer[i + offset]; + } + } + } + + /** + * 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 offset Offset to buffer array. + * @param length number of bytes to hash. + * + * @since ostermillerutils 1.00.00 + */ + public void update(byte buffer[], int offset, int length) { + 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. + * + * @param buffer Array of bytes to be hashed. + * + * @since ostermillerutils 1.00.00 + */ + public void update(byte buffer[]) { + 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 + * platform's default character encoding. + * + * @param s String to be hashed. + * + * @since ostermillerutils 1.00.00 + */ + 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. + * + * @since ostermillerutils 1.00.00 + */ + private MD5State workingState = new MD5State(); + /** + * Cached copy of the final MD5 hash sum. This is created when + * the hash is requested and it is invalidated when the hash + * is updated. + * + * @since ostermillerutils 1.00.00 + */ + private MD5State finalState = new MD5State(); + /** + * Temporary buffer cached here for performance reasons. + * + * @since ostermillerutils 1.00.00 + */ + private int[] decodeBuffer = new int[16]; + /** + * 64 bytes of padding that can be added if the length + * is not divisible by 64. + * + * @since ostermillerutils 1.00.00 + */ + private static final byte padding[] = { + (byte) 0x80, 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, 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. + * Passes MD5 test suite as defined in RFC1321. + * + * @since ostermillerutils 1.00.00 + */ + private class MD5State { + + /** + * True if this state is valid. + * + * @since ostermillerutils 1.00.00 + */ + private boolean valid = true; + + /** + * Reset to initial state. + * + * @since ostermillerutils 1.00.00 + */ + private void reset() { + state[0] = 0x67452301; + state[1] = 0xefcdab89; + state[2] = 0x98badcfe; + state[3] = 0x10325476; + + bitCount = 0; + } + /** + * 128-byte state + * + * @since ostermillerutils 1.00.00 + */ + private int state[] = new int[4]; + /** + * 64-bit count of the number of bits that have been hashed. + * + * @since ostermillerutils 1.00.00 + */ + private long bitCount; + /** + * 64-byte buffer (512 bits) for storing to-be-hashed characters + * + * @since ostermillerutils 1.00.00 + */ + private byte buffer[] = new byte[64]; + + private MD5State() { + reset(); + } + + /** + * Set this state to be exactly the same as some other. + * + * @param from state to copy from. + * + * @since ostermillerutils 1.00.00 + */ + private void copy(MD5State from) { + System.arraycopy(from.buffer, 0, this.buffer, 0, this.buffer.length); + System.arraycopy(from.state, 0, this.state, 0, this.state.length); + this.valid = from.valid; + this.bitCount = from.bitCount; + } + } + + /** + * Turns array of bytes into string representing each byte as + * a two digit unsigned hex number. + * + * @param hash Array of bytes to convert to hex-string + * @return Generated hex string + * + * @since ostermillerutils 1.00.00 + */ + private static String toHex(byte hash[]) { + StringBuffer buf = new StringBuffer(hash.length * 2); + for (int i = 0; i < hash.length; i++) { + int intVal = hash[i] & 0xff; + if (intVal < 0x10) { + // append a zero before a one digit hex + // number to make it two digits. + buf.append("0"); + } + buf.append(Integer.toHexString(intVal)); + } + return buf.toString(); + } + + private static int FF(int a, int b, int c, int d, int x, int s, int ac) { + a += ((b & c) | (~b & d)); + a += x; + a += ac; + //return rotateLeft(a, s) + b; + a = (a << s) | (a >>> (32 - s)); + return a + b; + } + + private static int GG(int a, int b, int c, int d, int x, int s, int ac) { + a += ((b & d) | (c & ~d)); + a += x; + a += ac; + //return rotateLeft(a, s) + b; + a = (a << s) | (a >>> (32 - s)); + return a + b; + } + + private static int HH(int a, int b, int c, int d, int x, int s, int ac) { + a += (b ^ c ^ d); + a += x; + a += ac; + //return rotateLeft(a, s) + b; + a = (a << s) | (a >>> (32 - s)); + return a + b; + } + + private static int II(int a, int b, int c, int d, int x, int s, int ac) { + a += (c ^ (b | ~d)); + a += x; + a += ac; + //return rotateLeft(a, s) + b; + a = (a << s) | (a >>> (32 - s)); + return a + b; + } + + private static byte[] encode(long l) { + byte[] out = new byte[8]; + out[0] = (byte) (l & 0xff); + out[1] = (byte) ((l >>> 8) & 0xff); + out[2] = (byte) ((l >>> 16) & 0xff); + out[3] = (byte) ((l >>> 24) & 0xff); + out[4] = (byte) ((l >>> 32) & 0xff); + out[5] = (byte) ((l >>> 40) & 0xff); + out[6] = (byte) ((l >>> 48) & 0xff); + out[7] = (byte) ((l >>> 56) & 0xff); + return out; + } + + private static byte[] encode(int input[], int len) { + byte[] out = new byte[len]; + int i, j; + for (i = j = 0; j < len; i++, j += 4) { + out[j] = (byte) (input[i] & 0xff); + out[j + 1] = (byte) ((input[i] >>> 8) & 0xff); + out[j + 2] = (byte) ((input[i] >>> 16) & 0xff); + out[j + 3] = (byte) ((input[i] >>> 24) & 0xff); + } + return out; + } + + private int[] decode(byte buffer[], int len, int offset) { + int i, j; + for (i = j = 0; j < len; i++, j += 4) { + decodeBuffer[i] = ((buffer[j + offset] & 0xff)) + | (((buffer[j + 1 + offset] & 0xff)) << 8) + | (((buffer[j + 2 + offset] & 0xff)) << 16) + | (((buffer[j + 3 + offset] & 0xff)) << 24); + } + return decodeBuffer; + } + + private static void transform(MD5State state, int[] x) { + int a = state.state[0]; + int b = state.state[1]; + int c = state.state[2]; + int d = state.state[3]; + + /* Round 1 */ + a = FF(a, b, c, d, x[ 0], 7, 0xd76aa478); /* 1 */ + d = FF(d, a, b, c, x[ 1], 12, 0xe8c7b756); /* 2 */ + c = FF(c, d, a, b, x[ 2], 17, 0x242070db); /* 3 */ + b = FF(b, c, d, a, x[ 3], 22, 0xc1bdceee); /* 4 */ + a = FF(a, b, c, d, x[ 4], 7, 0xf57c0faf); /* 5 */ + d = FF(d, a, b, c, x[ 5], 12, 0x4787c62a); /* 6 */ + c = FF(c, d, a, b, x[ 6], 17, 0xa8304613); /* 7 */ + b = FF(b, c, d, a, x[ 7], 22, 0xfd469501); /* 8 */ + a = FF(a, b, c, d, x[ 8], 7, 0x698098d8); /* 9 */ + d = FF(d, a, b, c, x[ 9], 12, 0x8b44f7af); /* 10 */ + c = FF(c, d, a, b, x[10], 17, 0xffff5bb1); /* 11 */ + b = FF(b, c, d, a, x[11], 22, 0x895cd7be); /* 12 */ + a = FF(a, b, c, d, x[12], 7, 0x6b901122); /* 13 */ + d = FF(d, a, b, c, x[13], 12, 0xfd987193); /* 14 */ + c = FF(c, d, a, b, x[14], 17, 0xa679438e); /* 15 */ + b = FF(b, c, d, a, x[15], 22, 0x49b40821); /* 16 */ + + /* Round 2 */ + a = GG(a, b, c, d, x[ 1], 5, 0xf61e2562); /* 17 */ + d = GG(d, a, b, c, x[ 6], 9, 0xc040b340); /* 18 */ + c = GG(c, d, a, b, x[11], 14, 0x265e5a51); /* 19 */ + b = GG(b, c, d, a, x[ 0], 20, 0xe9b6c7aa); /* 20 */ + a = GG(a, b, c, d, x[ 5], 5, 0xd62f105d); /* 21 */ + d = GG(d, a, b, c, x[10], 9, 0x02441453); /* 22 */ + c = GG(c, d, a, b, x[15], 14, 0xd8a1e681); /* 23 */ + b = GG(b, c, d, a, x[ 4], 20, 0xe7d3fbc8); /* 24 */ + a = GG(a, b, c, d, x[ 9], 5, 0x21e1cde6); /* 25 */ + d = GG(d, a, b, c, x[14], 9, 0xc33707d6); /* 26 */ + c = GG(c, d, a, b, x[ 3], 14, 0xf4d50d87); /* 27 */ + b = GG(b, c, d, a, x[ 8], 20, 0x455a14ed); /* 28 */ + a = GG(a, b, c, d, x[13], 5, 0xa9e3e905); /* 29 */ + d = GG(d, a, b, c, x[ 2], 9, 0xfcefa3f8); /* 30 */ + c = GG(c, d, a, b, x[ 7], 14, 0x676f02d9); /* 31 */ + b = GG(b, c, d, a, x[12], 20, 0x8d2a4c8a); /* 32 */ + + /* Round 3 */ + a = HH(a, b, c, d, x[ 5], 4, 0xfffa3942); /* 33 */ + d = HH(d, a, b, c, x[ 8], 11, 0x8771f681); /* 34 */ + c = HH(c, d, a, b, x[11], 16, 0x6d9d6122); /* 35 */ + b = HH(b, c, d, a, x[14], 23, 0xfde5380c); /* 36 */ + a = HH(a, b, c, d, x[ 1], 4, 0xa4beea44); /* 37 */ + d = HH(d, a, b, c, x[ 4], 11, 0x4bdecfa9); /* 38 */ + c = HH(c, d, a, b, x[ 7], 16, 0xf6bb4b60); /* 39 */ + b = HH(b, c, d, a, x[10], 23, 0xbebfbc70); /* 40 */ + a = HH(a, b, c, d, x[13], 4, 0x289b7ec6); /* 41 */ + d = HH(d, a, b, c, x[ 0], 11, 0xeaa127fa); /* 42 */ + c = HH(c, d, a, b, x[ 3], 16, 0xd4ef3085); /* 43 */ + b = HH(b, c, d, a, x[ 6], 23, 0x04881d05); /* 44 */ + a = HH(a, b, c, d, x[ 9], 4, 0xd9d4d039); /* 45 */ + d = HH(d, a, b, c, x[12], 11, 0xe6db99e5); /* 46 */ + c = HH(c, d, a, b, x[15], 16, 0x1fa27cf8); /* 47 */ + b = HH(b, c, d, a, x[ 2], 23, 0xc4ac5665); /* 48 */ + + /* Round 4 */ + a = II(a, b, c, d, x[ 0], 6, 0xf4292244); /* 49 */ + d = II(d, a, b, c, x[ 7], 10, 0x432aff97); /* 50 */ + c = II(c, d, a, b, x[14], 15, 0xab9423a7); /* 51 */ + b = II(b, c, d, a, x[ 5], 21, 0xfc93a039); /* 52 */ + a = II(a, b, c, d, x[12], 6, 0x655b59c3); /* 53 */ + d = II(d, a, b, c, x[ 3], 10, 0x8f0ccc92); /* 54 */ + c = II(c, d, a, b, x[10], 15, 0xffeff47d); /* 55 */ + b = II(b, c, d, a, x[ 1], 21, 0x85845dd1); /* 56 */ + a = II(a, b, c, d, x[ 8], 6, 0x6fa87e4f); /* 57 */ + d = II(d, a, b, c, x[15], 10, 0xfe2ce6e0); /* 58 */ + c = II(c, d, a, b, x[ 6], 15, 0xa3014314); /* 59 */ + b = II(b, c, d, a, x[13], 21, 0x4e0811a1); /* 60 */ + a = II(a, b, c, d, x[ 4], 6, 0xf7537e82); /* 61 */ + d = II(d, a, b, c, x[11], 10, 0xbd3af235); /* 62 */ + c = II(c, d, a, b, x[ 2], 15, 0x2ad7d2bb); /* 63 */ + b = II(b, c, d, a, x[ 9], 21, 0xeb86d391); /* 64 */ + + state.state[0] += a; + state.state[1] += b; + state.state[2] += c; + state.state[3] += d; + } +} diff --git a/src/newfile b/src/newfile index f227890..2212995 100644 --- a/src/newfile +++ b/src/newfile @@ -1,2 +1,2 @@ -aNNiMON, Ну Вот юин эсприта, основной плагмэйкер... 2542902 Вот LocID -//SE сфотошопить + aNNiMOON \ No newline at end of file +визуализация смены громкости +Быстрая перемотка \ No newline at end of file diff --git a/src/res/album.png b/src/res/album.png new file mode 100644 index 0000000..3442b7c Binary files /dev/null and b/src/res/album.png differ diff --git a/src/res/artist.png b/src/res/artist.png new file mode 100644 index 0000000..4188fff Binary files /dev/null and b/src/res/artist.png differ diff --git a/src/res/exit.png b/src/res/exit.png new file mode 100644 index 0000000..1a2f8dc Binary files /dev/null and b/src/res/exit.png differ diff --git a/src/res/pal.png b/src/res/pal.png new file mode 100644 index 0000000..ac347c5 Binary files /dev/null and b/src/res/pal.png differ diff --git a/src/res/pound.png b/src/res/pound.png new file mode 100644 index 0000000..c06391c Binary files /dev/null and b/src/res/pound.png differ diff --git a/src/res/sb.png b/src/res/sb.png new file mode 100644 index 0000000..195c71e Binary files /dev/null and b/src/res/sb.png differ diff --git a/src/res/sbl.png b/src/res/sbl.png new file mode 100644 index 0000000..8e50f2b Binary files /dev/null and b/src/res/sbl.png differ diff --git a/src/res/star.png b/src/res/star.png new file mode 100644 index 0000000..4269fd3 Binary files /dev/null and b/src/res/star.png differ diff --git a/src/res/t.png b/src/res/t.png new file mode 100644 index 0000000..9bf6eb1 Binary files /dev/null and b/src/res/t.png differ diff --git a/src/res/tl.png b/src/res/tl.png new file mode 100644 index 0000000..2568a4d Binary files /dev/null and b/src/res/tl.png differ diff --git a/src/res/track.png b/src/res/track.png new file mode 100644 index 0000000..8d5761e Binary files /dev/null and b/src/res/track.png differ diff --git a/src/res/zero.png b/src/res/zero.png new file mode 100644 index 0000000..39bbcf2 Binary files /dev/null and b/src/res/zero.png differ