Category Archives: Tech

MacFag-nek lenni jó

A feladat Nemrég vettem egy Mac minit media centernek, amibe a hétvégén Dr. iPod beszerelt egy SSD-t. A már benne levő hard disken szépen felkonfigurálva ott figyelt az operációs rendszer és az egész media center librarystől, így most az lenne az optimális, ha ez mind gyorsan átköltözne az SSD-re.

A megoldás

A hard disken alig 10 GB adat volt, így az simán felfér az SSD-re, csak abban nem voltam biztos, hogy ezt hogy lehet a legegyszerűbben megcsinálni. A megoldás az lett, hogy összedugtam a Mac minit egy másik Mac-kel, felbootoltam őt target disk módban, elindítottam a host gépen a Disk Utilityt és kértem úgy egy Restore-t, hogy a forrás volt az eredeti hard disk, a cél meg az SSD. Nem voltam biztos benne, hogy ez így flottul menni fog, tekintve, hogy két különböző méretű adathordozóról van szó – de simán ment minden. Az egész művelet a Thunderbolt drótnak köszönhetően pár percig tartott. Újraindítottam a Mac minit, meggyőződtem róla, hogy az SSD-ről korrektül ment a boot, aztán legyalultam a nagy hard disket és kész is volt a meló. Természetesen mindez egy dd onelinerrel ugyanígy ment volna, én mégis roppant mód megörültem annak, hogy ilyen simán lezajlott a dolog a Disk Utility használatával. Utólag persze nekiállt tekerni az agyam azon, hogy mindez működött volna úgy is, hogy recovery módban bootolok és onnan indítok egy Disk Utilityt. Mindazonáltal én úgy tartom, hogy a bölcs ember ilyenkor ahelyett, hogy a másik, ugyanazt megmutató utat is bejárná, inkább valami újat keressen. Ezért aztán kiültünk a teraszra és nekiestünk egy üveg Malbec-nek és némi zsíros sajtnak.
]]>

Excel VBA SpecialCells sucks

sample-spreadsheet Kérdezzük meg a VBA engine-t, hogy melyek azok a cellák, amelyek szerinte üresek az E4:F4 range-ben:

?Range("E4:F4").SpecialCells(xlCellTypeBlanks).Address
$E$4
Eddig rendben vagyunk. Most nézzük meg mit mondd, ha a vizsgálandó range-ünk csak egy cellát tartalmaz – legyen ez az E4:
?Range("E4:E4").SpecialCells(xlCellTypeBlanks).Address
$A$1:$C$2,$E$1:$E$2,$G$1:$G$2,$A$3:$B$3,$D$1:$D$3,$F$1:$F$3,$A$4:$C$4,$E$4,$G$4,$A$5:$B$5,$D$5,$F$5,$H$1:$H$5,$A$6:$H$15,$A$16:$G$16
Anyád, az. Tehát amennyiben a range egyetlen elemű, a .SpecialCells metódus a teljes táblát vizsgálja, nem pedig a szülőjének definiált egyetlen cellát. Ebből az lesz, hogy minden egyes .SpecialCells ellenőrzésnél egy újabb taknyolós workaroundot kell hegeszteni. ]]>

Media Center Szent Grál: tanulságos mese a megvezetett enduserről

