понедельник, 22 ноября 2010 г.

Таймер со звуком

Один хороший друг придумал мне развлечение - написать ему таймер. Дело нехитрое, из переменных величин - количество итераций и продолжительность периода. При каждом прохождении выводить звук.
Реализовать звучание простого звука очень легко, он можно заставить приложение читать звук из файла или из интернета.
Кусочки исходника:
1. Обработчик команд. Запуск всего этого дела я доверил goCommand

   public void commandAction(Command c, Displayable s) {
      Timer t = new Timer();
      if (c == goCommand) {
      count = Integer.parseInt (countField.getString());
   duration = Long.parseLong (durationField.getString()) * 1000 ;
   // Таймер для очередного раунда
   MyTimerTask round = new MyTimerTask (this, 69, 100, 80);
   // Таймер для последнего раунда. отличается звуком и продолжительностью звучания
   MyTimerTask lastRound = new MyTimerTask (this, 70, 900, 100);
         // Задаем расписание для первого таймера
   t.schedule (round, 0, duration);
   // Задаем расписание для последнего раунда
   t.schedule (lastRound, duration*count);
   }
   // Выходим из приложения
   if (c == exitCommand) {
      t.cancel();
      notifyDestroyed();
      }
   }

2. Но чтобы все выполнялось как положено, то нужно выполнение команд из таймера выполнять в отдельных потоках. Поэтому:

class MyTimerTask
      extends TimerTask {
   private int tone, duration, volume;
   private timerMIDlet midlet;
   // Конструктор
   MyTimerTask (timerMIDlet midlet, int tone, int duration, int volume) {
      this.midlet = midlet;
      this.tone = tone;
   this.duration = duration;
   this.volume = volume;
   }
/** run() собственной персоной. проигрываем звук и уменьшаем количество раундов*/   
   public void run () {
      try {
      Manager.playTone (tone, duration, volume);
         //Выводим на экран количество оставшихся раундов
   midlet.mainForm.append ("Осталось "+String.valueOf(midlet.count));
   midlet.count--;
         if (midlet.count <= 0)
      this.cancel();
   }
   catch (Exception e)
      {System.err.println(e.toString());}
   }

}

Здесь я описал метод run(), который как раз будет запускаться отдельным потоком.

Звук воспроизводится командой Manager.playTone (tone, duration, volume);
Но как я писал выше, с этим можно и повеселится:

//ноты
   byte C4 = ToneControl.C4;; 
   byte D4 = (byte)(C4 + 2);
   byte E4 = (byte)(C4 + 4);
   byte G4 = (byte)(C4 + 7);
// последовательность
private byte[] enumRound = {
  ToneControl.VERSION, 1, 
  ToneControl.TEMPO, 120,
  ToneControl.BLOCK_START, 0,
  ToneControl.SET_VOLUME, 100,
  ToneControl.C4, 64, D4,8, E4,8,G4,8,D4,8,E4,8,G4,8,D4,8,C4,8,E4,8,G4,8,
  ToneControl.SILENCE, 4,
  ToneControl.BLOCK_END, 0,
  ToneControl.PLAY_BLOCK, 0   
   };
...
 Player p = Manager.createPlayer (Manager.TONE_DEVICE_LOCATOR);
 p.realize();
 ToneControl tc = (ToneControl)p.getControl("ToneControl");
 tc.setSequence (enumRound);
 VolumeControl vc = (VolumeControl)p.getControl("VolumeControl");
 vc.setLevel (100);
 p.prefetch();
 p.start();  

Или

   Player p = Manager.createPlayer ("http://server/somemusic.mp3");
   p.setLoopCount(5);
   p.start();

понедельник, 8 ноября 2010 г.

Хранение записей в RecordStore

В J2ME есть замечательная возможность сохранять информацию в контейнерах RecordStore.
Я его использовал, например, когда писал BookReader, чтоб начинать читать с того места, где остановился. Ниже код для работы с RecordStore


import java.lang.Object;
import javax.microedition.rms.*;
/*** Works with RecordStore***/
public class RecStore {
   private RecordStore rs = null;
   static final String REC_STORE = "MonthMIDlet"; 
   
