Fixed: AVAudioPlayer Only Play 1-2s in iOS 6

I am developing Coco Voice ( http://cocovoice.com/ ) these days. After updating to iOS 6, no matter iOS 6 beta 4, iOS GM or iOS 6.0 release, I found that AAC-encoded voice message could not be played correctly. Only 1~2 seconds of voice was played even though the message was far longer than 2 seconds. But if I set currentTime to >= 1.4s, it will play the whole message after the given currentTime value. In this case, we always lose the first seconds message. Unacceptable for a voice mobile IM.

Searching the web, it seems only a few guys met with this problem. Someone explained that the duration is incorrect for AAC-encoded voice data. And some of them said they have reported this bug to Apple already (but I could not find the bug report). iOS 6.0 was just released yesterday or so, it may take at least a month or so for iOS 6.0.1 for this bug-fix. So we won’t just wait.

After lots of try, here is the solution:

AVAudioPlayer *soundPlayer = [[AVAudioPlayer alloc] initWithData:message error:&err];
soundPlayer.volume = 1.0f;
soundPlayer.currentTime = soundPlayer.duration + soundPlayer.duration;
soundPlayer.numberOfLoops = 1;
[soundPlayer setDelegate:self];
[soundPlayer prepareToPlay];
[soundPlayer play];

Just set currentTime to the end of the message and tell player to play the message twice. So it will be correctly played once. And set double duration to currentTime will make sure that player does not play the end of message twice.

BTW: If you set currentTime to 1.4f, and then NSLog the currentTime, you will find out that it will be changed to a different value.

Posted in iOS, Objective-C | 2 Comments

Use jmap and jhat to Detect Memory Leak

I noticed that my servers are running out of memory after one whole day’s service.

At first, I removed all functions that eat up memory. But still the next morning when the traffic is down, the memory is still high. So it seems I have memory leak in my server.

After making some searches and reading some blog articles, I learned that I can try to find view all memory by using jmap and jhat.

First, I made the dump:

jmap -dump:file=heap.bin ####

It was about 800M file, as my server is running at 1.5G maximum memory on 2G-memory server. I tried to use jhat to give a memory view:

jhat -J-mx1536m heap.bin

It run but failed with OutOfMemoryError, as my service was still running and it had no enough memory. Fortunately, I had another server without service running, so I uploaded the dump file to another server, and tried to start jhat there.? It run but with lots of warning message like the following:

WARNING:? Failed to resolve object id 0xac2f1690 for field key (signature L)
WARNING:? Failed to resolve object id 0xacd1c208 for field value (signature L)
WARNING:? Failed to resolve object id 0xac08df00 for field value (signature L)
WARNING:? Failed to resolve object id 0xac2f3f28 for field key (signature L)
WARNING:? Failed to resolve object id 0xac08df00 for field value (signature L)
WARNING:? Failed to resolve object id 0xac2eea70 for field key (signature L)
WARNING:? Failed to resolve object id 0xacd1c208 for field value (signature L)
WARNING:? Failed to resolve object id 0xac08df00 for field value (signature L)

And after a long time, it still gave me an OutOfMemoryError!

So I made another dump from another server which was running on its early stage with less memory being used. So the dump file was a lot smaller. And I could run jhat on the same without uploading to another. And after a very long time of waiting I finally got message:

Snapshot resolved.
Started HTTP server on port 7000
Server is ready.

Visiting http://###.###:7000/ , I noticed that jhat was slow. But it helped! I found my memory leak.

Great tools! I think I can reduce servers but still provide more stable services now.

Posted in Java, Server | 3 Comments

Disable cron.daily Task for Server

I just learned the lesson that for cron.daily tasks should be disabled for Linux servers.

I were having the headache that in some certain hour of each day, my servers run into high load average. I suspected that it is my app server’s problems, and I spent tons of time on optimizing my service servers. Optimization helped a little but high system load average was still coming. I wondered why. And l installed iotop by “yum install iotop” the day before yesterday, and found that “prelink” and “updatedb” did a lot of IO reading and writing. And finally I got to know that they were the cron.daily tasks, which is located under /etc/cron.daily/ .

So disabling tasks under /etc/cron.daily/, like mlocate.cron (will invoke udpatedb), makewhatis, prelink and others, will help your servers perform a lot better.

By the way, your should also edit /etc/crontab to reschedule the time for those daily jobs. The default hour is 4 a.m. in the morning. But your servers’ timezone setting might be different or your servers’ peak traffic might be at that hour, so modifying it to your servers’ valley hour will help performance.

After these modifications, WeBuzz.IM web IM services servers will run a lot better from now on.

Posted in Server | Tagged , | Comments Off on Disable cron.daily Task for Server

Implementing Gmail-alike Web Mail Client by Java2Script

WeMail, this to-be-implemented Gmail-alike web mail client, is based on technologies of Java, SWT, JavaMail and Java2Script.

Before going into designing and implementing details, here are some background information.

Java2Script (J2S) Pacemaker provides an Eclipse Java to JavaScript compiler plugin and an implementation of JavaScript version of Eclipse Standard Widget Toolkit (SWT) with other common utilities, such as java.lang.* and java.util.*. You can convert your SWT-base Rich Client Platform (RCP) into Rich Internet Application (RIA) by Java2Script Pacemaker.

JavaMail is a Java API used to receive and send email via SMTP,POP3 and IMAP. JavaMail is built into the Java EE platform, but also provides an optional package for use in Java SE.

SWT is an open source widget toolkit for Java designed to provide efficient, portable access to the user-interface facilities of the operating systems on which it is implemented.

Google Web Toolkit (GWT) is an open source set of tools that allows web developers to create and maintain complex JavaScript front-end applications in Java. Other than a few native libraries, everything is Java source that can be built on any supported platform with the included GWT Ant build files.

Why implementing another Gmail-alike web mail client?

When GWT is released, lots of developers ask whether GWT will be used in Google’s major products, like Gmail, Google Reader or other products. Yeas went by, but there is still no Gmail powered by GWT. So using Java-to-JavaScript technology to build another Gmail web client should be fun for technical geeks. I choose Java2Script to build this web mail client, hoping it would help improving Java2Script toolkit.

I like Gmail UI, but I can not use its UI for other mail providers, like Hotmail or Yahoo! Mail. So I believe WeMail will help users doing their email jobs like receiving, composing and replying emails, in Gmail-alike UI for all mail providers. And it will sure increase their daily email processing efficiency.

And there are lots of companies that might block web access to Gmail, Yahoo! Mail or other mail providers. In these cases, a web mail client for general POP/IMAP & SMTP will help those users accessing emails even behind firewalls.

So I finally made up my mind to build it. And it was my two weeks’ fun.

Dang, dang, dang! Here it comes WeMail – Web Mail Client for Gmail/Hotmail/Live Mail/Yahoo! Mail/AOL Mail.

Configureing mail servers and login:
wemail-web-login

WeMail main window, listing emails:
wemail-list

Viewing an email:
Click for large view of wemail-message-viewer

Composing an email:
wemail-composing

How is this Gmail alike web mail client being implemented?

I use WindowsBuilder Pro (formerly known as SWTDesigner) to design all the UI elements. Here are screenshots of its UI components being designed:

Overview of WeMail in designer:
wemail-design-overview

Designing top menu bar:
Click for large view of wemail-menubar

Designing logo and search bar:
wemail-toolbar

Designing left side widget:
wemail-widget

Designing email selector bar:
wemail-selector

Designing email message header:
wemail-mail-header

Designing email message viewer:
wemail-viewer

Designing email composer:
wemail-composer

Designing footer panel:
wemail-footer

Designing login window:
wemail-login-window

Designing mail server configuring window:
wemail-configure-window

Designing and adjust user interfaces causes lots of time.

And what about the receiving and sending emails? I use JavaMail to do email jobs. Between SWT UI and JavaMail, Java2Script’s Simple RPC technology is used. Those mail jobs are separated into following RPCs:
1. CheckMails
2. DiscardEmails
3. FetchMailContent
4. ListFolderMails
5. MarkMailAsRead
6. SaveDraft
7. SendMail

UI events will trigger those RPCs being called in separate threads and UI will be updates after their jobs are done.After RPCs get woven into UI elements. It is ready to be run as a native Java desktop application. So it is:

wemail-desktop

Running, debugging, testing, bug-fixing, all take times. But up until now, all I do is native Java developments. No HTML, no JavaScript technologies is needed.

After the Java desktop version of WeMail is OK, it will be ready for being converted in an AJAX based web browser application. That is the Java2Script job (I am not going into Java2Script details, more information can be found on Java2Script at Sourceforge.net.): Install Java2Script Eclipse plugin and convert existed project into a Java2Script project. All those *.java files will be compiled int JavaScript automatically. Then pack all necessary files into a Servlet *.war file and deploy it into Java Servlet container server like Tomcat. And work is done. WeMail is available at http://webuzz.im/mail/ .

So it is my WeMail’s development log. Having fun.

Posted in AJAX, Java, Java2Script | Tagged , , , , , | 5 Comments

Connect Yahoo IMAP Server by JavaMail

These days, I were implementing an online web mail client for all mail services, like Gmail, Hotmail/Live Mail, Yahoo! Mail, AOL/AIM Mail. And adding Yahoo! Mail support cost me lots of time, but the solution is simple.

Yahoo! Mail provides only web access for free users and does not provide free POP3 services. You need to buy Yahoo! Mail Plus to have POP support. Not long before, Yahoo! Mail provided IMAP services for Zoho Web Mail. It means that IMAP support is free for any Yahoo! Mail users, no Yahoo! Mail Plus is needed. But Yahoo! Mail’s IMAP services is not a totally standard IMAP service. You need send some special tokens before you login. So a customized Thunderbird is need to Yahoo! IMAP support.

JavaMail provides a convenient way to connect mail servers by POP/IMAP/SMTP and others. Here is a “how-to” of making a little modification of JavaMail library to support Yahoo! Mail’s IMAP service.

1. Download sources of JavaMail
2. Modify com.sun.mail.imap.IMAPStore.login(IMAPProtocol, String, String) from a private method into a protected method, because we need to override it for Yahoo! IMAP.
3. Replace the compiled IMAPStore*.class files in JavaMail’s binary library file mail.jar.
4. Write two classes:

public class YahooIMAPStore extends IMAPStore {

	public YahooIMAPStore(Session session, URLName url) {
		super(session, url);
	}

	@Override
	protected void login(IMAPProtocol p, String u, String pw)
			throws ProtocolException {
		Response[] r = p.command("ID (\"GUID\" \"1\")", null);
		p.notifyResponseHandlers(r);

		super.login(p, u, pw);
	}
}

public class YahooIMAPSSLStore extends IMAPSSLStore {

	public YahooIMAPSSLStore(Session session, URLName url) {
		super(session, url);
	}

	@Override
	protected void login(IMAPProtocol p, String u, String pw)
			throws ProtocolException {
		Response[] r = p.command("ID (\"GUID\" \"1\")", null);
		p.notifyResponseHandlers(r);

		super.login(p, u, pw);
	}
}

5. Modify JavaMail related codes to use overrided YahooIMAPStore:

if ("yahoo.com".equals(domain)
		|| "ymail.com".equals(domain)
		|| "rocketmail.cn".equals(domain)) {
	if (protocol == null) {
		protocol = "imaps"; host = "imap.next.mail.yahoo.com"; port = 993;

		protocol = "imap";
		host = "imap.mail.yahoo.com";
		port = 143;
	}
	if (sendProtocol == null) {
		sendProtocol = "smtps";
		sendHost = "smtp.mail.yahoo.com";
		sendPort = 587;
	}
}
...
if (host.indexOf(".yahoo.com") != -1) {
	props.setProperty("mail.imap.class", "im.webuzz.mail.YahooIMAPStore");
	props.setProperty("mail.imaps.class", "im.webuzz.mail.YahooIMAPSSLStore");
}
Session session = Session.getInstance(props, null);
if (host.indexOf(".yahoo.com") != -1) {
	session.addProvider(new Provider(Provider.Type.STORE, "imap",
		"im.webuzz.mail.YahooIMAPStore", "WeBuzz", "1.0"));
	session.addProvider(new Provider(Provider.Type.STORE, "imaps",
		"im.webuzz.mail.YahooIMAPSSLStore", "WeBuzz", "1.0"));
}

store = session.getStore(protocol);
store.connect(host, user, password);
...

Done! Enjoy Yahoo! Mail’s IMAP support by JavaMail.

BTW: You can test out WeBuzz’s Web Mail for Yahoo! Mail, which is using JavaMail and IMAP with the above hacks.

Posted in Java | Tagged , , | 10 Comments

“Code like you won’t be there tomorrow”

Today, I came up with Doug on the Eclipse CDT’s “Code like you won’t be there tomorrow“. I liked its ending very much:

You can create the best system ever, and people will appreciate it while you’re there, but they may end up cursing you if you disappear and leave it in their laps.

Posted in Project Management | Tagged | 2 Comments

Compiling GDB Debugger in Windows

Here are the steps:

  1. Download 7-zip, if you do not have one.
  2. Install MinGW, please read MinGW’s Getting Started wiki. I choose manual installation:

    Download at least the following (or newer) packages from the MinGW download page:

    • binutils
    • gcc-core
    • mingw-runtime
    • w32api
    • expat

    Unpack them directly to D:\mingw

    Expat
    GDB can use the Expat XML parsing library. This library may be included with your operating system distribution; if it is not, you can get the latest version from http://expat.sourceforge.net.
    The `configure' script will search for this library in several standard locations; if it is installed in an unusual path, you can use the `–with-libexpat-prefix’ option to specify its location.

    Expat is used for:

    To download expat for MinGW, please visit here.

    For more about expat, please visit http://sources.redhat.com/gdb/onlinedocs/gdb_31.html.

  3. Install MinGW’s MSYS:
    • Install MSYS DTK 1.0 in D:\mingw\1.0
    • Install MSYS Core 1.0.11. It is an archive. Unpack it in D:\mingw\1.0
  4. Setting PATH and HOME environment, and run D:\mingw\1.0\msys.bat
  5. Download GDB debugger sources. I use the latest repository snapshot. And upack them to D:\mingw\1.0\home
  6. ./configure & make

You should have gdb.exe in D:\mingw\1.0\home\gdb-#.#.#\gdb\ in about 30 minutes.

To port GDB debugger to a new architecture, you should not miss the detailed guide ” Howto: Porting the GNU Debugger — Practical Experience with the OpenRISC 1000 Architecture “.

Update:

To compile GDB Insight 6.8 under MSYS environment, you should make a patch :

Index: gdb/ChangeLog
===================================================================
RCS file: /cvs/src/src/gdb/ChangeLog,v
retrieving revision 1.9174.2.20
diff -u -r1.9174.2.20 ChangeLog
— ChangeLog 31 Mar 2008 03:40:42 -0000 1.9174.2.20
+++ ChangeLog 11 Apr 2008 09:10:13 -0000
@@ -1,3 +1,8 @@
+2008-04-11 Hans Kester
+
+ * configure.ac: Added configdir for MinGW.
+ * configure: Added configdir for MinGW.
+
2008-03-30 Daniel Jacobowitz

* ia64-tdep.c (examine_prologue): Correct array access.

Index: gdb/configure.ac
===================================================================
RCS file: /cvs/src/src/gdb/configure.ac,v
retrieving revision 1.64
diff -u -r1.64 configure.ac
— configure.ac 13 Jan 2008 12:23:05 -0000 1.64
+++ configure.ac 11 Apr 2008 09:02:13 -0000
@@ -1445,7 +1445,7 @@
AC_SUBST(WIN32LDAPP)

case “${host}” in
-*-*-cygwin*)
+*-*-cygwin* | *-*-mingw*)
configdir=”win”
;;
*)