XBMC-t tartalmazó raspbmc disztribúció. A 12-es XBMC (becenevén “Frodo“) már képes arra, hogy uPnP master-slave-et játszon. Ez annyit tesz, hogy míg az egyik média centeren futó XBMC uPnP szerverként megosztja a saját médiakönyvtárát, addig más XBMC-k uPnP kliensként láthatják ezeket a librarykat és így elég csak az egyik XBMC-nek karbantartani a metaadatokat. Nálam van két darab Raspberry Pi is, mindkettőn raspbmc, így nosza neki is álltam ezt élesíteni rajtuk. Az eredmény az alábbiakban részletezett kisebb káosz lett. A disztribúció installja ugyanúgy problémamentes, mint eddig, az uPnP beállítás sem rocket science – az egyik (server) XBMC-t megkérjük, hogy hirdesse magát uPnP-n, a másik (kliens) XBMC-nek pedig azt mondjuk, hogy a server XBMC által hirdetett uPnP megosztást vesszük fel media folder gyanánt. A dolog működik, ám egy ronda szépséghibája akad: a kliens XBMC-n az uPnP megosztás sorrendje csak név szerinti lehet, így azon nem tudunk pl. időben csökkenő sorrendet beállítani, hogy azonnal lássuk, mik a friss anyagok a megvásárolt DVD-inket mondjuk H.264 formában tároló gyűjteményünkben. A Raspberry Pi-n futó XBMC talán egyik legnagyobb előnye, hogy képes használni a kis masina HDMI kimenetén levő aktív CEC lábat, lehetővé téve ezáltal, hogy a HDMI CEC kompatibilis televíziónk távirányítója a teljes XBMC frontendet vezérelje (=egy remote mind felett rulez). Nos, a friss raspbmc disztibúcióval pont ez a funkció kezdett el akadozni. Minden egyes sleep után csak a Raspberry Pi-re kötött billentyűzet volt képes felébreszteni a mini média centert – úgy tűnt, hogy a CEC kapcsolat a sleep-pel együtt elmúlik, majd a gépet felébresztve újra létrejön. Ebből kezdett elegem lenni, így először nekiálltam fórumokat túrni, majd egy idő után más Raspberry Pi XBMC disztrókat keresgéltem. Így akadatam rá az openELEC és az XBian pakkokra. Az openELEC jött előbb – felpakoltam, bekonfirguráltam, hagytam, hogy libraryt scanneljen magának, kipróbáltam a média lejátszás funkciókat, majd vártam, hogy lemenjen sleep-be és megpróbáltam a TV távirányítójával felébreszteni: siker. Minden működött, így feltettem a másik Raspberry Pi-re is ugyanezt a csomagot, beállítottam azt is. Másnap meglepetten vettem észre, hogy az openELEC-en futó XBMC borzasztóan akadozik. Ránézek a CPU load-ra: 100%, pedig csak a főmenüben áll az XBMC. Új legális DVD másolat nincs a libraryban, ergo a scannerek sem futhatnak, hát akkor meg mi a rák ez? Szűk órányi googling előhozza, hogy két dolog lassíthatja szerencsétlent: a skinben bekapcsolt RSS feed, illetve a “Common Plugin Cache” nevű add-on, amit többek között a YouTube trailerek lejátszásához készített plugin is használ. Kikapcsolom mindkettőt, de még mindig magas a CPU load. Reboot: most már kicsit jobb – 70-85% közötti. Tanulság #1: a Raspberry Pi nem egy Cray supercomputer. Ha ezen a ponton nem járt volna tovább az agyam, az nagyon hasznos lett volna. De persze járt. Épp megszereltnek lehetne nyilvánítani a media centert, amikor eszembe jut, amit az előbbi googling közben az egyik fórumozótól olvastam. A srác a Plexet, az XBMC-ből forkolt média centert emlegette. Az ő Plex servere, ami a library managementet végzi egy Synology NAS-on futott. Ehhez már csak annyinak kellett beugrani, hogy az LG tavaly megiratta a Plex-es fiúkkal a serverük frontendjét a Smart TV-ikhez, és indultak is a fogaskerekek: csináljunk Plex backendet a NAS-ra és az LG TV-n próbáljuk ki a Plex klienssel! A NAS-ra gond nélkül feltelepült a Plex backend és némi konfugurálás után neki is látott a library építésnek. Miután elkészült, megnéztem, hogy mit mutat a TV-n. Nos, a TV egész konktétan egy Loading… becenevű homokórát mutatott úgy 3-4 percig onnantól kezdve, hogy megkértem őt a Plex backend által kínált libraryban való tallózásra. Valószínűleg valami LG store-ból kellett volna letölteni még egy Plex frontendet is a TV-be, ám ez már nem következett be, ugyanis a TV egyszercsak minden figyelmeztetés nélkül rebootolt. Néztem bután, mint ló a tüzijátékra, hogy ez meg mi volt. Első körben természetesen a gonosz új Raspberry Pi disztróra gyanakodtam, hátha ott valami watchdog űz nem túl fair játékot és küld valamit a CEC porton a készüléknek. Mire azonban oda jutottam volna, hogy input forrást váltok a TV készüléken és ránézek az XMBC-re, újabb reboot következett. Tanulság #2: a házilag gyártott media centerekkel lehet küzdeni bőven. Kezdett megindulni az adrenalin, így egy hirtelen mozdulattal lehúztam a Raspberry Pi HDMI kábelét a TV-ről és már mentem is volna XBiant installálni szerencsétlen openELEC helyére, amikor a TV ismét újraindult. Álltam, néztem egy darabig, hogy a boot után megjelenik rajta a NO SIGNAL felirat, majd megint jön egy reset. WTF? A dolog odáig fokozódott, hogy két reboot között cirka 30 másodperc már telt csak el. Lehet, hogy a TV hibás? Pár újabb rebootnyi ciklussal nagy nehezen eljutok odáig a TV menüjében, hogy megtalálom a Factory Reset opciót, aztán a következő rebootnál el is indítom. A reset lefut, a TV frissen, mindenféle beállítás nélkül jelentkezik be, majd amikor megnyugodva elkezdem újra konfigurálni, ismét újraindul. Nincs mit tenni, ez halott – én meg szerencsétlen openELEC-et hibáztattam! Becsomagolom a TV-t a hétfői szervizbe cipeléshez, majd leülök fórumokat olvasgatni, hátha más is pórul járt már folyton rebootoló LG Smart TV-vel. Mit ad az ég, egy rahedli bejegyzést találok, pontosan ugyanilyen esetekről. Sajnos mindenhol ugyanaz a válasz: vidd vissza és cseréltesd ki. Nincs sehol egy szervízmenü, vagy valami bootable USB image, amivel újra működővé lehetne varázsolni szerencsétlent. Már csukom be az utolsó ilyen fórumoldalt, amikor meglátom a legalsó bejegyzését: a jóember Plexet installált frissen és onnantól indult a reboot móka, majd leszedte a backendet és a probléma elmúlt. Nosza, TV kicsomagol, talp újra összeszerel, NAS-ról a Plex uninstallál, TV indít és minden újra a régi: az LG Smart TV reboot betegsége megszűnt. Tanulság #3: valami kóddarab van az LG Smart TV készülékekben, amit egy élő Plex backend képes annyira hanyattvágni, hogy az a televízió újraindulását eredményezi. Lehet, hogy majd egy software update ezt orvosolni fogja, de egész biztosan nem én leszek az a felhasználó, aki ezt ellenőrizni fogja. 2013 február 23-án vasárnap részemről eltemettem a Plexet örökre. ]]>