   public void openRecStore () // создаем и/или открываем RecordStore
   {
      try
      { 
      rs = RecordStore.openRecordStore(REC_STORE, true );
      }
      catch (Exception e)
      {System.err.println(e.toString());}
   }

   public void writeRecord(String str) // записываем str в RecordStore
   {
      byte[] rec = str.getBytes();
      try
      {
         rs.addRecord(rec, 0, rec.length);
      }
      catch (Exception e)
      {System.err.println(e.toString());}
   }
/* считываем все записи и 
возвращаем только ту, которая recNum */
   public String readRecords (int recNum) 
   {
      try
      {
      // Intentionally make this too small to test code below
         byte[] recData = new byte[5]; 
         int len;

         for (int i = 1; i <= rs.getNumRecords(); i++)      
         {
           if (rs.getRecordSize(i) > recData.length)
             recData = new byte[rs.getRecordSize(i)];
          
           len = rs.getRecord(i, recData, 0);
           if (i == recNum) 
        return new String(recData, 0, len);
         }
      }
      catch (Exception e)
      {System.err.println(e.toString());}
   return null;
   }
   
   public void closeRecStore() // закрываем RecordStore
   {
      try
      {
         rs.closeRecordStore();
      }
      catch (Exception e)
      {System.err.println(e.toString());}
   }
   
   public void deleteRecStore() // удаляем RecordStore
   {
      if (RecordStore.listRecordStores() != null)
      {
         try
         {
            RecordStore.deleteRecordStore(REC_STORE);
         }
         catch (Exception e)
         {System.err.println(e.toString());}
      }      
   }
}

среда, 3 ноября 2010 г.

Прикрепить файл к письму. Python

На работе попросили переписать скрипт так, чтоб текст приходил не в теле письма, а в прикрепленном письме.
Казалось бы, чего тут сложного, однако все оказалось не так просто.
В моей рабочей версии Python'a (3.1.1) есть небольшой баг, который подробно описан здесь.
Суть в том, что кодер base64 возвращает данные в виде bytes, а должен возвращать string.
На знаю как для новых версий, возможно там изначально исправлена эта ошибка, но для моей подошел вот этот патч. После него все встало на свои места.

import smtplib
import mimetypes
from email.mime.multipart import MIMEMultipart
from email.mime.application import MIMEApplication

COMMASPACE = ', '
fromaddr = 'from@somehost.com'
toaddrs = 'rcpt1@somehost.com', 'rcpt1@somehost.com'

path = 'c:\\some.file'
msg = MIMEMultipart()
msg['Subject'] = 'Errors in inet files'
msg['From'] = fromaddr
msg['To'] = COMMASPACE.join (toaddrs)
msg.preamble = 'You will not see this in a MIME-aware mail reader.\n'

attach = MIMEApplication (open(path, 'rb').read())
attach.add_header ('Content-Disposition', 'attachment', filename='some.file')
msg.attach (attach)

server = smtplib.SMTP('smtp.somehost.com')
server.set_debuglevel(1)
server.sendmail(fromaddr, toaddrs, msg.as_string())
server.quit()

вторник, 2 ноября 2010 г.

BookReader

3 недели назад, собирался залить себе книжек на телефон. Дома сидел под Ubuntu.
Стал искать конвертер текста в jar под Линукс. Не нашел. Есть только под винду. Говорят, что он и под вайном неплохо работает, но не суть.
Суть: решил я написать конвертер текста в jar.
Ну вот, спустя 3 недели выкладываю первый релиз

Здесь лежит первый релиз программы.Все разумеется в исходниках.
Чтоб скомпилировать и пользоваться необходимо: Qt (я писал для версии 4.3.6) с поддержкой zlib, gcc компилятор.
Собираем следующим образом
$ cd /path/to/BookReader/
$ qmake -project
$ qmake
$ make
после этого в директории /path/to/BookReader/ должен создаться файл BookReader готовый к запуску.

В программе используется набор QuaZIP, за что отдельная благодарность автору.

Буду благодарен всем, кто не поленится протестировать и напишет мне о допущеных мной ошибках и прочем

About

В этом блоге я буду опубликовывать заметки для себя, софт что я пишу, ну и все что может этому сопутствовать.