Index: gdb/configure
===================================================================
RCS file: /cvs/src/src/gdb/configure,v
retrieving revision 1.242
diff -u -r1.242 configure
— configure 13 Jan 2008 12:23:04 -0000 1.242
+++ configure 11 Apr 2008 09:05:54 -0000
@@ -23080,7 +23080,7 @@

case “${host}” in
-*-*-cygwin*)
+*-*-cygwin* | *-*-mingw*)
configdir=”win”
;;
*)

Posted in C++, Debug | Tagged , , | 3 Comments

Export Eclipse Plugin, Assert Errors

Here is my scenario:
I import Eclipse RSE( Remote System Explorer) plug-ins into my workspace and I want to build and test it myself. There are no errors in the workspace and running and debugging is all OK. And I want to export these plug-ins out: Export->Plug-in Development->Deployable plug-ins and fragements -> … An error dialog tells me that “Error occurred during the operation. A zip file containing the build logs has been generated and placed at …”. And exact that *.zip file and there is a @dot.bin.log, saying something like:
4. WARNING in D:\eclipse\workspace\org.eclipse.rse.core \src\org\eclipse\rse\core\ SystemTypeMatcher.java (at line 31)
assert pattern != null;
^^^^^^
'assert' should not be used as an identifier, since it is a reserved keyword from source level 1.4 on
----------
5. ERROR in D:\eclipse\workspace\org.eclipse.rse.core \src\org\eclipse\rse\core\ SystemTypeMatcher.java (at line 31)
assert pattern != null;
^^
Syntax error on token "!=", = expected