Media Center Szent Grál: feliratozzunk!

A probléma Filmünk van, ráadásul mondjuk sok, feliratunk meg nem van, főleg nem több nyelven.

A megoldás

Subliminalt installálunk:
  • leszedjük az aktuális master branchet innen
  • hagyjuk, hogy installálja magát: sudo ./setup.py install
Ha ez kész, megírjuk az alábbi getsub scriptet:
#!/bin/sh
for F in `ls -1 *.mp4 *.avi *.mkv *.m4v *.mov`
do
	echo Processing "$F"...
	BASE=${F%.*}
	if [ -f "$BASE.hu.srt" -a -f "$BASE.en.srt" ]
		then echo "Subtitles exists - skipping download."
		else
			echo "Trying to download subtitles..."
			/usr/local/bin/subliminal -m -l hu -l en "$F"
	fi
done
Mindezek után csak annyi a dolgunk, hogy bemászunk egy folderbe, ahol a sok film lakik és ráeresztjük a getsub scriptünket. Az eredmény jó esetben a filmfile-ok mellett keletkező .hu.srt és .en.srt állományok kellemes tömege. Advancedebb olvasóink rekurzívvá tehetik a scriptet. Update: az összes advanced olvasót megelőzve íme az ajándék minimalistább, ám annál rekurzívabb script (a tegnapi verzióban lemaradtak a space tartalmú fileneveket védő idézőjelek, amire ma hajnalra fds mester hívta fel a figyelmemet):
#!/bin/sh
find . \( -name "*.mp4" -or -name "*.avi" -or -name "*.mkv" -or -name "*.m4v" -or -name "*.mov" \) -and \( ! -iname ".*" \) -print0 | while read -rd $'\0' F; do
	BASE=${F%.*}
	echo Processing "$F"...
	if [ ! -f "$BASE.hu.srt" -o ! -f "$BASE.en.srt" ]
		then /usr/local/bin/subliminal -m -l hu -l en "$F"
	fi
