REGEX: Cleaning up sourcecode

remove comment lines
[\s\t]+//.+

remove multi-comment
\/\*([\s\S]*?)\*\/

remove empty lines
^\s*[\r\n]+

XP: Registry hack for JAD files

couple things I like to add to the context menu when I right click the jadfile:

1. open with wtk
2. open with vim

here's how to accomplish these things with a simple regedit hack:

STEP 1: Set up the open with...

[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.jad\OpenWithList]
"a"="gvim.exe"
"MRUList"="ab"
"b"="emulator.exe"

[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.jad\OpenWithProgids]
"jadfile"=hex(0):

[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.jad\UserChoice]
"Progid"="jadfile"

STEP 2: Set up the jadfile attribute

[HKEY_CLASSES_ROOT\jadfile\shell\vim]
@=">> vim"

[HKEY_CLASSES_ROOT\jadfile\shell\vim\command]
@="\"c:\\program files (x86)\\Vim\\vim73\\gvim.exe\" \"%1\""

[HKEY_CLASSES_ROOT\jadfile\shell\wtk]
@=">> wtk"

[HKEY_CLASSES_ROOT\jadfile\shell\wtk\command]
@="c:\\WTK2.5.2_01\\bin\\emulator.exe -Xheapsize:5M -Xdescriptor:\"%1\""

ANDROID: Factory Flash DroidX

Motorola Droid X SBF
http://www.multiupload.com/NYV7593UM3
http://www.multiupload.com/HS3Q4U95CG
http://rootzwiki.com/

Instructions (Linux)
1. Unzip the SBF and place VRZ_MB810_1.13.6.2_1FF_01.sbf and sbf_flash in the downloads folder
2. Put the Droid X in bootloader and connect it via usb.
3. Open a terminal window.
4.Change your directory: CD Downloads
5. Then type: ./sbf_flash VRZ_MB810_1.13.6.2_1FF_01.sbf
6. Wait and finish!

ANDROID: Superuser + Shared JNI LIBs

If you need access to system libs (in my case, uinput), you will usually need to do one of 2 things:

1. create another unix executable (binary), which will call uinput, and invoke it with su (super user). Put this file in the /raw directory, and copy it to the device during run-time. This seems to be the easier method. The source is as such:

your_copy_binary(R.raw.your_binary, getFilesDir().getAbsolutePath()+"/your_binary");
Process sh = Runtime.getRuntime().exec("su");
OutputStream os = sh.getOutputStream();
os.write("chmod 777 " + getFilesDir().getAbsolutePath() + "/your_binary" + "\n", "ASCII");
os.write(getFilesDir().getAbsolutePath() _ "/your_binary", "ASCII");

2. create a unix shared library embedded within your android app, call open(...) to directly access the system lib, give the manifest SUPERUSER permissions, and finally set the lib to chmod 777.

Here's the JNI sourcecode:
int success = open("/dev/input", O_WRONLY | O_NONBLOCK);

Here's the Manifest added permission:
< uses-permission android:name="android.permission.ACCESS_SUPERUSER" />

Here's the final step to chmod
chmod 777 /dev/uinput


I prefer the second method, because it's closer to how the android NDK was intended to run.

ANDROID: Eclipse J2EE Helios & Code Assist

Code assist is EXTREMELY slow for whatever reason on the HELIOS J2EE build. This wasn't happening before on Galileo. So I did some researching and found this nifty note on the interweb...

