Packaging Eclipse in OSX

Recently I experimented a bit with Eclipse packaging. At first it seems not very important, given that the folks at Eclipse work hard to produce executable packages. On the other hand, the Mac OSX packaging is not the best possible one.

The default folder structure of Eclipse applications on Mac OSX is something like follows:
[cc]eclipse
–configuration/
–dropins/
–features/
–p2/
–plugins/
–Eclipse.app/
–artifacts.xml[/cc]

In this structure Eclipse.app is a special folder, that acts as an executable item for OSX.

This structure is easy to produce, very similar to the ones of Windows or Linux, but there are some drawbacks. First, in the /Applications folder the folder icon is a generic folder, instead of an Eclipse icon (okay, this one is easy to resolve, as every folder can have a custom icon). More importantly, all indexer try identifies the executables by name. If there are multiple Eclipse instances installed, then every instance will have the same name displayed. If the path is also displayed, it is possible to distinguish between the instances.
Multiple Eclipse instances shown by the same name

Some time ago (~1 year) I tried simply renaming the Application bundle did not work, as there is seems to be some kind of configuration that won’t work after that. But this was quite a time ago.

Now I found another possible solution: there is an Eclipse repackager script shared in GitHub I could give a try.

The script is a simple bash script, with simple parametering:

[cc_bash]./EclipseOSXRepackager «eclipse source folder» «target.app»[/cc_bash]

A quick testing showed it does not handle dropins, so I hacked and shared a new version (and meanwhile I was able to test Git for the first time – btw. thanks for the fine tutorials, GitHub team 🙂 ).

My updated solution is available also from GitHub: http://github.com/ujhelyiz/yoursway-eclipse-osx-repackager

To tell the truth, even the updated script has some serious issues: I could break the app two ways: the smallest issue was, that P2 could not install or remove anything, or in the worse case the bundle couldn’t even start.

So I have a quick question: does anyone has a working solution for creating proper, working app bundles for OSX from Eclipse? Or simply could help fixing the repackager script?

Inkrementális enkóderek alkalmazása

Kicsit lassan haladok az önképzéssel, nehezen gyűjtöm össze a megfelelő mennyiségű szorgalmat, hogy a hétköznapi hajtás után egy-egy hétvégén pihenés helyett elővegyem a hardvereket a fiókból. Ezen a hétvégén kivételesen sikerült. Hogy pontos legyek, kezembe került egy inkrementális enkóder, ami (akinek nem ismerős a fogalom) arra jó, hogy forgó mozgás irányát, mennyiségét és esetleg sebességét meghatározzuk.

Az abszolút enkóderekkel ellentétben az inkrementális enkóderek nem képesek megadni a forgás pillanatnyi helyét, segítségükkel csak azt lehet meghatározni, hogy történt-e forgás valamelyik irányba. Viszont jelentősen olcsóbbak, és kevesebb lábat foglalnak el a mikrokontrolleren. Ez sem utolsó szempont, tekintve hogy pár óra kínlódás után rájöttem, hogy a kontrolleremen két láb halott..

Általában véve a forgási enkóderek működését a Wikipedia vonatkozó cikke jobban elmagyarázza, mint én tudnám, így erre nem térek ki részletesen. A lényeg csupán annyi, hogy egy egységnyi forgás alatt két kapcsoló zár az enkóderben egymás után, a forgás irányától függően. Ennek tipikus bekötése active-low jelleggel rendkívűl egyszerű, az enkóder C csatlakozója ráköthető a földre, az A és B lábak számára pedig kiválasztunk két portot a kontrolleren, az én esetemben ez RB6 és RB7 lett. Ezen kívül semmilyen más alkatrészre nincs szükség, hiszen a Pic16F690-es processzor integráltan tartalmaz felhúzó áramkört, ami képes magas szinten tartani az adott portot, és leföldelés esetén biztonságos szinten tartja az áramot.