done
]]>

CIB e-bank

hiszti és az egyik ezzel kapcsolatos threadben @vszakats tett ki egy non-applet futtató scriptet a Pastebinre. A script a saját könyvtárába létrehoz egy AppletLocal.html file-t, egy jogosultságot definiáló cibib.policy file-t, aztán letölti curl segítségével a CIB-től a cibib.jar appletet, végül elindítja. Az applet letöltése közben a curl néma, így azt érezheted, hogy nem történik semmi, pedig megy az, csak nem látod, szóval egy kis türelem, mire lejön a 2 megás applet. Ha egyszer lent van az applet és kész a HTML és a policy file, akkor elég ez a miniscript az indításhoz:

#!/bin/sh
dir="`dirname $0`"
appletviewer $dir/AppletLocal.html -J-Djava.security.policy=$dir/cibib.policy > /dev/null &
Az egész hóbelevanchoz természetesen nem kell Java browser plugin, azokat nyugodtan kikapcsolhatod, ahogy Józsi írta. Viktornak jövök egy sörrel, ha erre jár 🙂 Update #1: eti tuningolt a scripten kicsit. Az ő változata már megnézi, hogy módosult-e a CIB serverén az applet és csak akkor szedi le, ha igen (curl -z paramétere), továbbá kicsit kevesebb jogot adott neki, így természetesen etinek is jár a serital 🙂 Update #2: közben kiderült, hogy eti scriptjébe mégiscsak kell a több jog ahhoz, hogy az applet a Clipboardot használhassa. Én nem pöcsöltem vele, visszaadtam neki mindent, így most a script így néz ki. Update #3: eti elolvasta az stderr kimenetet és mégiscsak a minimálisan szükséges jogot kapta az applet. Update #4: eti közben kiókumulált még két jogosultsági beállítást, hogy legalább a plain text output működjön – sajna a PDF output továbbra sem jó, de már ez is valami! Az outputot az $output_dir-ben beállított folderbe pakolja majd az applet. Update #5: újabb eti tweak, hogy defaultban az output foldert nyissa meg az applet export target könyvtárnak.
#!/bin/bash
# //fns.pappito.com/2013/02/20/cib-e-bank/
#dir=~/tmp/cibib
dir="`dirname $0`"
output_dir=~/Desktop
[ -f $dir/AppletLocal.html ] || cat > $dir/AppletLocal.html <<eof
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en" style="overflow: hidden">
<head>
<title> CIB Internet Bank </title>
</head>
<body style="overflow: hidden;margin: 0px">
<applet name="mainApplet" code="ebank.applet.MainApplet" width="800" height="600" mayscript archive="cibib.jar">
<param name="CABBASE" value="https://cibib.cab">
<param name="default_fontsize" value="11">
<param name="PACKED" value="TRUE">
<param name="java_arguments" value="-Dsun.java2d.noddraw=true -Dsun.java2d.d3d=false">
<param name="separate_jvm" value="true">
<param name="centerimage" value="true">
<param name="boxborder" value="false">
<param name="image" value="loader_hu.gif">
<param name="MAYSCRIPT" value="true">
<param name="BASEVIEW" value="1">
<param name="LOGLEVEL" value="50">
<param name="PROTOCOL" value="https">
<param name="SERVERURL" value="https://ibank.cib.hu/IBWBGateway/IBGatewayServlet">
<param name="PRINTERURL" value="https://ibank.cib.hu/IBWBGateway/IBPrintingServlet">
<param name="LANGUAGE" value="hu">
<param name="INITWIDTH" value="800">
<param name="INITHEIGHT" value="600">
</applet>
<!-- <param name="DEMOMODE" value="TRUE"> -->
	<script>