I know this error. But I already set the Compiler Compliance Level to 1.5 already, and in the workspace there is no errors complaining about this.

Googling all over the net and there is no clear solution to solve this problem. Someone says that modifying ANT script build.xml by adding source=”1.4″ will solve this problem. But the problem is that using Export->… the build.xml will always be regenerated.

After reading the source of plug-in org.eclipse.pde.build, I found that there is an option for the script generator to specify javacSource in build.xml. You can just add two lines in build.properties file like the following:
javacSource = 1.4
javacTarget = 1.4

And exporting plug-ins won’t have errors any more.

It feels great to have sources in hand when solving problems. 😀

Posted in Bug Fix, Eclipse, Tricks | Tagged , | 3 Comments

Enable Line-In to Speaker for Vista

Here is the hack for my Dell Inspiron 1520:

A lot of people have been reporting various versions of this issue. In short you are not able to hear line-in audio from the computers speaker even though the meter shows an audio signal. It seems that simply adding a registry key to enable the input monitor will fix the problem, at least it did on my Dell Dimension 9100. Once you add this key and reboot, you will need to enable the input monitor by going to “Control Panel” –> “Sound” –> “speakers/headphones” click on properties, then click on the “Levels” tab and enable the input monitor button.

That should do it, it did for me.

Here is the contents of the reg file I imported to fix the problem:
——————
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Class\{4D36E96C-E325-11CE-BFC1-08002BE10318}\0000\Settings\filter\SpeakerHp]
“EnableInputMonitor”=hex:01
————————