A feladat tehát a következő: detektálni kell az enkóder kapcsolóinak a zárását, figyelembe véve a sorrendjüket, és ennek megfelelően kell egy változó értékét növelni, vagy csökkenteni. Ha az A kapcsoló zár előbb, és később a B, akkor növelni, ha fordítva akkor csökkenteni kell eggyel a változót. Az általam használt EC12E típusú enkóder 24 diszkrét egységre bont egy kört, azaz 15 fokonként képes érzékelni a forgást, tehát a változó értékét 15-el megszorozva megkapjuk a pontos forgást. Az enkóder mechanikus jellege miatt a használat közben számítani kell pergés előfordulására, aminek a kezeléséről gondoskodni kell.

A mikroprogram gyors időközönként leolvassa a kapcsolók állását, és ez alapján kell eldöntenie, hogy merre forgatjuk az enkóder karját. Mivel figyelembe kell venni a kapcsolók korábbi állapotát is, triviálisan adja magát egy állapotgép-alapú megoldás, ami a pergést úgy küszöböli ki, hogy megengedi az állapotok közötti oda-vissza ugrálást a pergést követve, a pergés stabilizálódásával pedig az állapot is a megfelelő értéken rögzül.

Az állapotgép bemenete a két kapcsoló állása és minden leolvasáskor végrehajt egy lépést:

Az állapotgép megfelelő élei biztosítják, hogy amíg valamelyik kapcsoló pereg, addig a megfelelő két állapot között lépkedjen. Az ábrán pirossal és kékkel jelöltem azokat a lépéseket, mikor is növelem vagy csökkentem a forgást mérő változó értékét.

A programot a gyakorlatban is kipróbáltam, assembly-ben írtam a Pic16F690-hez a kódot, és a pickit2 próbapanelen lévő 4 led segítségével jelzem a változó aktuális értékét:

#include <p16F690.inc>
     __config (_INTRC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _BOR_OFF & _IESO_OFF & _FCMEN_OFF)
 
     cblock 0x20
State		;state machine variable
Display         ;data to be displayed
     endc
 
     org 0
Start:
	clrf PORTB
     	bsf STATUS,RP0		; select Register Page 1
	bcf OPTION_REG,7
     	movlw 0xFF
     	movwf TRISA		; Make PortA all input
     	movwf TRISB
     	clrf TRISC		; Make PortC all output
     	clrf ANSEL 		; all pins digital
    
     	bcf STATUS,RP0		; back to Register Page 0 
     	bsf STATUS,RP1		; Reg page 2
	
	movlw 0xFF		
	movwf WPUB		; enable weak pull-up for Port B

	bcf STATUS, RP1		; Reg page 0

     	clrf Display
	clrf State

MainLoop:

;state table:
; input	|  000 	|  010	|  100	|  011	|  101	|
;  00	| 		->000			| == always ->000
;  01	|      ->010 	| ->000 | ->010 |->000- | == if state,0 ->000 (dec if 101), else ->010
;  10	| ->100	| ->000	| ->100 |->000+	| ->100 | == if state,1 ->000 (inc if 011), else ->100
;  11	| ->000 | ->011 | ->101 | ->011 | ->101 | == if state,0 ->101, else if state,1 ->011, else ->000

;decide current input: 00, 01, 10, or 11
;note that all input are active low

	btfss PORTB,6
	goto Input0
	goto Input1

Input0:
	btfss PORTB,7
	goto Input00
	goto Input01	

Input1:
	btfss PORTB,7
	goto Input10
	goto Input11

Input11: ;00
	clrf State		;state ->000
	goto Output
Input10: ;01
	btfss State,0		
	goto I01B		;if 0xx
	goto I01A		;if 1xx
I01A:			
		btfsc State,2	;if xx1
		decf Display,1	; decrement data
		clrf State	;->000
		goto Output
I01B:
		clrf State	;->010
		bsf State,1
		goto Output
Input01: ;10
	btfss State,1
	goto I10B		;if x0x
	goto I10A		;if x1x
I10A:
		btfsc State,2	;if xx1
		incf Display,1	; increment data
		clrf State	;->000
		goto Output
I10B:
		clrf State	;->100
		bsf State,0
		goto Output
Input00: ;11
	btfsc State,0		;if 1xx
	goto IA
	btfsc State,1		;or x1x
	goto IA
	goto Output
IA:
		bsf State,2 	;->uu1
	goto Output

Output:

     movfw     Display       ; Copy the display to the LEDs
     movwf     PORTC

     goto      MainLoop
     end