window.onerror = myErrorHandler;
function help(pageName)
{
	help_window = window.open(pageName, "help", "toolbar=0,location=0,resizable=0,status=0,menubar=0,scrollbars=0,hotkeys=1,fullscreen=0,width=500,height=380,marginheight=0,marginwidth=0,dependent=1");
	help_window.focus();
}
function printWindow(text)
{
	msgWindow=window.open("","_blank", "toolbar=1,location=0,resizable=1,status=1,menubar=1,scrollbars=1,fullscreen=0");
	msgWindow.document.open("text/html", "replace");
	msgWindow.document.write(text);
	msgWindow.document.close();
}
function saveWindow(text)
{
	msgWindow=window.open("","_blank", "toolbar=1,location=0,resizable=1,status=1,menubar=1,scrollbars=1,fullscreen=0");
	msgWindow.document.open("text/plain", "replace");
	msgWindow.document.write(text);
	msgWindow.document.close();
}
function myErrorHandler(msg, url, linenumber)
{
	alert(msg + ' at line: ' + linenumber);
	return true;
}
	</script>
</body>
</html>
EOF
cat > $dir/cibib.policy <<eof
grant {
	permission java.net.SocketPermission "ibank.cib.hu:443", "connect,resolve";
	permission java.awt.AWTPermission "accessClipboard";
	permission java.io.FilePermission "$output_dir", "read,write";
    permission java.io.FilePermission "$output_dir/-", "read,write";
};
EOF
if [ -f $dir/cibib.jar ]; then
	modified_since="$(/bin/ls -lT $dir/cibib.jar | grep -o '[A-Z][a-z][a-z] [123 ][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9] [0-9][0-9][0-9][0-9]')" && \
	curl -z "$modified_since" -o $dir/cibib.jar.new https://ibank.cib.hu/cibib.jar || exit 1
	if [ -f $dir/cibib.jar.new ]; then
		mv -v $dir/cibib.jar{,.old} || exit 1
		mv -v $dir/cibib.jar{.new,} || exit 1
	fi
else
	echo "Downloading latest CIB applet..."
	curl -o $dir/cibib.jar https://ibank.cib.hu/cibib.jar || exit 1
fi
appletviewer $dir/AppletLocal.html -J-Djava.security.policy=$dir/cibib.policy -J-Duser.dir=$output_dir > /dev/null &
]]>

A hordozható adattárolókról

Józsi ajánló posztját, így azt gondoltam, pont passzolna mellé a dolog, úgyhogy vágjunk bele! Ha a Macintoshodon külső storage-ről szeretnél adatot elérni, az alábbi interfészek állnak rendelkezésre:

  • optikai meghajtó – nem jó. Kicsi, elavult, sérülékeny, lassan írható.
  • SD kártya – majdnem oké. Nem a leggyorsabb és a relatíve nagy kapacitás még drága, de kicsi, univerzális és viszonylag jól bírja a gyűrődést.
  • USB2 – lassan már nem oké. A leguniverzálisabb, de ahogy nő a storage igény, úgy érzed egyre lassabbnak. Cserébe viszont lassan a kávéfőzőn is van USB slot.
  • FW800 – nem oké. Sebességben veri az USB2-t, viszont minden ilyen csatlakozóval ellátott eszköz megkapja az AppleTaxot, amit a “buziAlmás” felhasználó fizet meg. Ezért cserébe a penetrációja is sokkal kisebb.
  • Gigabit Ethernet és WiFi – nem oké. Kevés a sebességük.
  • USB3 – oké. A sebesség már az, ami tisztességesnek mondható a mai (=2013-as) mércével, eszköz van bőven, az ár is megfelelő, viszont az Apple csak 2012 táján kezdett neki a 2008-ban tervezett standard implementálásának.
  • Thunderbolt – oké. A sebesség brutális, a szabvány tartalékai szintén, ám itt minden eddiginél irgalmatlanabbul súlyt le az AppleTax: az amúgy is méregdrága Thunderbolt csatolós eszközökhöz a gyártó licencspórolási céllal nem mellékeli a Thunderbolt kábelt, ami a usernek akár 10kHUF nagyságrendű újabb lehúzást is jelenthet (lásd a printerkábelek kispórolása anno, csak ez ma még gusztustalanabb mértékben megy).
