tag:blogger.com,1999:blog-83009114679737056492024-03-19T01:47:22.366-07:00Dr. katz's closet - Of Man, Women, Life and Computer ScienceSupper for ewwrydayTone Kastlungerhttp://www.blogger.com/profile/03560854879582481991noreply@blogger.comBlogger67125tag:blogger.com,1999:blog-8300911467973705649.post-26780378629781843842024-03-08T14:00:00.000-08:002024-03-08T14:00:33.633-08:00#chatgpt - an adventure; with codereview!<p> So there's alot of fuss around AI lately; it's been stirring my curiosity for a while - it's been a long time since playing with it in chess games at university.</p><p>For fun, and to explore; i deciced to want to make a "maze" game. A very simple game in which you have to figure out how to get out of a maze, while avoiding enemies.</p><p>Nothing fancy, very basic prototype level stuff. Only one requirement: let chatgpt do all the work!</p><p><br /></p><p>So far, I have:</p><p>- a maze</p><p>- a player</p><p>- two enemies</p><p>- a rendering loop</p><p>- collision engine<br /></p><p>- and some stats</p><p>The first funny thing; it calls python "pseudo-code" (i.e. it coded it in python from the beginning). There was a bit a hassle with setting up the dependencies for the OpenGL piping (on Debian), but otherwise it runs. I had a few iterations on it; code restructuring was particularly painful (apparently class structure context is something that gets easily lost when extrapolating from a single file to individual ones - i.e. one per class); when I decided to move the maze code into it's own class, the references to it woule have been still "maze", but it didnt acknowledge the actual maze data present within the maze class (as in maze.maze was missing from the other classes using it).<br />Most of the logic is then also glued into the rendering class, for some reason - I wonder if the notion of the inversion of control pattern is tricky for it.<br /><br />So after this output, we get this: </p><p><img alt="" height="540" src="data:image/png;base64,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Z/NHj156x39a9w/FOnBwcetnLz7/5Y7dlevef/ySeQt2hPB0OXnq3GtnVN73s18++ObXWyorNq344IX7b332uy/ryA3J3f/8RdmQY+77RvsCj8mUefT55w365I83LFy2tbqmcvUrd93/ese0c04kRMbqbcF1EUAAAQQQQACBwAKWE+799yPH7b5v1piSIVMufnvMubMK9j9ato699JHbJ625/qjhg8eccMOyQ+6+53TtM4sB+rSWXrTovT+f0vS3S44ZO7T0kBMuvH9pU3rG924pupxOp+v7z6pTJ16+8M/npr15w9kzj5l12V92T7rmod/O7MeNyADQHEIAAQQQQAABBGIoYJbPLOou3/ba7KI5tr/vfPKE73/Qscsj1LpVO7KV0hke3VutODqLXVc6DhSpKy8vnzNnTpevzQkIIIAAAggggAAC/gUWLFhQVlZms8l3XPYX2deKtbNYdMVsNssr2UqRXtX2+zf7HFu+WdNSOIDHyP7VOYIAAggggAACCCBgMtleuPna6klnHnPosDznrs+evvL+1aP/98/jvvutSIwQQAABBBBAAAEEEPASsA3IqXz0dz++ZUtlTXt60bijL3zuz9dOlN/joSCAAAIIIIAAAggg4FfANv2Kv757hd/DHEAAAQQQQAABBBBAwFuAL0B7m1CDAAIIIIAAAgggEESAEBkEiMMIIIAAAggggAAC3gKESG8TahBAAAEEEEAAAQSCCBAigwBxGAEEEEAAAQQQQMBbgBDpbUINAggggAACCCCAQBABQmQQIA4jgAACCCCAAAK9RODB/+z+v1cqQpwsITJEKJohgAACCCCAAAIIfCfA36bh3YAAAggggAACCPQugfmv7Tqxrt95Uwtl2ut3t969ZGerwzysIKNfdorZag3RgjuRIULRDAEEEEAAAQQQMIjANTMLV+xofn1Vrcznjjd2nTguZ9HFpVce3/+9dfWhz5AQGboVLRFAAAEEEEAAASMIpNgsx4/N+XBdw94m+7a97bIvsyrukzS1NCv06fE4O3QrWiKAAAIIIIAAAkYQkMfZyfkp2enJ9S0OmU926v67irnpthZ7qBMkRIYqRTsEEEAAAQQQQMAYAr87eUBZ2VCbzVbXZpYZNbY5U5LdM9vb2JGemhTiHHmcHSIUzRBAAAEEEEAAAYMIOF2mRV/u+8/a+vwMW1Gf5DdW1cnE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" width="659" /> </p><p>quite an open maze, I must say. I will try to solve this problem later on.<br /></p><p>The stats also do not show, despite being there (there should be a header with a life counter).</p><p>The whole process of prompt "engineering" (or whatever it is heretically called) is just brain dumb. Telling chatgpt what is needed is actually _very_ tedious, and can easily lead to errors. Another thing : chatgpt _cannot_ commit to github. Now that's quite the deal; yes of course chatgpt is storing every change for you, and it can revert to any of them at any point; but if you'd want the flexibility of git in it, it'all download/add/commit/push/merge cycles. Unhandy to say the least.<br />Also, when you ask it for a change, chatgpt will stay specific, i.e. it will prefer to output a short part of the code you are asking changes for, instead (for example) of the whole file with the new changes in it (this makes copy pasting tedious too). It's also "missing out" on some module imports for constants (mainly DOUBLEBUF, OPENGL, which come from the pygame module). As well the font initialization part was missing.</p><p>Now lets say I want to add some extra logic (If I click on a wall, I want to be able to "move" the brick by one cell forward or backwards). This is the changeset chatgpt proposes:</p><blockquote><p>48a49,50<br />> self.dragging_wall = False<br />> self.dragging_wall_pos = None<br />72a75,78<br />> def handle_mouse_down(self, x, y):<br />> x = max(0, min(x // 20, self.maze_width - 1))<br />> y = max(0, min((y - 50) // 20, self.maze_height - 1))<br />> if self.maze.maze[y][x] == 1:<br />> self.dragging_wall = True<br />> self.dragging_wall_pos = (x, y)<br />> <br />82a89,97<br />> def handle_mouse_up(self):<br />> self.dragging_wall = False<br />> self.dragging_wall_pos = None<br />> <br />87,89d101<br />< # Handle dragging wall<br />< if self.dragging_wall and self.dragging_wall_pos is not None:<br />< x, y = pygame.mouse.get_pos()<br />94,107d105<br />< x = max(0, min(x // cell_size, self.maze_width - 1))<br />< y = max(0, min((y - header_height) // cell_size, self.maze_height - 1))<br />< if self.maze.maze[y][x] == 0:<br />< self.maze.maze[self.dragging_wall_pos[1]][self.dragging_wall_pos[0]] = 0<br />< self.maze.maze[y][x] = 1<br />< self.dragging_wall_pos = (x, y)<br />< <br />95a108<br />> def draw(self):<br />102a116,119<br />> elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:<br />> self.handle_mouse_down(*event.pos)<br />> elif event.type == pygame.MOUSEBUTTONUP and event.button == 1:<br />> self.handle_mouse_up()<br />108,109c125,126<br />< glVertex2f(x * cell_size, y * cell_size + header_height)<br />< glVertex2f((x + 1) * cell_size, y * cell_size + header_height)<br />---<br />> glVertex2f(x * cell_size, y * cell_size + header_height)<br />> glVertex2f((x + 1) * cell_size, y * cell_size + header_height)<br />111,112c128,129<br />< glVertex2f((x + 1) * cell_size, (y + 1) * cell_size + header_height)<br />< glVertex2f(x * cell_size, (y + 1) * cell_size + header_height)<br />---<br />> glVertex2f((x + 1) * cell_size, (y + 1) * cell_size + header_height)<br />> glVertex2f(x * cell_size, (y + 1) * cell_size + header_height)<br /><br /></p></blockquote>But hey it's been one hour tops, and I am this far! The enemies move, adn the player is controllable. Impressive. The same game took me about 6 hours to code a few years back (mainly the maze algorithm was a bit cumbersome).<br /><p> </p>Tone Kastlungerhttp://www.blogger.com/profile/03560854879582481991noreply@blogger.com0tag:blogger.com,1999:blog-8300911467973705649.post-36011720090464277512024-02-25T13:42:00.000-08:002024-02-25T13:42:45.730-08:00Jira Herp derp #2<p> So Jira.</p><p>At it again.</p><p>Damn.</p><p>It used to be a decent tool (avoiding flame wars here /flame:off).</p><p>But recently with all the cloud jazz from atlassian, life has become impossible with jira.</p><p>Sorry jira, our relationship is not working anymore. It's not you (but it is), it's just that we want...different things, I guess.</p><p><b>You</b> want to make more money for yourself, to be able to sustain your growth (and buy shiny new features, which will clog your already clogged UI).</p><p><b>I</b> want to have a simple UI, which I can use to track my acitivity and integrate with my CI cycles.<br /></p><p><b>You</b> want to make sure everthing is secured properly; and because of that, you go and hide in the cloud, as if that would be a safe place to be. And not only that, you take all your companion apps with you!<br /></p><p><b>I</b> want to be able to install/manage relevant versions of you according to my needs, be it with the basic jira <i>or with the companion apps</i>. After all, <i>I have paid for your already </i>(see previous post).</p><p>Why should I have to pay (alot) more for :</p><p>- the same functionality</p><p>- in a foreign environment (the cloud)</p><p> just because <insert reasons here atlassian>?</p><p><br /></p>Tone Kastlungerhttp://www.blogger.com/profile/03560854879582481991noreply@blogger.com0tag:blogger.com,1999:blog-8300911467973705649.post-31184664901001972842024-02-25T13:35:00.000-08:002024-02-25T13:35:19.275-08:00Disagreements, by grades of severity<p>During my work life I have come to the conclusion that in fact, all that matters are interactions with people; meaning the people you work with, as well as the interactions one has with the others in the context of a team and/or group; specifically a software engineering/developing group in this (and my) case / experience.<br /><br />It is relevant that the quality of the outcome is affected by the quality of the interactions; and least not only that, also one's experience on the team will be affected. So communication is affecting (of course) a big part of that outcome. Given that communication, then, plays such a big role in the quality of the outcome, one has to realize that conflict, in a team, plays the opposite role, i.e. degrades the quality of the output. Conflict is one of the team traits that I feel are often mentioned; but at the same time its <i>expected</i> from everyone to be capable of handling it. Personally I don't like the word "conflict" itself. Its too broad of a term; when we talk about "conflict", it's very uncertain what we mean. Armed conflict? How would that translate into a Software development team - armed assault? Verbal violence? Personal attacks? Or fad arguments against one's own opinion? Passive-aggressive comments? Banter chit-chat in the interested person's absence?<br /></p><p>Conflict is a dangerous word. Back in the 1920's, futurists (and later fascists) belived the world could be changed (for the better) only with conflict. <br /><br />Fast forward 100 years later, the world has suffered the biggest armed conflict in human history, with millions of lives spent; the Futurists (which by then had become Fascists) had proven the way of changing the world they envisoned not to be the right one, therefore humiliating themselves and their thought school.<br /><br />The Fascists, as a team, failed. Their "ways of working", their "tools", did not survive. Conflict was shown not to be the "herald" virtue it had been advertised for.</p><p>The Fascist's (failed) endeavours is a perfect example as in how conflict is toxic for a team (and im sure everyone agrees on this); even if used as an external tool for "improving" the team's own wellbeing (you won't make good friends if you make everyone an enemy).<br /></p><p>I've come to cherish different grades of "hostility" (if you pass me the term) whilst communicating through the years:</p><p>- disagreement</p><p>- questions</p><p>- (counter)argument</p><p>- agreement</p><p>- violent agreements</p><p>Each of these carry a different grade of severity; heaviness in being addressed; and difficulties for the approach. <br /></p><p>A <i>disagreement</i> is the simplest form; i.e. any reason that is incapacitating people to find consensus / understanding / common ground.<br />Typical scenarios can variegate from hearing only "no", to offensive expressions flying in the air.</p><p>A <i>question</i>, as such, is a simpler and more neutral form. They might be part of disagreements, or then gather people towards consensus, which is where they get the neutrality from. On a question, you typically have an answer; but the difference is, the discussion ends there. The answer satisfies the need for knowledge completely, no other question (argument or counterargument) is necessary.</p><p>An <i>argument</i>, or counter argument, you can have presented either as a reason in a (civilised or uncivilised) discussion, or as a question, posed as an answer to another question, or a follow-up question to an answer. </p><p>An <i>agreement</i> is then the situation of (peaceful) "yes"'es which highlight the fact consensus has been achieved, and everyone (or at least the relevant parties) are on the "same page".</p><p>A <i>violent agreement</i>, finally, tackles down to an<i> argument</i> being <i>agreed</i> on by all the involved parties, in a "violent" fashion. Think of someone all being involved in a discussion on a given topic; but all shouting wildly "yes" at eachother, as if every one's "yes" would be better than the others (spoiler: they are all good the same, but the passion transpares here the most). <br /></p><p>The maturity of a team (and the individuals composing it) can be seen from how "conflict" situations are handled; more mature teams are more likely to not dig into the details of the issue, whereas younger, less mature teams will tend to split arguments up, hereby achieving the opposite effect, i.e. generating more tracktion for the respective cause - the conflict will spread. Mature teams will most likely steer clear from disagreements with the help of questions, to hover over into arguments, and from there to agreements (be them violent or not).<br /></p><p><br /></p><p><br /></p>Tone Kastlungerhttp://www.blogger.com/profile/03560854879582481991noreply@blogger.com0tag:blogger.com,1999:blog-8300911467973705649.post-22897897299379694462022-10-22T14:20:00.002-07:002022-10-31T09:30:51.761-07:00Hardware-ology - how to restore a Vaio laptop to Win10<p>So I happened to get ahold of an old Vaio Laptop. No recovery disk. At time of use, came with Win7.<br /></p><p>My kids have asked for a laptop for a long time for now, and I figured this is a good shot.</p><p>However.</p><p>The Vaio is pretty old (~2018 or such), and targeted to Win7.<br />The bios on it appears to NOT be able to boot from other than FAT32 partitions.<br />Win10 images come in UDF format (some industry craze of later times apparently),<br />which - you guess it - cannot be picked up by the bootloader on the Vaio (needless to say, the bios is as barenaked as possible).</p><p><br />After excluding also PXE (my home router does not support it); it seems there is time to take a different step. How about slicing out the extras from the Win10 installation image to make it fit on a 4GB partition? In the end, it's merely 1.8 GB over that limit. Shouldn't be that hard, right?</p><p>So I found <a href="https://www.dell.com/support/kbdoc/de-de/000127789/windows-10-iso-enth%C3%A4lt-eine-wim-datei-die-f%C3%BCr-das-fat32-dateisystem-gro%C3%9F-ist?lwp=rt">this link</a> from Dell that tells how to slice the windows image.<br /></p><p style="text-align: left;">However.</p><p style="text-align: left;">I have been a debian user for about 7 years now, so there is no windows machine around at my home. </p><p style="text-align: left;">So, the best solution was to get one of the Edge Virtual machines Microsoft kindly provides, and hope the tool in question ("dism") is available...and guess what? On the Win10 VM, it is!<br /></p><p style="text-align: left;">So, downloading the latest Win10 ISO, installing guest tools on the Edge VM, sharing a folder, correcting the file access rights to basically 777 to _everything_ and splitting the install with this command:</p><p style="text-align: left;"><br />`dism /Split-Image /ImageFile:"c:\temp\install.wim /SWMFile:"c:\temp\install.swm" /FileSize:4000`</p><p style="text-align: left;">Great. That was easy. Now we have a Win10 ISO that fits on a FAT32 partition.<br /><br />Unfortunately, the Vaio still does not comply with the USB stick and just display an empty screen with a flickering cursor.</p><p style="text-align: left;">The Vaio itself is not a USB-3 device. But the stick is 2.10.</p><p style="text-align: left;">Bummer.</p><p style="text-align: left;">So the next step is, if it's not a "legacy" boot device, it can only be a UEFI one, right?</p><p style="text-align: left;">Thanks to the Alpine people, over <a href="https://wiki.alpinelinux.org/wiki/Create_UEFI_boot_USB">here</a> we have perfect instructions on how to create a UEFI-compatible boot stick.</p><p style="text-align: left;">So, in this case, reformat the stick, and re-sync all the files (this has become tedious by now hasn'it it?).</p><p style="text-align: left;">Well, same result. Bummer #2</p><p style="text-align: left;">EDIT : long story short, downloading Rufus and installing the ISO on the usb stick was the straightforward solution. Done.<br />For some reason, the formatting of the stick is incredible specific for these old MBR/UEFI booting machines.<br /></p>Tone Kastlungerhttp://www.blogger.com/profile/03560854879582481991noreply@blogger.com0tag:blogger.com,1999:blog-8300911467973705649.post-90365438757782786542021-08-29T12:25:00.010-07:002021-08-29T13:12:36.766-07:00The Barber paradox<p>The barber, a well-shaved man, shaves all and <i>only</i> the people from a town who do not shave by themselves. Who shaves the barber? <br /></p><p>A barber - as defined by the assumption - is someone who shaves <i>all and only </i>people who do not shave by themselves. <br />Furthermore, any individual is a barber, as long as he shaves more than one person. Let's assume for simplicity there to be only one barber.<br /><br />"All" in the context of the statement is not defined as a number; but we can assume (for the sake of
simplicity) for it to be more than one, i.e. at least two. The definition, furthermore, states also that
there is more than one person (=people) that do not shave alone. <br /><br />Lets assume all the villagers, including the barber, those who shave alone, and those who don't, to be individuals. Let's also focus only on the individuals who do not shave alone, and the barber, and forget the ones who shave alone.<br />Let's further include another assumption, i.e. that all individuals can shave.<br /></p><p>Assuming we have only one individual acting as a barber all the time in the town (i.e. one single individual who shaves more than one, and all persons from the set that do not shave alone).</p><p><br />In the set of individuals, a barber stands out as an individual who shaves more than one person - in fact the barber shaves "all" the people who do not shave alone - except himself, which he cannot, due to definition (this btw precludes him being part of the set of people who do not shave by themselves). All other individuals can shave without being barbers, as long as everyone shaves only one and the same person - the barber.<br /><br />All the people who are shaved by the single barber can therefore shave
the barber; as the barber is a single individual; they do not have to be
considered as barbers in the terms of the original definition.<br /><br />This sets the barber into a "special" barber set - it shaves everyone; but is shaved by everyone else.<br />Moreover; the barber is not a barber, if he shaves himself.<br /></p><p>Is this crazy or what?<br /><br />Further developments:<br />- barber is a role that changes from individual to another (in turns; the question is, not who shaves the barber, but <i>who is the barber today</i>? ); i.e. can there be more than one barber in the town, for whom the same restrictions apply?<br /><br /><br /></p>Tone Kastlungerhttp://www.blogger.com/profile/03560854879582481991noreply@blogger.com0tag:blogger.com,1999:blog-8300911467973705649.post-35380291730253437012020-10-30T16:29:00.003-07:002020-10-30T16:29:11.961-07:00JIRA herp derp!<p>So you want to use jira, because it's fancy and great and awesome. Yes you are right, it is good (at least for sw development).<br />And you want to do it quickly; so you use a docker container?<br />And you want to use it safely; so you want HTTPS?<br />And you do NOT want to put it behind an apache reverse proxy?<br />Well, Tomcat supports https just well.<br />BUT! Keep in mind that the key store needs to be in JKS format,as the JVM is 1.8.xx. Yes, ladies & gents, in atlassian's docker container, the JVM is ancient.<br />I just spent three hours figuring out why "trustAnchor is empty". Herp derp<br /></p>Tone Kastlungerhttp://www.blogger.com/profile/03560854879582481991noreply@blogger.com0tag:blogger.com,1999:blog-8300911467973705649.post-52550785455332742442019-04-21T07:06:00.000-07:002019-04-26T12:29:09.608-07:00Let's do the time-warp again! Or, compile LLVM in SB2 on the SFOS sdk (x86 target)<div dir="ltr" style="text-align: left;" trbidi="on">
Yes; this sounds like one of these epic challenges.<br />
The stock browser of SFOS is pretty much abandoned to itself. It is gecko-based; gecko has been labeled as "deprecated" by Mozilla, then as "still supported", then got re-promoted to a (somewhat obscure) "we keep it until we can switch". The switch in question meaning to be the jump to servo, a rust-based web engine used in their latest quantum-based firefox. So the idea is to compile it on the x86 target to begin with.<br />
<br />
Achieving this faces challenges.<br />
<br />
In order to achieve this goal, we will need clang, which requires
llvm and a decently recent (>=4.9.5) gcc compiler, as well a decently
recent python 3 verison (>=3.5.0). On top of this, we have here:<br />
<br />
a) the glibc in the mer toolchain (at the time of writing) is stone age (2.19)<br />
b) the compiler in the mer toolchain (at the time of writing) is old (4.8)<br />
c) the compilation environment, scratchbox2 (a legacy development chroot originally developed by Nokia), has aged a bit, but the taste has slightly bitterned, and might cause acidity of stomach to some newer software's.<br />
<br />
The first two points affect mainly the correct functionality of llvm. <br />
llvm as a compiler is a different type of beast. In that it reimplements some functionalities in it's own ways, to ensure portability across multiple platforms. For example, locks via symlinks (same as pthreads do for instance). This exact feature of llvm is the first hurdle to overcome in order to get a functional toolchain; it uncoveres a non-POSIX conformance issue in <a href="https://bugs.merproject.org/show_bug.cgi?id=1997">mer / scratchbox2</a> (on i486 architecture) related to symlinks path resolution (in the mapping logic).<br />
<br />
scratchbox2 as a development tool is very powerful; it allows to build for multiple targets, by isolating each specialized environment, and allowing fine-grained customization for the developer; combined with easiness of switching between these. Needless to say, the flexibility of this tool is admirable. Packages can be installed in specific environments(so-called "targets"), multiple architectures are supported, targets can be exported/copied, you name it. All of this is possible thanks to an interception layer, provided via a customized <i>pre-loader</i> library, configured as default when entering the development MER chroot, and which takes care of mapping the active target to the "real" counterpars (in terms of files) by intercepting and managing the most well-known System calls / glibc api's (open, close, execvp and so on). <br />
It needs to be also mentioned that nowadays (with MER merging int SFOS)
the platformc chroot has been officially replaced by VM's, which ship
scratchbox2 pre-installed.<br />
<br />
<br />
The 'box2's interception layer's has limits, however, and they become visible on our journey to firefox. Take pthread, for an example; a library on it's own, but which (as an implementation) "lives" at glibc's home repository. This vicinity causes trouble for sb2, as the closeness gives way to <a href="https://bugs.merproject.org/show_bug.cgi?id=2000">"priviledged" relationships</a> (in terms of api's) between pthread and glibc; now before you scream in disgust, these types of "close" relationships are very much acceptable from a glibc's or pthread's perspective (coherence of api's), if not welcomed (performance), and make sense in glibc/pthread's universe (coherence). But for the outsider's ('box2) interception layer, as an alien, this is a major <a href="https://bugs.merproject.org/show_bug.cgi?id=2017">problem</a>, an interaction which is totally invisible to the SFOS development environment, and hence causes lots of things to go havoc (for example multiprocessing module of python, which internally relies on system-V semaphores).<br />
<br />
And unfortunately, there is more glibc features which rely on many private counterparts of public api's. Up to the point where common POSIX libraries become non-functional under scratchbox2 (we already mentioned these - systemV semaphores anyone?) on some targets (i486, for instance), or exec's, which also fall into the set of functions utilized internally by glibc via a private api. Exec's are for example used by the posix_spawn api's, which in turn - you know where this is going - are used (if the spawn.h header is detected, and is the case as MER ships it) by llvm.<br />
<br />
Nevertheless, with these issues out of the way, you should be able to reliably compile the llvm. So now to the funny part, the compilation. Did I mention MER has an ancient glibc? (e)glibc 2.19 , as used (at the time of writing) by MER, lacks certain floating point operations (sse3 & more recent), which llvm relies on. Though these are not critical per se, they might turn up iffy warnings during compilation (if not bugs at runtime), hence relative build.rs files which include them in the compilation need to be patched to exclude them.<br />
<br />
Once done so, you should have a clean LLVM implementation running on SFOS. Enjoy!</div>
Tone Kastlungerhttp://www.blogger.com/profile/03560854879582481991noreply@blogger.com1tag:blogger.com,1999:blog-8300911467973705649.post-27667048678348087922017-11-12T13:39:00.003-08:002017-11-12T13:39:27.072-08:00Of Mountains, Tablets, and fishes - A story of porting SFOS to Teclast x89 tablet<div dir="ltr" style="text-align: left;" trbidi="on">
In Raethoromanian(Ladin)/Dolomites mythology, mountains have always played a big role.<br />
<br />
A legend tells the story of a girl from the (Dolomites) mountains, accidently noticed by a Prince hunting in the area, and of the two subsequently falling deeply in love with each other. <br />
Soon realizing the fact, and realizing her son is reluctant to back out of the relationship, the Queen forces him to move the girl into their home, the castle of the Realm, so that they could get properly married, and live together.<br />
It so happens that the people from the castle did not approve of the relationship, and foremost did not accept the girl, even before her entrance to the castle; they envy her, hate her, and shame her on her first public appearance, at which, out of shame and shyness, she turns into a small mountain furret (montagnóla). <br />
The guests appear shocked, and consider killing the animal, but suddently the unexpected : a fire-like halo shines in strongly from the windows. <br />
The guests, scared by the unusual event, curiously glare outside, wondering if the town is on fire; only to notice a once-gray mountain turned glooming fire-red! The ground creepily starts shaking, the castle slowly collapsing on itself, into the ground. The girl and Prince barely escape to safety; they are destined to become King and Queen of what is the biggest Ladin myth of the Dolomites, the Reign of the Fanís.<br />
The mountain has been fire-red ever since, as of to reminding humans to their humbleness, and can be admired even today, in the Dolomites area of Sennes.<br />
<br />
What does this have to do with tablets, and more to with fishes?<br />
Quite few, if nothing at all, of course!<br />
Or, perhaps the effort required to seize the top of a mountain, is comparable to the amount of work required to port SF OS to a new tablet HW?<br />
<br />
In the spirit of "if the mountain does not come to I, I will go to the mountain" (see, mountains again!); if Jolla did not (manage to) make a tablet for me, well I'll be damned if I can't make one for me. It's a challenge to myself.<br />
<br />
This series of posts are supposed to give an insight in the deep works of kernel porting, modules compiling, booting, involved when porting SFOS to new Hardware. I hope people will find it inspiring, and start experimenting on their own. Sailfish is a great OS, and most of all, a great idea (even tho still lacking in terms of full freedom). This, coupled with the amount of things I will (need to) learn on the way to it, is reason enough for me to try. And most importantly, I want to have FUN doing it.<br />
<br />
The chosen hardware for this effort, is the <a href="http://www.gearbest.com/tablet-pcs/pp_349613.html">Teclast x89</a>, featuring a cheap Intel Bay Bridge SoC, 2 GB of RAM, 32 GB of flash, sd-card slot, dual boot Android / Windows 10 out of the box, and (luckily) unlocked bootload. <br />
All in all, a decent Hardware replacement for the official Jolla tablet.<br />
<br />
But first, some considerations:<br />
DISCLAIMER : ANY OUTCOME OF THESE ACTIONS ARE THE RESULT OF YOUR OWN RESPONSIBILITY; I AM NOT RESPONSIBLE FOR DAMAGED HARDWARE / SERVICES / EQUIPMENTS. This is advanced hard work; if you are not ready to risk your hardware, or do not have a ginuea-pig hw, DO NOT START.<br />
<br />Still interested? Stay tuned for the next posts!</div>
Tone Kastlungerhttp://www.blogger.com/profile/03560854879582481991noreply@blogger.com0tag:blogger.com,1999:blog-8300911467973705649.post-38178910273244014712016-06-23T12:47:00.002-07:002016-06-23T12:47:51.063-07:00Virtualbox and Win7 issues<div dir="ltr" style="text-align: left;" trbidi="on">
If VirtualBox does not start on Win7;<br />
uninstall it, install it without USB emulation (add it afterwards).</div>
Tone Kastlungerhttp://www.blogger.com/profile/03560854879582481991noreply@blogger.com0tag:blogger.com,1999:blog-8300911467973705649.post-43032538520072793752015-09-19T05:02:00.003-07:002015-09-19T05:07:00.142-07:00XDG VS SailfishOS<div dir="ltr" style="text-align: left;" trbidi="on">
During development of Quickbar, I happened to stumble upon a small issue related to XDG and mime types. This same issue has been raised over at <a href="https://together.jolla.com/question/110408/xdg-open-no-longer-working/">tjc forums</a> lately, so I got inspired and restarted digging.<br />
<br />
The problem : lookup of mime types seem to fail relentlessy; opening files with xdg-open as of now (release 1.1.9.28) opens Documents application, no matter which file is actually opened. "So what", you might ask, "where's the problem, apps on SailfishOS rely on QT. We can open anything we want with QDesktopServices::openUrl". Unfortunately, qt internally (and QDesktopServices::openUrl more specifically) relies on xdg-open. So to investigate this, I followed the xdg-mime trace given in the comments of the tjc post. <br />
<br />
On SailfishOS xdg tools refer to mimeapps.list for storing mime type associations; xdg scripts come from the package xdg-utils (in case of mer 1.1.0-rc3, keep in mind this version number cause it's the cause of all evil). This is a weird part, but everything is still correct here; this was quite misleading for a long time, as I believed the problem to be mimeapps.list being used as DEFAULT even outside KDE envs; that held until I stumbled on <a href="http://lists.freedesktop.org/archives/xdg/2014-February/013183.html">this post</a> in the freedesktop mailing list, which claims that defaults.list has been declared deprecated and superseded by mimeapps.list. In fact, <a href="ttp://standards.freedesktop.org/mime-apps-spec/mime-apps-spec-1.0.1.html">the specification</a> does not happen mention defaults.list at all anymore. The same issue is raised in different environments as well, for example on <a href="https://github.com/lxde/libqtxdg/issues/7">this post of the lxde group</a><br />
From the same LXDE group post, it seems
the latest and greatest (yet unreleased) version of xdg on the master contains a
fix for this. issue.</div>
Tone Kastlungerhttp://www.blogger.com/profile/03560854879582481991noreply@blogger.com0tag:blogger.com,1999:blog-8300911467973705649.post-89214352668648822352015-08-29T14:17:00.002-07:002015-08-29T14:23:54.353-07:00The 4 rules of coding - or, of coding-applied strategic thinking.<div dir="ltr" style="text-align: left;" trbidi="on">
Coding is not an easy job. From the perspective of the programmer, Coding is a war. I'll tell you why.<br />
You need to do it right; which means; you need to do it clean; you need to do it FAST; and you - potentially, well, pretty much all the time - absolutely NEED to get it right the first time. There is no second chance. You have time to think on how to do it, sure, perhaps weeks, months, YEARS; but you will get that time only ONCE.<br />
<br />
One shot. Perfection.<br />
<br />
It's not an easy life being a coder. If you like to write; if you like to think; if you like to plan; you are not good enough. You need to like to write AND to think AND to plan. You need a STRATEGY.<br />
<br />
Remember, practice makes the master. FOUR simple "riddles" govern the practice of coding, each of them require solving for the specific problem they are being applied on. The four riddles of coding, for properly solving a given problem, are for you find out:<br />
<ol style="text-align: left;">
<li>WHAT needs to be done</li>
<li>HOW to achieve that (functionality-wise)</li>
<li>WHY it needs to be done like this (in a structural context)</li>
<li>HOW IT CAN BE USED </li>
</ol>
Point 1. Is pretty straightforward, and stems off from the requirements.<br />
Point 2. is purely logic; and means collecting the idea of how to do things (i.e. opening files, writing to them vs opening pipes and/or writing to a REST Api etcetcetc). This is the threshold of AVERAGE programmers. They will write average code. This is just a fact. It is not BAD code per se; as it will do what it is meant to do. Only; people working with that code will make the coder's ear ring with F*U's for the rest of his life.<br />
Point 3. Adds perspective in the mix. You might say, "of course I know WHY it needs to be done like this; to fulfill the requirements". That's only half the coin, man! This WHY is waay more subtle and entwingled into the deeper meaning / structure and is meant to get you to think of the solution you are applying (to the problem given by the requirements) in a broader spectrum; or, how more "advanced" programmers like to put it, in terms of "architecture", and in a wholistic view. In short, this point opens up for future usability of your code (funcionality-wise). Things like code structure, Functionality-grouping, application of patterns fall into this area. You can discern Good coders from the rest by the fact that they make use of these tools or not.<br />
Point 4. is the hardest one, and usually only Great coders make it all the way up to this point. This is strategy to it's finest. Point 3 at the n'th potential. Code that is written needs to be USED. Needs to be relied on. If code cannot be used, it is useless, rusty, unreliable. If your code is not "level 4" code, it won't survive a new generation of programmers in your team. "The old code is shit, let's rewrite it", they will say. NIH sindrome.<br />
<br /></div>
Tone Kastlungerhttp://www.blogger.com/profile/03560854879582481991noreply@blogger.com0tag:blogger.com,1999:blog-8300911467973705649.post-77824102708780871762015-03-12T13:53:00.003-07:002015-03-12T13:56:42.200-07:00Raspberry Pi 2 rocks! mount.cifs not so much..<div dir="ltr" style="text-align: left;" trbidi="on">
I got this new toy yesterday and i L-O-V-E it!<br />
<br />
One problem tho.<br />
I also have a B+ model, which I used to run owncloud server (plus other sensors servers).<br />
Having collected a decent ammount of data from my sensor network already, I wanted to keep it.<br />
So i upgraded from RPi B+ to RPi2 following instructions on the RPi website.<br />
This went fine & smooth, altho the owncloud server could not anymore connect to the backend NAS (which is used to store all the data).<br />
Symptom of the failure was error -13 upon mounting. Which I figured should translate "in password being wrong" (at least in my case). A few tries with different users (defined on the NAS) didnt give expected results, until I realized to check the version of cifs. Which on the RPi2 is 5.5, and on the nas is 5.1.<br />
Well, it appears the reason for it is that the default security mode of cifs has changed. It used to be ntlm, but it is not anymore - although in the documentation it clearly states it: <br />
<blockquote class="tr_bq">
· ntlm Use NTLM password hashing (default)</blockquote>
The above is what comes out of the mount.cifs man page.<br />
Forcing the sec to ntlm in the samba options of the mount solves the issue.</div>
Tone Kastlungerhttp://www.blogger.com/profile/03560854879582481991noreply@blogger.com0tag:blogger.com,1999:blog-8300911467973705649.post-28556320929676111652015-02-27T13:00:00.001-08:002015-02-27T13:00:59.870-08:00Postmortem : So long, Nokia Store (ex Ovi)!<div dir="ltr" style="text-align: left;" trbidi="on">
-Today, Leonard Nimoy died. He undoubtfully represented and played one of the most intriguing characters of Show business history.<br />
<br /><br />Today, after a nice sauna and realxation, I remembered that something else was supposed to die - the Nokia store. I recalled some email sent from Microsoft stating everything would have been shutted down by end of February 2015. Puzzled if it already happend, I grabbed my laptop and quickly checked store.nokia.com. It seemed to still be there. Nokia Store. The place of shattered dreams. Once the biggest online app store by far, with download stats even Apple could have only dreamt of. Nowadays a sad, forgotten place full of outdated software. I recall my software I placed up there. Of course, as everything, I am always late - and as such, I started at the end of Nokia - time i.e. when the N9 was released. The iPhone-killer. The beast that would have reneved Nokia. Well, we all know how well that went.<br />
At that time, with a steady job, and wanting to focus more on Linux, I bought the only barebone-linux phone available at the time, namely the N9. I wanted to start developing for it, I wanted to experiment, learn, investigate possibilities, have an adventure! And where else if not on Nokia (at that time still) Ovi Store? So I grabbed some extra money and funded myself for a shiny new Cyan N9 16 GB (yes back then it was all I could afford). I must admit, thinking about it, even today, I miss the slickness and the particular color and shape. It fitted perfectly in the pocket. But lets not disgress.<br />
On the day the phone was made available, I was at Verkkokauppa, Helsinki, to pick it up, excited about this new adventure. I recall one of the store minions holding a bunch of them in his hand, portraiing an annoied look on his face like for saying : just please get these things out of my hands.<br />
Well, turned out I did the right thing to show up @ Verkkokauppa, cause the Cyam phones got sold out in about a few weeks. The real reason for this was of course shortage of production (which by then had already been stopped by Nokia), but what would I have known back then?<br />
I went back to my work place, and straight away placed the phone on, and started to discover it.<br />
Finding the tools seemed to require a little bit of digging already back then, but from Nokia main page you would be able to gather all the necessary assets. After setting up everyting (not with a few painful mistakes at first), I was ready to go.<br />
<br />
My first App was BWizz, an application which basically could be used to edit and import / export bookmarks between the different browsers available for the phone. It was my first Qt App, and as such, a fresh start, especially with qml; but becoming aquainted to it did not take long. Soon enough I was coding plugins for image ressources and UI interfaces like a pro. Qml is that easy, really.<br />
So I got BWizz up to shape for publishing. I knew Nokia had QA process in place; and as I had previous experience with QA processes from my workplace, I knew it would take some time. I did not have many hopes to be able to pass it; but after a few weeks of rejection, eventually I managed to get BWizz published. The pricepoint was #1 (=1 €). "So", i thought, "this is done!" - and went off for a celebration beer. On the first day, BWizz made 20 downloads. I got about 5 emails with questions, and two with more feature requests. In order to try to improve downloads, a free version followed.<br />
Eventually, the total would have added up to 2000 BWizzFree downloads, and about 151 paid BWizz apps. So, 151 €? Hell no! Keep in mind out of revenue made for selling the apps, you need to deduct operator and service provider (aka Nokia) fees. For each BWizz sold, then, 0.7 € would land in my pocket. Peanuts, really.<br />
<br />
<br /></div>
Tone Kastlungerhttp://www.blogger.com/profile/03560854879582481991noreply@blogger.com0tag:blogger.com,1999:blog-8300911467973705649.post-43700403186881321952015-01-12T12:14:00.004-08:002015-01-12T13:09:16.161-08:00Find the Fun in "How difficult can debugging mem leaks on mobile be?"; Or : an afternoon spent with Valgrind!<div dir="ltr" style="text-align: left;" trbidi="on">
So!<br />
<br />
QuickBar on SailfishOS has come a decent way, I would say. We've got :<br />
* full apps support (both android and native);<br />
* device-lock screen support;<br />
* Swipe-launch<br />
* on-lockscreen presence<br />
* favourites.<br />
<br />
And we have more to come:<br />
* autostart<br />
* integration with event screen<br />
* ... <br />
<br />
All in all, a nice (still little) stash of features!<br />
Recently I have been wondering; given SailfishOS's problem with memory management, how does Quickbar's memory footprint affect the overall performance of the system? The application is omnipresent once launced, and farily easily interacted with. Consequently, a memory leak might threaten stability of the system quite severly if left to run on it's own unnoticed.<br />
Given this thought, I decided to focus on memory consumption next. So, I went off into this investigation by first figuring out the overall size of the memory footprint of QuickBar. There is this utility, <b>pmap</b>, which perfectly fits this purpose. So, devel-su/pkcon install pmap, pmap -x <pid of="" quickbar="">.Upon the first result, I jumped on my chair : Quickbar used a whole whopping 130 MB!! </pid><br />
<br />
Subsequent measures re-confirmed this number. So somewhere memory is either leaking very badly, or ressource usage is not optimized at all. This needed to be investigated more in detail, which led to the hunt for more to this purpouse suitable tools.<br />
The search lead me to <a href="http://valgrind.org/docs/manual/mc-manual.html">Valgrind</a>, open-source tool with excellent run-time analysis toolkit. I fired up a putty term, devel-su / pkcon install valgrind, crossed my fingers, and to my surprise the tool is present in Mer, so it got installed and I was ready to go. First thing to do, was to gain more knowledge on the command line. For my specific purpouses (memory leakage), I came up with the following minimalistic command line:<br />
<br />
--workaround-gcc296-bugs=yes Ignore a Known compiler issue<br />
--show-leak-kinds=all Display all kinds of leaks<br />
--log-file=/tmp/output-valgrind.txt Logfile location<br />
--leak-check=full Check for all possible memory leaks<br />
--tool=memcheck Toolkit for memory check<br />
<br />
As a test round, I built a standard Sailfish app in default configuration (meaning debug mode, no optimizations, QML debugging on), deployed it (and the relative debug symbols) to the device. pmap for this empty app gives a default memory footprint of 127MB (which relaxed my nerves a bit). So then next was the run it in Valgrid (BTW, All the type of analysis provided in the trace log are explained down to the detail in the <a href="http://valgrind.org/docs/manual/valgrind_manual.pdf">Valgrind manual</a> - brace for long read).<br />
<br />
Running the commandline above against my emptyapp test application, gave me a typical recap for the result of the analysis in question (given the due time spent waiting due to the performance impact): <br />
<blockquote class="tr_bq">
==8455== Memcheck, a memory error detector<br />
==8455== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.<br />
==8455== Using Valgrind-3.9.0 and LibVEX; rerun with -h for copyright info<br />
==8455== Command: emptyapp<br />
==8455== Parent PID: 8454<br />
......<br />
==8455== LEAK SUMMARY:<br />
==8455== definitely lost: 409 bytes in 31 blocks<br />
==8455== indirectly lost: 46,302 bytes in 500 blocks<br />
==8455== possibly lost: 173,058 bytes in 1,344 blocks<br />
==8455== still reachable: 1,384,442 bytes in 16,850 blocks<br />
==8455== suppressed: 0 bytes in 0 blocks<br />
==8455== <br />
==8455== For counts of detected and suppressed errors, rerun with: -v<br />
==8455== Use --track-origins=yes to see where uninitialised values come from<br />
==8455== ERROR SUMMARY: 3717 errors from 35 contexts (suppressed: 0 from 0)</blockquote>
Notice how Valgrind gives you the option to (tentatively) track origins of memory leaks (not used in this case). Entries in the tracelog file are for example:<br />
<br />
<blockquote class="tr_bq">
<span style="font-size: x-small;">==8455== Invalid read of size 4</span><br />
<span style="font-size: x-small;">==8455== at 0x401A8BC: ??? (in /lib/ld-2.15.so)</span><br />
<span style="font-size: x-small;">==8455== Address 0x78c52dc is 52 bytes inside a block of size 54 alloc'd</span><br />
<span style="font-size: x-small;">==8455== at 0x4838CBC: malloc (vg_replace_malloc.c:291)</span><br />
<span style="font-size: x-small;">==8455== by 0x4008B0F: ??? (in /lib/ld-2.15.so)</span><br />
<span style="font-size: x-small;">==8455== </span><br />
<span style="font-size: x-small;">==8455== Syscall param sendmsg(msg.msg_iov[0]) points to uninitialised byte(s)</span><br />
<span style="font-size: x-small;">==8455== at 0x554D544: sendmsg (in /lib/libpthread-2.15.so)</span><br />
<span style="font-size: x-small;">==8455== Address 0x78c9dde is 4,158 bytes inside a block of size 16,424 alloc'd</span><br />
<span style="font-size: x-small;">==8455== at 0x4838CBC: malloc (vg_replace_malloc.c:291)</span><br />
<span style="font-size: x-small;">==8455== by 0x7F29E53: ??? (in /usr/lib/libwayland-client.so.0.1.0)</span><br />
<span style="font-size: x-small;">==8455== </span><br />
<span style="font-size: x-small;">==8455== Conditional jump or move depends on uninitialised value(s)</span><br />
<span style="font-size: x-small;">==8455== at 0x7CA7988: mmap (in /system/lib/libc.so)</span><br />
<span style="font-size: x-small;">==8455== </span><br />
<span style="font-size: x-small;">==8455== Syscall param mmap2(length) contains uninitialised byte(s)</span><br />
<span style="font-size: x-small;">==8455== at 0x7C9AAD8: __mmap2 (in /system/lib/libc.so)</span><br />
<span style="font-size: x-small;">==8455== </span><br />
<span style="font-size: x-small;">==8455== Syscall param mmap2(offset) contains uninitialised byte(s)</span><br />
<span style="font-size: x-small;">==8455== at 0x7C9AAD8: __mmap2 (in /system/lib/libc.so)</span><br />
<span style="font-size: x-small;">==8455== </span><br />
<span style="font-size: x-small;">==8455== 20 bytes in 1 blocks are still reachable in loss record 138 of 538</span><br />
<span style="font-size: x-small;">==8455== at 0x4837D5C: operator new[](unsigned int) (vg_replace_malloc.c:378)</span><br />
<span style="font-size: x-small;">==8455== by 0x7E2F131: std::_Locale_impl::make_classic_locale() (in /system/lib/libstlport.so)</span><br />
<span style="font-size: x-small;">==8455== </span></blockquote>
<blockquote>
<span style="font-size: x-small;">....<br />==8455== 20 bytes in 1 blocks are still reachable in loss record 139 of 538<br />==8455== at 0x4837D5C: operator new[](unsigned int) (vg_replace_malloc.c:378)<br />==8455== by 0x7E2F141: std::_Locale_impl::make_classic_locale() (in /system/lib/libstlport.so)<br />==8455==</span><br />
<span style="font-size: x-small;">.....</span><br />
<span style="font-size: x-small;">==8455== 2,560 bytes in 2 blocks are possibly lost in loss record 468 of 538<br />==8455== at 0x4837D5C: operator new[](unsigned int) (vg_replace_malloc.c:378)<br />==8455== by 0x7E3B4A5: std::__node_alloc_impl::_S_chunk_alloc(unsigned int, int&) (in /system/lib/libstlport.so)</span><br />
<span style="font-size: x-small;">...... </span><br />
<span style="font-size: x-small;">==8455== 46,430 (128 direct, 46,302 indirect) bytes in 1 blocks are definitely lost in loss record 533 of 538</span><br />
<span style="font-size: x-small;">==8455== at 0x48365A8: calloc (vg_replace_malloc.c:618)<br />==8455== by 0x7F01437: xkb_state_new (in /usr/lib/libxkbcommon.so.0.0.0)<br />==8455== <br />==8455== 59,204 bytes in 1,092 blocks are possibly lost in loss record 534 of 538<br />==8455== at 0x4838CBC: malloc (vg_replace_malloc.c:291)<br />==8455== by 0x51E69D7: QArrayData::allocate(unsigned int, unsigned int, unsigned int, QFlags<qarraydata::allocationoption>) (in /usr/lib/libQt5Core.so.5.2.2)<br />==8455== </qarraydata::allocationoption></span></blockquote>
<br />
We have uninitialized values on conditional jumps and syscalls(not much we can do about these) ;<br />
the "still reachable" data's are - in a very simplified view - mostly pointers not nullified (i.e. pointing to void) or pointing to non-standard locations (cookies before the memory array, some compilers use them to store information like the length of the memory array etc).<br />
The ones you want to keep an eye upon are the "possibly lost" and "definitely lost" ones, which pin-point possible and almost certain memory leaks respectively.<br />
<br />
The memory foot print of the same empty app in Release mode (obtained via pmap ) returned a memory footprint of also 127 MBytes.<br />
<br />
So, the question arised - if the footprint of a bare-bone Qt app is about 127 MBytes, how much is one without Qt? I headed back to my QtCreator, and built a non-qt c project (containing the default "Hello world" plus a sleep for 10 minutes); then deployed it to the phone, and ran a pmap check on it. The result on the first run (with no modifications to the project) was staggering : 87 MBytes!<br />
Looking at the output of pmap, I discovered the one to blame, namely libQtCore, which was loaded as well. I decided to google around, and stumbled on <a href="http://stackoverflow.com/questions/2296514/bulding-with-qmake-on-linux-how-to-prevent-qmake-from-linking-to-qtcore-and-qt">this post</a>, which seemed to hind to the fact that QtCreator automatically linked QtCore and QtGui even in non-qt projects unless told not to do so (in my case via a QT -= core gui in the .pro file).<br />
So I went back, and added the line above to the project file, recompiled and copied over to the device, and re-run. The result was a significantly reduced memory foot print, which was between 2 and 3 megabytes.<br />
<br />
<br />
</div>
Tone Kastlungerhttp://www.blogger.com/profile/03560854879582481991noreply@blogger.com0tag:blogger.com,1999:blog-8300911467973705649.post-40834920683396748322014-06-14T12:38:00.002-07:002014-06-14T12:40:56.621-07:00A small teaser - Quickbar on Sailfish!<div dir="ltr" style="text-align: left;" trbidi="on">
This is a side project we have been working on lately @ GiuliettaSW.<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj66uCLUXyN8quwa-UrCIA2duCBL95bYYORPIlsh91GcPXHKGfWTlLvA5wPj7l1rzPAGqznvf-yUxcVOrJAjjw-b-8oXc2iG56ybeS-lVsHffOn_wNMK6sqlwMpeswv1QY53Qha938rjng/s1600/20140614213004.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj66uCLUXyN8quwa-UrCIA2duCBL95bYYORPIlsh91GcPXHKGfWTlLvA5wPj7l1rzPAGqznvf-yUxcVOrJAjjw-b-8oXc2iG56ybeS-lVsHffOn_wNMK6sqlwMpeswv1QY53Qha938rjng/s1600/20140614213004.png" height="320" width="180" /></a></div>
<br />
Developing this was not easy, and it is a very early (and buggy!) version.<br />
This version is functionally similar to the N9 in that it provides access to the last used apps.<br />
Of course, as Sailfish OS has no Stauts bar per se, for now it is on display on the lock screen only.<br />
<br />
We hope to be able to push it on Harbour in the next month, so keep your eyes open! :)</div>
Tone Kastlungerhttp://www.blogger.com/profile/03560854879582481991noreply@blogger.com0tag:blogger.com,1999:blog-8300911467973705649.post-56974974423110815692013-12-30T11:37:00.001-08:002013-12-30T11:37:50.117-08:00Quick update on the N9 vs Jolla sync<div dir="ltr" style="text-align: left;" trbidi="on">
A step was missing; thanks to Christopher Lamb for pointing it out.</div>
Tone Kastlungerhttp://www.blogger.com/profile/03560854879582481991noreply@blogger.com0tag:blogger.com,1999:blog-8300911467973705649.post-74668019093180562932013-12-18T13:12:00.001-08:002013-12-18T13:12:23.203-08:00SailfishOS vs Self-signed Exchange server certificates<div dir="ltr" style="text-align: left;" trbidi="on">
In case you self-signed your Exchange certificate, or are trying to access a server which has a self-signed certificate from your Jolla, make sure to download the certificate and copy it over to the phone. For this you will need to enable developer mode, and scp or WinSCP (if you navigate Windows waters).<br />
<ol style="text-align: left;">
<li>"Export" (download) the certificate from the website you are trying to access in PEM or CRT format</li>
<li>enable developer mode on your Jolla</li>
<li>copy the downloaded file to /etc/ssl/certs</li>
<li>reboot </li>
</ol>
</div>
Tone Kastlungerhttp://www.blogger.com/profile/03560854879582481991noreply@blogger.com0tag:blogger.com,1999:blog-8300911467973705649.post-45226343127207101622013-11-28T12:16:00.000-08:002013-11-29T09:49:04.075-08:00Sailfish OS : dev mode of Other half / Jolla & Win 7 <div dir="ltr" style="text-align: left;" trbidi="on">
Developer mode under Windows 7 might not work as expected.<br />
Reason for it seems to be Win7 host ip configuration to be not usable.<br />
Fix for this is easy.<br />
First, configure developer mode on the jPhone:<br />
1) enable dev mode<br />
2) set password<br />
3) optional: set ip address for usb connectivity<br />
<br />
Then configure Win7 host: <br />
1) connect your jPhone with usb to the Win7<br />
2) from the pc, open network & sharing center<br />
3) select "Change adapter settings"<br />
4) open the adapter labeled with "Remote NDIS based Internet sharing device"<br />
5) go to properties<br />
6) select entry for IP V4<br />
7) enter a static ip (in the same subnet of the phone). So if your phone has 192.168.2.15 (default), you can put 192.168.2.10 for example<br />
8) set phone ip address as gateway & dns entries as well.</div>
Tone Kastlungerhttp://www.blogger.com/profile/03560854879582481991noreply@blogger.com0tag:blogger.com,1999:blog-8300911467973705649.post-90076380675353046612013-11-27T22:29:00.000-08:002013-12-30T11:34:33.652-08:00Sailfish OS vs N9 sync<div dir="ltr" style="text-align: left;" trbidi="on">
So finally!<br />
Sailfish OS in hand, happy me!<br />
But! How to sync all data from n9?<br />
Easy, four steps:<br />
1) connect both phones via bluetooth<br />
2) from n9, once devices are paired, go to "Settings" -> "Sync and backup" <br />3) select sync<br />
From here you can select your Jolla phone, and by clicking on it you can define what to sync. <br />
4) configure sync <br />
<br />
<br /></div>
Tone Kastlungerhttp://www.blogger.com/profile/03560854879582481991noreply@blogger.com5tag:blogger.com,1999:blog-8300911467973705649.post-51426911957594993062013-11-02T10:49:00.002-07:002013-11-02T10:49:52.672-07:00Sailfish development : application templates missing<div dir="ltr" style="text-align: left;" trbidi="on">
It so happened that upgrading to the latest Sailfish Alpha release broke my QtCreator templates.<br />
Symptom of this manifested in missing project templates for Sailfish applications. Exactly the same issue that is mentioned <a href="http://askubuntu.com/questions/259719/qt-quick-ui-templates-missing-from-qt-creators-new-file-or-project-dialog">here</a> . Luckily, removing ~/SailfishOSAlpha2 directory fixed the problem.</div>
Tone Kastlungerhttp://www.blogger.com/profile/03560854879582481991noreply@blogger.com0tag:blogger.com,1999:blog-8300911467973705649.post-12757363970492808602013-07-21T11:26:00.000-07:002013-07-21T11:29:34.967-07:00SailfishOS under Win7 and user's home restriction<div dir="ltr" style="text-align: left;" trbidi="on">
<div>
So I have been hanging out in Jolla's waters lately.<br />
SailfishOS comes packaged with two virtual machnes (running under Virtual Box);<br />
one for the building tools<br />
one for the emulator<br />
<br />
<br />
Problem is by default the building tools vm requires projects to be placed under the user's home directory. Under Win7, that directory is C:\users\<username><username>;</username><br />
in this folder, the installer will generate a .scratchbox2 folder, which configures (as the name says) sb2. This location is shared to the Virtual machine via VB's shared folders.<br />
These can be relocated (whilst the machine is powered off) from the VM's configuration.<br />
<br />
<ol style="text-align: left;">
<li>Start Oracle Virtual Box</li>
<li>Make sure MerSDK VM is powered off </li>
<li>Open Settings page for MerSDK</li>
<li>Select the "Shared folders" on the right</li>
<li>Change the location of the "home" share to your wanted folder</li>
<li>The new share will automatically be named as the same folder you just chose in step 5, rename it to "home" </li>
</ol>
</div>
Now you would think this to be enough; but whilst the machine will run fine in this setup, <b>all your sb2 targets will be gone</b>. Luckily copying the .scratchbox2 subfolder found in the original location (C:\users\<username><username>) to the new one fixes this issue.</username><br />
<div>
<br />
So full steam ahead, yer scummy sea guls! No more excuses to soak the deck with your lazy ass'es swet anymore! Arr!</div>
</div>
Tone Kastlungerhttp://www.blogger.com/profile/03560854879582481991noreply@blogger.com0tag:blogger.com,1999:blog-8300911467973705649.post-22442042219269896272013-05-24T09:16:00.000-07:002013-05-24T09:16:09.645-07:00Planet MeeGo, Day #2 : THe lost bricks, or : if you go back now, you really are a n00b!<div dir="ltr" style="text-align: left;" trbidi="on">
So!<br />
We've landed on planet meego (intentionally or not, it is still unclear to me, but whatever).<br />
We've understood there is more than QML on N9 : N9's soul is composed by MeeGo.<br />
What is MeeGo? Or, wait, let me refrase : what <b>was </b>MeeGo?<br />
MeeGo was meant to be the leading platform in mobile linux.<br />
Born out of the two gods of linux Maemo and Moblin, the chimera MeeGo lasted, well, some laptops (funnily, my sister managed to get one by accident), and one mobile phone.<br />
Reasons for this early death (Cripple Death Syndrome?) have been discussed and overdiscussed in other threads on other forums, and are not the center of the discussion here.<br />
The center of the discussion is MeeGo, and more specifically developing under MeeGo.<br />
So, how do you develope an application under MeeGo? You google : MeeGo Application, and <a href="http://developer.meego.com/guides/create-your-first-qml-application">this</a> comes up. Too bad it's not MeeGo, it's QtQuick.<br />
Let's try again: google meego application example"; <a href="http://www.youtube.com/watch?v=1BpNzUltCgA">QML/QtQuick</a> again!<br />
"Wtf? Where is my MeeGo?". <br />
<br />
Right behind an obscure google term : <a href="http://wiki.meego.com/MeeGo_Touch_Framework">meegotouch</a> (third hit in Google, I mentioned even Google rules do not apply to MeeGo searches). <b>Btw, according to some rumors, all the links should be removed by end of May by the Linux Foundation</b>. This is not confirmed yet, so be not surprised if the links point to void. Just a heads up. In case it is going to happen, you should still be able to navigate the sites through the wayback machine (or some other mirror). Also, most likely many of the information in here might apply to SailfishOS as well, Jolla's upcoming MeeGo-based OS.<br />
<br />
So anyway, we found our MeeGo! Wooho!<br />
Building a MeeGo application seems easy. And it is, as can be seen from <a href="http://harmattan-dev.nokia.com/docs/platform-api-reference/xml/daily-docs/libmeegotouch/tutorial.html">here</a>.<br />
According to <a href="http://harmattan-dev.nokia.com/docs/library/html/guide/html/Developer_Library_Alternative_development_environments_Platform_SDK_user_guide_Using_Harmattan_Platform_SDK.html">Nokia Docs</a>, a linux is preferred in order to build MeeGo apps.<br />
I have been working with both WinXP and Win7 without many problems (well, maybe in WinXP some problems, but not under Win7 anymore). Yes, it is a bit more challenging, and yes, it is not as straightforward; and yes, if you are an absolute Free SW type of guy, and Wind0wz horrifies you, there is no reason to use anything else except linux (the only reason I am stuck on Wind0wz is due to lack of capacity to run a virtual machine with satisfying results). But this is not the point of the discussion now anyway.<br />
Also, according to the above-mentioned docs, the MeeGo is referred by Nokias as part of the Platform SDK. But to me it seems more like meego *is* the PlatformSDK.<br />
<br />
I think the most useful concept is the strictly Model-View-Controller architecture pattern of MeeGo.<br />
As well as iOS (and probably Windows Phone), MeeGo separates the three in a very strict manner. This of course has positive and negative aspects. For example, if you do not know what MVC is, you will face a very hard time trying to figure out how to do things on your own.<br />
Let's take the <a href="http://harmattan-dev.nokia.com/docs/platform-api-reference/xml/daily-docs/libmeegotouch/styling.html">styling features</a> as an example.<br />
Did you know you can auto-generate styling components out of a simple interface (declared appropriately)? It is indeed, very easy. Two things are required:<br />
<ol style="text-align: left;">
<li>A (style) class declaration </li>
<li>QtCreator declarations in .pro file to configure the helper tools to generate class stubs for the declared (style) class</li>
</ol>
Instructions on how to follow up on this can be found <a href="http://harmattan-dev.nokia.com/docs/platform-api-reference/xml/daily-docs/libmeegotouch/styling_in_code.html">here</a>.<br />
<br />
Once the qmake is properly configured, and the files are properly included in your app, the MeeGo Application will autostyle itself, by looking up the stylesheets in predefined (Theme-based) paths.<br />
This not only perfectly separates the look-and-feel from your C++ code; it also simplyfies your life as a programmer alot. Of course, this is deprecated technology, so it opens up doors to all kinds of weird (sometimes buggy) behaviours as well, but hey, it works, and so far I always found a work-around for some of the issues no problem.<br />
<br />
But why MeeGo? Is this all it has to offer over, say, Qt and/or QML? Is it worth the catch?<br />
<br />
Well, N9-technically speaking, yes. From a practical point of view, MeeGo tried to fuse the positive aspects of both worlds and combine them to a powerfull toolkit.<br />
MeeGo escapes the clumsyness of QML (and well over its limits in many aspects, speed being the first one) and frees the programmer from the burden of managing alof of necessary UI-related functionalities, as well as giving a much better degree of flexibility and lean-ness, by providing out-of-the-box tools (like the styling, for instance) that Qt is missing.<br />
<br />
Of course, there is also the fact that MeeGo is a dead platform (except for SailFishOS, but the extent of the compatibility with it is still to be confirmed IMHO. QML was supposed to be cross-platform, but as we have seen, on BB10 this is not the case (QtQuick vs Cascades)).<br />
<br /></div>
Tone Kastlungerhttp://www.blogger.com/profile/03560854879582481991noreply@blogger.com0tag:blogger.com,1999:blog-8300911467973705649.post-86657485600127726432013-04-08T13:44:00.002-07:002013-04-08T13:48:47.345-07:00Planet MeeGo day #1 - The Dark side of N9, or : trust your instinct, n00b!<div dir="ltr" style="text-align: left;" trbidi="on">
So!<br />
I have been tricking around with N9 for a while now.<br />
I must say.<br />
This is a great Phone (if we consider it should have come out back in 2010/11)!<br />
This could have been a great OS!<br />
<br />
So I have developed so far two applications, <a href="http://store.ovi.com/content/340640">LINKer</a>, and <a href="http://store.ovi.com/content/304258">BWizz</a> (both are available in free and paid versions from OVI/Nokia store, btw).<br />
In chronological order, they manifested as : <br />
<ol style="text-align: left;">
<li><a href="http://store.ovi.com/content/304258">BWizz</a>, a bookmark editor.</li>
<li><a href="http://store.ovi.com/content/340640">LINKer</a>, an utility which gives you access to any file on your Phone, directly from your home screen (which originally only allows for Apps / Applets / URL bookmarks).</li>
</ol>
Whilst the first one is a "normal" QML-based application, the second one goes a step further, and dives a bit more into the wreck of MeeGo, specifically in the Share-ui capabilities of the OS (which I personally like as a concept, but is nothing new, as Android and now BB10 has as well).<br />
<br />
Somehow, all this time I had been working with MeeGo, it felt as if I was working with a huge woolen ball;<br />
twisted, complex, confused. The main reason for this feeling is most likely due to the fact that I could never get ahold of the "big picture". Already documentation is so fucking scattered around that your stamina will drop! There is <a href="http://harmattan-dev.nokia.com/docs/library/html/guide/html/Developer_Library_MeeGo_1.2_Harmattan_Developer_Library.html">harmattan-dev</a>, when it is not offline, that is, and then there is the <a href="http://wiki.meego.com/Main_Page">MeeGo Wiki</a> (with it's own forum), the <a href="http://www.maemo.org/">Maemo forums</a>, the <a href="http://qt-project.org/doc/qt-4.7/">Qt documentation</a>, some blog here and there (including this), the code base on gitorious - which btw is in the end the best resource for everything, really; the power of open source was strong in this OS indeed!<br />
<br />
You would say with all these sources, the clearance (clearance, mind you, <b>not </b>coverage) about the OS is top-notch. Wrong! This whole scattering causes only frustration and loss of precious time spent jumping from one location to the other, trying to figure out which one is the one containing what you are looking for. For some kind of destiny joke, even Google seems to be obscure So, if you were looking for information on architecture / QML / Qt, then most likely the Nokia pages in <a href="http://harmattan-dev.nokia.com/docs/library/html/guide/html/Developer_Library_MeeGo_1.2_Harmattan_Developer_Library.html">harmattan-dev</a> are by far the better ones. For <b><i>anything else</i></b>, and I really mean <i><b>anything else</b></i>, everywhere else but <a href="http://harmattan-dev.nokia.com/docs/library/html/guide/html/Developer_Library_MeeGo_1.2_Harmattan_Developer_Library.html">harmattan-dev</a> is a better place. <br />
"Thank God there is everywhere else then", you would say. Wrong againg. <a href="http://harmattan-dev.nokia.com/docs/library/html/guide/html/Developer_Library_MeeGo_1.2_Harmattan_Developer_Library.html">harmattan-dev</a> is the only place which actually has some <i><b>structured</b></i> information (albeit still messy and sometimes very, very vague).<br />
So, whilst <a href="http://harmattan-dev.nokia.com/docs/library/html/guide/html/Developer_Library_MeeGo_1.2_Harmattan_Developer_Library.html">harmattan-dev</a> is the normal starting point in your Journey To MeeGo,and is a good strating point, <br />
since it covers every part required to publish a QML / Qt application to the Nokia store, everywhere else is nowhere else. It is a non-place! As you take a leap of faith and decide to step out of this "perfect Nokian Qt + QML" world, in which everything is perfect, but everything almost never works as it should, you will notice the even the normal laws of Googling do not apply anymore! Pages with the most hits for your search terms will not appear on Google's main page anymore! You will find yourself treasure-hunting together pieces of information for a certain topic from the most unexpected locations, and in the end you will still be back at square one because in the mean time the reason for the search will be erased from your mind. And this for every single problem you face. For example, <a href="http://www.maemo.org/">Maemo forums</a> is a great place to find even very obscure information tidbits of various topics. If you know what you are looking for. How do you know that? By trusting your instinct. Because that is the way it has to go. <br />
After <a href="http://store.ovi.com/content/340640">LINKer</a>, I felt something was missing. In my decent experienced IT life, I have seen may OS'es, and somehow always managed to get a good glimpse of how they worked and what was going on "behind the scenes" in a fairly fast time. With MeeGo, this was not the case.<br />
I had made two applications. One on QML (<a href="http://store.ovi.com/content/304258">BWizz</a>), which in my opinion was already quite deep (based on Qt Plugins and so on), and the second one (<a href="http://store.ovi.com/content/340640">LINKer</a>) based on lower-level Platform services (Share-ui and libContentAction). So by then I had a pretty clear idea of the structure; and I started toying around with various concepts for my third application. For this application, I decided I wanted to make an overlay. An overlay like the notification banner, for instance. And this decision, like some crazy curse, or spell, opened up the dark hearth of MeeGo in front of me. There was no way to find how to make such beast in QML (QML requires a window, which I did not want). So, I had to start looking elsewhere. <br />
After some initial lookaround, it became clear that at Nokia-(Platform) level I would have not found what I was looking for.<br />
There must have been more to it!<br />
So I decided to turn to the Gitorious codebase of MeeGo; as google kept on pushing up these results and as I am a n00b. And there, in all that which seemed to me like a pile of abandoned books, ruins of something that should have been but was not, I started searching through code and code. And guess what? The first thing I noticed, was that there was very little QML. NO QML! What the hell? I told to myself. N9 is supposed to be QML based? So wasnt I supposed to be able to make everything in QML? Where was the shiny and fancy, easy-to-use Nokia world of QML? Where were all the quick components? Why were they not used? Why was here libmeegotouch, meegotouch, contentlib, theming, a complete separate (MeeGo-) widget etimology based on Qt, buried and hidden away? Why did these MApplication, MButton, MLabel, and on keep on popping up? What was this...second personality of N9?<br />
It turned up there was much more than QML. MUCH more than that.</div>
Tone Kastlungerhttp://www.blogger.com/profile/03560854879582481991noreply@blogger.com0tag:blogger.com,1999:blog-8300911467973705649.post-81601813472024155022013-03-05T12:56:00.001-08:002013-03-05T12:56:47.674-08:00BB10 screenshots from Alpha Device<div dir="ltr" style="text-align: left;" trbidi="on">
It seems the easiest way to take a screenshot from the alpha device is to keep the volume up and down buttons simultaneously pressed! Wow!</div>
Tone Kastlungerhttp://www.blogger.com/profile/03560854879582481991noreply@blogger.com0tag:blogger.com,1999:blog-8300911467973705649.post-2055285389534079412013-03-05T12:55:00.000-08:002013-03-05T12:55:26.883-08:00LINKer goes BlackBerry!<div dir="ltr" style="text-align: left;" trbidi="on">
Startin today LINKer is available on BB10!!!<br />
<br />
<span style="font-family: sans-serif; font-size: 12px;"><a href="http://appworld.blackberry.com/webstore/content/21197956/" target="_blank">http://appworld.blackberry.<wbr></wbr>com/webstore/content/21197956/</a></span><br />
<br />
<span style="font-family: sans-serif; font-size: 12px;">Get it while it's hot! </span> </div>
Tone Kastlungerhttp://www.blogger.com/profile/03560854879582481991noreply@blogger.com0