If you are using the JEE edition of HELIOS, the assists can be speeded up by turning off JAX-WS assist in the edit/advanced preference (Window->Preferences->Java->Editor->Content Assist->Advanced. It also appears that the assists cycle through a list of suggestion sources, starting with a different one each time, which would explain why the assists are not always slow.

Sped things up, but still slow... so then I checked for more links and ended with this one: https://bugs.eclipse.org/bugs/show_bug.cgi?id=317979

It states the bug is fixed in newer release of the Eclipse SDK. Too bad this still doesn't work!

Finally I reverted to GALILEO, and the issue is no more. It must be an issue on Android end, and not eclipse.

MACPORT: 1.9.1 + OSX 10.6.4

While attempting to install Android environment, it prompted me to install MACPORT, followed by this command:

POSIXLY_CORRECT=1 sudo port install gmake libsdl git-core gnupg

Which crashes when attempting to install db46, with a jni.h not found error. Some quick searching on the interweb later, I found this issue exists (probably) with the java sdk installed with Snow Leopard... and the fix is to install this dmg:

https://connect.apple.com/cgi-bin/WebObjects/MemberSite.woa/wa/getSoftware?bundleID=20719

or direct link to the dmg:

http://connect.apple.com/cgi-bin/WebObjects/MemberSite.woa/wa/getSoftware?fileID=26495&wosid=3h7EYNxPvekL2pGKzaKoAl6riR9



Edit: So this doesn't actually work for me, and I suspect it's because I'm on 10.6.4, not 10.6.3... but either way, I figured out how to get past db46:

copy and paste the content in:
/Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/JavaVM.framework/Versions/1.6.0/Headers

into:
/opt/local/include

After db46 is installed, be sure to remove these additional header files... it's a bad hack.

IPHONE: Binary Submission + Invalid Binary

Kept getting this odd INVALID BINARY error message today whenever I'd try to submit my binary.

The problem is I submitted my binary earlier this week as a iPhone-ONLY application, but wanted to go back and change it to be a 'Universal' build.

There used to be an option in Itunes Connect to choose which devices you wanted to target, but now it's all just handled in your application building process.

Anyway here's the settings for the ORIGINAL build that was an 'acceptable' build:
- Architecture: Standard (armv6 armv7)
- Base SDK iOS: Device 4.1
- Targeted Device Family: iPhone
- iOS Deployment Target: iOS 4.0

Here's what I tried to change the build to, which caused the INVALID BINARY error:
- Architecture: Standard (armv7)
- Base SDK iOS: Device 3.2
- Targeted Device Family: iPhone/iPad
- iOS Deployment Target: iOS 3.2

Here's what finally worked (universal build):
- Architecture: Standard (armv6 armv7)
- Base SDK iOS: Device 4.1
- Targeted Device Family: iPhone/iPad
- iOS Deployment Target: iOS 3.2

Too lazy to test exactly what was the cause of the issue, but it's obviously between the 'Architecture' or the 'Base SDK iOS'. My guess is the Architecture over Base SDK... but who knows.

JNI + MAC OS X: Simple sample

Couple things to be aware of:

#1. for MAC OS X, the binaries end with .dylib or .jnilib (not .so, .dll)
#2. when compiling the shared lib, you should split up the compilation from the linking
#3. when compiling the shared lib in MAC OS X, be sure to specify the JavaVM framework

The code is like every other JNI example, so I wont post it here. The actual problem was in the command-prompt commands... which should go something like this:

javac HelloWorld.java
javah -jni HelloWorld
cc -c -I/Library/Java/Home/include helloworld.c
cc -dynamiclib -o libhelloworld.jnilib helloworld.o -framework JavaVM
java HelloWorld

5 simple lines...

Do not use the following line to compile for MAC OS X, it will give you all sorts of complaints:
[g]cc -dynamiclib [-G] [-m32] -o helloworld.dylib -I/Library/Java/Home/include [-arch i386] helloworld.c

Again.. DO SEPARATE the COMPILATION and the LINKING steps!!!

These are common error messages that spawn from the above command...

Exception in thread "main" java.lang.UnsatisfiedLinkError: no helloworld in java.library.path (missing javavm definition)

Exception in thread "main" java.lang.UnsatisfiedLinkError: no suitable image found. Did find: ... mach-o, but wrong architecture (ironically, not really caused by wrong architecture)

Exception in thread "main" java.lang.UnsatisfiedLinkError: no suitable image found. Did find: ... can't map (happens when you use wrong architecture)

ld: library not found for -l..., collect2: ld returned 1 exit status

Undefined symbols: "_main", referenced from: start in crt1.10.6.o, ld: symbol(s) not found, collect2: ld returned 1 exit status



PRINTER: Sharing a printer over WAN

On a mac, sharing printers over LAN is easy, and only involves a single checkbox. Sharing over WAN is more difficult...

1. Under Utilities > Print & Fax, remove the printer from the "server" (the machine physically connected to the printer)

2. In terminal, type the following lines:
cupsctl --remote-any
cupsctl --remote-printers
cupsctl --share-printers

3. Now go into the terminal on the "client" Mac

4. In terminal, type the following lines:
cupsctl --share-printers
cupsctl --no-remote-printers
cupsctl BrowsePoll=SERVERIP:631
cupsctl 'BrowseLocalProtocols="CUPS"'
cupsctl 'BrowseRemoteProtocols="CUPS"'

Edit... if this works, but then fails again, try the following (in this order):
A. Turn off the printer, and back on again (the QUEUE may be backed up)
B. Remove the printer from the Printer & Fax setup screen, and add it back again
C. Clear the Printer & Fax settings by holding OPTION while clicking the MINUS sign
D. Repeat step C for both Client & Server machines
E. Repeat steps 1-4 above and make sure all attributes are correct by using cupsctl

RM: Operation not permitted

Not much documentation online that really helped.

Some people suggested using: ls -lo 'FILE DIRECTORY' to discover the special locks on the files/directories.

I solved it by using sudo: sudo rm -rf 'FILE DIRECTORY'

Android Video Streaming + Darwin Server

symptom: video stutters frequently. suspected audio is the reason, since video plays fine without audio.

solution: hint the videos with MP4BOX with the -latm option like this:

mp4box -hint -latm filename.mp4

FTP: SFTP with Filezilla

(assume you already have a PEM file)

goto view > settings

select connection > sftp

add keyfile...

select the pem file

check back if it didnt import correctly the first time

ANDROID: OpenGL White Screen Weirdness

For some reason the G1 was displaying a white screen in GLSurfaceView when the NexusOne was displaying images just fine.

Note that my GLSurfaceView is initialized to be ARGB 8888 with DEPTH BUFFER 16
Also, it is set with pixelformat.Translucent

Turns out, this is caused by texture loading, not the EGL. textures in GLES 1.0 needs to be in powers of 2! NexusOne solves that issue by using GLES 2.0, without letting the users know about it.

So, convert your bitmaps to powers of 2, before using the GLUtils method to create your textures!!!

ANDROID: Overriding OnMeasure

When generating a custom layout view, you will often need to override the onMeasure method. sometimes, you just want the width or height to 'fill_parent'... in this case we cant simply do:

setMeasuredDimension(fill_parent, fill_parent);

NOR can we pass in the width & height values received by onMeasure like so:

setMeasuredDimension(width, height);

INSTEAD, here's what you need to do:

super.onMeasure(w, h);
setMeasuredDimension(getMeasuredWidth(), getMeasuredHeight());

This will get you the parent's width and height, assuming you've set its layout-params to be (w=fill_parent, h=fill_parent)

ANDROID: Alpha Masking

Lets say we had 2 bg images, and wanted to use an alpha mask (black = invisible pixels, transparent = visible pixels) to mask those 2 bg images composite together...


(1) create default paint
(2) set filter bitmap to false
(3) draw bg #1
(4) draw bg #2
(5) set paint's setXfermode to dstOut
(6) draw mask
(7) set paint's setXfermode to null

however, if you are putting this View object on top of another view, the mask will ALSO mask out the pixels in the PARENT VIEW... this is obviously not wanted behavior. to resolve this, you could simply render everything to a mutable-bitmap, and in onDraw, just draw that bitmap instead. See below:


inside public void onDraw(Canvas onDrawCanvas);

mutable = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
canvas = new Canvas(mutable);
paint = new Paint();
paint.setFilterBitmap(false);

canvas.drawBitmap(bg1, 0, 0, paint);
canvas.drawBitmap(bg2, 0, 0, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT);
canvas.drawBitmap(mask, 0, 0, paint);
paint.setXfermode(null);

onDrawCanvas.drawBitmap(bitmap, 0, 0, paint);

ANDROID: Image Scaling

I was encountering a very bizarre error where images were all being displayed larger than actual pixelxpixel size.

Finally I figured out it was because anything placed in /drawable directory gets scaled automatically by the density value!

So the fix are as follows:

- Use drawable-ldpi, -mdpi, -hdpi directories for drawables instead!
- Use BitmapFactory.Options(); options.inScaled = false;
- Place any assets that should not be scaled in drawable-nodpi

ANDROID: Starting another Activity

From an activity...

Intent i = new Intent();
i.setClass(this, NewClass.class);
startActivity(i);

Where this is the main context...

ANDROID: Camera

When using the camera, you might see a weird error where in portrait, the camera preview shows 2 screens instead of one. This is because the camera orientation is LANDSCAPE by default. To fix this issue, you can do one of 2 things...

(1) Force your application to be in landscape by using the following in the manifest.xml



(2) Alter the camera parameters to account for the orientation differences:

Camera.Parameters parameters = camera.getParameters();
parameters.set("orientation", "portrait");
camera.setParameters(parameters);

NOTE: If your application is not of fixed-orientation, you will have to detect the orientation of the application and adjust the 2nd parameter string accordingly between "portrait" and "landscape"

Android: Custom XML Layout

main.xml usually takes a 'TextView'. But what if you wanted to use a 'custom' view instead?

to do this:

1. have a class that extends a View
2. define its constructor: public CONSTR(Context, AttributeSet, int)
3. in xml type in manually

< com.domain.package.CONSTR >

etc

< / com.domain.package.CONSTR >

DID

Again nearly forgot to report the progress last night. Spent the majority of time creating the project estimate for the Bear Bear project she wants to hire me to do.

The original estimate was actually approximately 200 hours, but at $45/hr, that amounted to over $9000. Knowing she wouldnt have it, I had to skim down some hours and take out any paddings.

All in all, part the $6500 from this project would go towards the iPad I would be developing with.

Secondly, I began redo-ing the danny-yu.com website. By using separate text files for containing the data, it's way easier to manage when new items need to be added.

Regex Look-Ahead/Back

This is a tricky topic, but here's the best explanation I found:

* (?=) - Positive look ahead assertion foo(?=bar) matches foo when followed by bar

* (?!) - Negative look ahead assertion foo(?!bar) matches foo when not followed by bar

* (?<=) - Positive look behind assertion (?<=foo)bar matches bar when preceded by foo * (? - Negative look behind assertion (? * (?>) - Once-only subpatterns (?>\d+)bar Performance enhancing when bar not present

* (?(x)) - Conditional subpatterns

* (?(3)foo|fu)bar - Matches foo if 3rd subpattern has matched, fu if not

* (?#) - Comment (?# Pattern does x y or z)


Example: I was looking for ABCabc123 in "apple/banana/ABCabc123"

regular expression: (?<=apple/banana/)\\w+(?=\")

AJAX: Internal Server Error 500

First lesson learned today: Always check the error logs whenever you get a weird server error with obscure message describing what actually transpired...

While attempting to use AJAX & PHP, I kept running into a weird Internal Server Error. After spending lots of time on google, it turns out that the problem was the PERMISSION (chmod) given to the PHP file being requested.

I had the php file set at PERM 0777, which apparently causes the server to freak out, because PHP files being writable can be a very, very dangerous thing.

Lesson #2: Set the permission for PHP on server to 0644.

MySQL on OS X

Seems like everytime I revisit mysql I'm confused about login & user creation, so here it is again:

log in using:

mysql -u USERNAME

create user using:

use mysql;
insert into user(host,user,password,select_priv) values
('localhost','USERNAME',password('PASSWORD'),'Y');

grant privileges to user:

grant all privileges on *.* to 'USERNAME'@'localhost' with grant option;

make sure to flush privileges to enable new accounts:

flush privileges;

to log in:

mysql --user=USERNAME --password=PASSWORD (optional: db name)

Maximizing windows in OS X

So my mouse was acting crazy, and basically it caused me to shrink a window down to like 2x10 pixels... impossible to drag back to maximum size. After some research, I found an AppleScript that can be used to maximize windows:
tell application "System Events"
if UI elements enabled then
set FrontApplication to (get name of every process whose frontmost is true) as string
tell process FrontApplication
click button 2 of window 1
--button 2 is the green "zoom" button for all applications
--window 1 is always the frontmost window.
end tell
else
tell application "System Preferences"
activate
set current pane to pane "com.apple.preference.universalaccess"
display dialog "UI element scripting is not enabled. Check 'Enable access for assistive devices'"
end tell
end if
end tell

I then downloaded QuickSilver (by blacktree), and bound the script to the keys COMMAND+Z. Now I can just select any window, hit COMMAND+Z, and the window will maximize again. WHEW! What a life-saver.

To add the script to QS, you do the following:
1. Goto the Triggers tab
2. Hit the small + icon at the bottom left
3. Select (add) hotkey
4. Click on the Command-Key column, and set your Hot Key
5. Double-click on the Command column
6. For Select an Item, select the apple-script you just created
7. The Action should automatically be 'Run'
8. Save and exit

Test out your script by pressing the hotkey... it worked for me :)

OpenGL: Copy PixelBuffers to GL Texture

NOTE: some source is omitted, but should be relatively easy to re-enter.

1. Create the pixel buffer

EGLint configAttributes[] = {
EGL_RED_SIZE, 5,
EGL_GREEN_SIZE, 6,
EGL_BLUE_SIZE, 5,
//EGL_ALPHA_SIZE, 8,
EGL_DEPTH_SIZE, 16,
EGL_STENCIL_SIZE, 0,
EGL_LUMINANCE_SIZE, EGL_DONT_CARE,
EGL_SURFACE_TYPE, SURFACE_TYPE,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT,
EGL_BIND_TO_TEXTURE_RGB, EGL_TRUE,
EGL_NONE
};

EGLint pbufferAttributes[] = {
EGL_WIDTH, width,
EGL_HEIGHT, height,
EGL_COLORSPACE, COLOR_SPACE,
EGL_ALPHA_FORMAT, ALPHA_FORMAT,
EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGB,
EGL_TEXTURE_TARGET, EGL_TEXTURE_2D,
EGL_NONE
};

eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
eglInitialize(eglDisplay, &major, &minor);
eglChooseConfig(eglDisplay, configAttributes,
&eglConfig, 1, &numConfigs);
eglContext = eglCreateContext(eglDisplay,
eglConfig, NULL, NULL);
eglSurface = eglGetCurrentSurface(EGL_DRAW);
eglPbuffer = eglCreatePbufferSurface(eglDisplay,
eglConfig, pbufferAttributes);

2. Create empty pbuffer texture (theSource) to render GL onto

glGenTextures(1, &theSource);
glBindTexture(GL_TEXTURE_2D, theSource);
glTexImage2D(GL_TEXTURE_2D, GL_RGB, width, height,
0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, NULL);
glTexParameterf(GL_TEXTURE_2D,
GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D,
GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D,
GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D,
GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

3. Drawing to the pixel buffer surface

eglMakeCurrent(eglDisplay, pbuffer, pbuffer, eglContext);
glBindTexture(GL_TEXTURE_2D, theSource);
// draw code, glDraw*, etc
eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext);

4. Creating the target texture (theCopy)

glGenTextures(1, &theCopy);
glBindTexture(GL_TEXTURE_2D, theCopy);
glTexImage2D(GL_TEXTURE_2D, GL_RGB, width, height,
0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, NULL);
glTexParameterf(GL_TEXTURE_2D,
GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D,
GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D,
GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D,
GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

5. Copying the pbuffer to the tagret texture (theCopy)

eglBindTexImage(eglDisplay, pbuffer, EGL_BACK_BUFFER);
glActiveTexture(GL_TEXTURE0 + theCopy);
glBindTexture(GL_TEXTURE_2D, theCopy);
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, 256, 256, 0);

UTF8 in Java

Java seems to already assume UTF8 encoding.

String test = "ÀÁÂÃÄ";
System.out.println(test); // prints out ÀÁÂÃÄ
System.out.println(test.length()); // prints out 5

Here's how to convert the above UTF8 string into series of bytes:

byte[] bytes = test.getBytes("UTF8");

And here's how to convert those bytes back into a Java string:

String utf8 = new String(bytes, "UTF8");

Both of these must be wrapped by try-catches in case your system doesn't recognize UTF8 encoding, which would be pretty rare...

UTF8 Encoding

in utf8, words can be 1-4 bytes long.

each word uses the first couple bits of each byte to signify that it's a command. there's probably some clever mathematics involved, but I'm not going to spend the time to go figure it out.

see http://en.wikipedia.org/wiki/UTF-8

U+0000 - U+007F stands for the simplest case, ascii values 0-127. all these values are a single byte, and the way you can tell is its first bit will be 0.

VALUE: 0xxxxxxx

U+0080 - U+07ff are the 2-byte characters. the first byte will begin with 110, and the second byte will begin with 10.

VALUE: 110yyyxx 10xxxxxx

U+0800 - 0xFFFF are the 3-byte characters. the first byte will begin with 1110, the second with 10, and the third again with 10.

VALUE: 1110yyyy 10yyyyxx 10xxxxxx

U+10000 - U+10FFFF are the 4-byte characters. the first byte will begin with 11110, and each byte thereafter begins with the 10 bits.

VALUE: 11110zzz 10zzyyyy 10yyyyxx 10xxxxxx

Where x: lowest 8-bits
Where y: middle 8-bits
Where z: highest 5-bits

The maximum value that can be represented is x^(5+8+8). However, for some reason, the UTF8 standard only uses 0x00 - 0x10 for the highest bits. meaning the maximum value for any UTF8 (right now) is 0x10FFFF.

See the next post for how to handle these values in Java.