A teljesség kedvéért: fentiekhez non-Apple világban csapódna még az eSATA. Megvan a lista, nem is elemezgetném, hanem inkább elmondom az általam talált megoldásokat.

The Nifty MiniDrive

Kickstarter project. A lényege, hogy a ma már minden Mac notebookon jelen levő SD kártya slotba egy olyan micro SD kártya foglalatot gyártsanak, ami teljesen belesimul a gép síkjába: Micro SD kártyák jelenleg 256 GB kapacitásnál tartanak (igaz eddig csak noname-ben láttam ekkorát, a SanDisk 64 gigánál tart). A Kickstarter project 2012 augusztus elején zárult, az utolsó infók szerint 2013 január végén indul a szállítás.

Seagate FreeAgent GoFlex Thunderbolt Adapter

A Seagate a hordozható GoFlex HDD családjához fejlesztette ezt a Thunderbolt adaptert: thunderbolt-portable-adapter Noha erről a gyártó sehol nem tesz említést, az adapter természetesen egy közönséges 2.5″-os SATA HDD csatlakozó. Ennek megfelelően bármilyen vele kompatibilis storage-et rádughatsz, nem kell annak GoFlex dobozban lennie. Egy tetszőleges méretű SSD-t ráapplikálva lényegében lebomlanak a sebességhatárok és brutális teljesítményű mobil adathordozót kaptál a kezedbe. Just think about it.]]>

Apple Maps for iOS vs Google Maps for iOS IRL teszt

iPod illesztőkábel. Az út elején erre a kábelre csatlakoztattuk az iPadet, míg egy mezei szivargyújtós töltő töltötte az iPhone akksiját. Sokáig nem tudtuk mire vélni, hogy mitől bolondult meg az iPad: bármelyik navigációs alkalmazást indítottuk el, mind össze-vissza dobálta a pozíciónkat, fogalmuk nem volt, milyen irányba halad épp az autó. Közel 10 perc küzdelem után jöttünk rá, hogy a problémát a Pioneer CD-IU51V kábele okozza: amint lehúztuk az iPad-ről, a GPS újra magához tért és minden ment simán. Summa summarum, ha ilyen bajod van, mindenképp érdemes a töltőkábelre is gyanakodni.]]>

Ékezet gyilkolás vim-mel

" Remove diacritical signs from characters in specified range of lines.
" Examples of characters replaced: á -> a, ç -> c, Á -> A, Ç -> C.
function! s:RemoveDiacritics(line1, line2)
  let diacs = 'áâãàçéêíóôõöőüúű'  " lowercase diacritical signs
  let repls = 'aaaaceeiooooouuu'  " corresponding replacements
  let diacs .= toupper(diacs)
  let repls .= toupper(repls)
  let all = join(getline(a:line1, a:line2), "\n")
  call setline(a:line1, split(tr(all, diacs, repls), "\n"))
endfunction
command! -range=% RemoveDiacritics call s:RemoveDiacritics(<line1>, <line2>)
Ezek után már csak meg kell nyitnunk az ékezetes szövegfile-unkat vim-ben és kiadni a :RemoveDiacritics parancsot – voila! ]]>