You can either create a reg file with this text, or go there yourself and create the binary value.

Here is my standard Microsoft type warning that you should never edit the registry unless you really know what you are doing!

Thanks snashbar very much for his/her post “Possible fix for LIne-in issue with SigmaTel driver in Vista

P.S. After I solved the Line-in problem, I found that the Line-In is really noisy. I finally found a solution: change the level of Microphone/Line In and Microphone Boost to 0:

P.S.2 For Mac OS X user, there is an application called “LineIn” for you to put through line-in to speaker.

Posted in Vista Hacks | 5 Comments

VMWare Player, Ubuntu and Mac OSX

So you want to play some other operating systems for some new features, or test your applications on other OSs? Take a try on VMWare Player. It is free.

Along with downloading and installing VMWare, you should also download OS images ( also called as Virtual Applicances). I think you should not miss Ubuntu 8.04 Desktop image (512M). I found that Ubuntu 8.04 running quite smoothly inside VMWare on my laptop with duo-core 2.2Ghz CPU and 2G memory. And I am lazy to install GIMP on my Vista, so running GIMP for some graphic manipulations may be one of Ubuntu jobs. And developing C++ or Java applications inside Ubuntu may be another job for me. And lots of other testing jobs. So owning an Ubuntu desktop is necessary.

(But I find a big inconvenience in my Ubuntu. I can input anything but having great difficulties in inputting 5 characters: “, ‘, ~, `, ^. I need to press that key and follow a space key to input these characters. I struggled hours to fix it but failed. So if you need a solution, please be kind to inform me.)

By the way, why not taking a try on Mac OSX Leopard. Download its 3.3G (expanded to 8G) Mac OSX Leopard x86 image (You should know that it is a pirate copy), following its instructions to install and patch. As using VMWare Player, you have to modify *.vmx directly to load *.iso patch into Leopard:

ide1:0.fileName = “D:\Downloads\Maxxuss-AMDPCNET-v1.0_1043.iso”
ide1:0.deviceType = “cdrom-image”

And you may also change

guestOS = “freebsd-64”

to

guestOS = “freebsd”

So no 64-bit CPU warning in starting this x86 Mac copy.

Well, I feel little excitement to Leopard as it is too slow. So maybe it is just for feature peeking or some small tests. It is not ready for daily work. Hope you have enough patience for the 2-3 days’ image download time and 12G hard disk spaces wasting.

Posted in Tricks | Tagged , , , | 2 Comments