A dolgot összeállítva minden várakozásomat felülmúlva működött, a forgást pontosan és gyorsan méri, bár csak kézzel forgattam, így nem tudtam letesztelni, hogy mekkora szögsebességet képes még mérni. Mindenestre akár felhasználónak nyújtott bemeneti eszközként is remekül szerepelhet, mindenképpen kifinomultabb megoldás mint pl. egy potméter A/D átalakítóval. Digitális hifiken rendszeresen találkozhatunk ezzel a megoldással hangerő-szabályozás formájában.

Árnyékköpések: Food Fight

Életünk első kalandozása a Shadowrun világában, mely egy ártatlan bevásárlásnak indult, és amelyben sajnos minden NJK-nak volt neve. Featuring: Timi hangokat halló kalóza, TeoZ gremlin-elf adeptje, D-nee tárgyalóképes fegyverspecialistája, Overander figyelemelterelő covert ops specialistája, Eversong troll riggere, és természetesen Stampie, mint egykor ember KM.

JK1 (gremlins negative qualityvel): Nem csoda, hogy nincs commlinkem.
JK2: Persze, hiszen gremlin vagy.
JK1: Nem gremlin vagyok, hanem elf.

JK (rigger): Milyen messze vagyunk a kocsimtól?
KM: (hasból) …1 km-re.
JK: Pont 1 km a hatótávolságom!

JK1: Ott valaki mozog.
JK2: (miután perception testre dobott critical glitch folytán képzelődött) Én meg hangokat hallok!

JK: (NJK-król) Vagy egyszerűen nem álltak le gondolkodni.
KM: Túl sok az augmentation…

JK1: (két kétajtós szekrénnyel való harc közben) Mekkora egy szekrény sebzése?
JK2: Ez egy gyenge idegzetű szekrény.

JK: (miután elintéztük az összes ellent, de erről a karakter nem tudhatott, csak a játékos) Én felkiáltok, hogy nincs több… szerintem.

NJK: (frissen megmentve, félelemmel a hangjában) Kik vagytok ti?
JK: Shadowrunnerek, akik éppen most fejezték be első moduljukat.

Intelligencia – a telligencia ellentéte.

Mi a hiba a kódban? #2

A [intlink id=”1249″ type=”post”]múltkori, nagy sikerű írásom[/intlink] hatására Tompika küldött nekem egy hasonlóan izgalmas problémát.

[cc_java]while (true) {
Process p = Runtime.getRuntime().exec(“macska”);
p.waitFor();
}[/cc_java]

A kód eredeti, Tompika kedvenc állatait, a macskákat felemlegetve. A kód elméletben a következőt kellene, hogy csinálja: az első sor a [cci_java]p[/cci_java] referenciával elérhető módon indít egy processzt; míg a második sor vár, amíg a processz fut.

Ha megnézzük a kapcsolódó JavaDoc kommenteket, ez így működőképes is lehet. Ezzel szemben futásidőben problémák léptek fel, amiket feltehetőleg a következő kódrészletre való kicserélés javított:

[cc_java]while (true)
{
Process p = Runtime.getRuntime().exec(“macska”);
p.waitFor();
p.getErrorStream().close();
p.getOutputStream().close();
p.getInputStream().close();
p.destroy();
}
[/cc_java]

A kódrészlet utolsó sora vicces. Idézném a Javadoc kommentet:

[cci_java]public abstract void destroy()[/cci_java]

Kills the subprocess. The subprocess represented by this [cci_java]Process[/cci_java] object is forcibly terminated.

Amit én úgy értelmeznék, hogy a függvényt meghívva explicite lezárom a Processt. Viszont állítólag nem így történik. Valaki tudja a magyarázatot? Kíváncsi lennék rá.

PS.: ha valaki hozzájut hasonló gyöngyszemekhez, és eljuttatja hozzám, szívesen közzéteszem.

New service release: 0.7.2

I’m proud to announce that after a long time, we finally managed to throw out a new release. I’ve managed to improve the core functionality therefore this release contains a significant advance in overall performance.

Also, Stampie managed to fix a long-awaited feature, the two-way synchronization with the variables view.

In the future, we plan to redesign the use-cases of the tool. Currently, we’re in an experimental phase, which means we do not know how we want it to work.