Skip to main content

Ralsina.Me — Roberto Alsina's website

Posts about programming (old posts, page 88)

This is why you don't run random stuff.

Yes­ter­day I was try­ing to fig­ure ou­ut some ob­scure in­put things in Co­braPy such as "de­tect­ing the En­ter key" and ran in­to a love­ly pack­age in PyP­I: Pym­put

What does it do? It lets you in­ject and read in­put events.

And by in­put events I mean mouse and­key­board.

And it does so in your whole ses­sion.

And you would­n't no­tice if it was do­ing that.

And it does this in 20 lines of friend­ly python code. Here, have a key­board snif­fer:

from pynput import keyboard

def on_press(key):
    try:
        print('alphanumeric key {0} pressed'.format(
            key.char))
    except AttributeError:
        print('special key {0} pressed'.format(
            key))

def on_release(key):
    print('{0} released'.format(
        key))
    if key == keyboard.Key.esc:
        # Stop listener
        return False

# Collect events until released
with keyboard.Listener(
        on_press=on_press,
        on_release=on_release) as listener:
    listener.join()

This is one of the rea­sons why Way­land (or Mir, I re­mem­ber Mir!) needs to hap­pen. It's triv­ial for any desk­top app to mon­i­tor ev­ery­thing you do. Of course nowa­days you al­so will see soft­ware ad­ver­tis­ing this, as a "fea­ture" where it's used to "mon­i­tor em­ploy­ee pro­duc­tiv­i­ty".

Be­cause re­mem­ber, of­ten things are on­ly il­le­gal when in­di­vid­u­als do them, if you are a com­pa­ny and are charg­ing for it, then Bob's your un­cle.

Side Projects have Projects as Side Effects

I went and did a thing. But why, why?

When I start­ed play­ing with the idea of do­ing a sort-of-retro-80s-pro­gram­ming-en­vi­ron­ment called Co­braPy I sus­pect­ed one of the prob­lems would be find­ing a graph­ics li­brary that did what I want­ed and had good per­for­mance.

I have used PyGame a lit­tle in the past but nev­er liked it too much, so I tried Py­glet and it was work­ing great ... un­til I tried to add some­thing as sim­ple as a wid­get to en­ter tex­t. It does­n't re­al­ly do wid­get­s, for that you ap­par­ent­ly use glooey

But glooey is ... I don't like it. And then I ran into a bug where you can either clean the contents of an EditableLabel and set it to focused without it crashing deep in its bowels. I worked around it by using fake mouse events to focus. And then noticed you can't type a double quote in one of those widgets. So, I got pissed.

It lit­er­al­ly took me less time to find a nice C game li­brary, read a tu­to­ri­al on CF­FI, do min­i­mal ed­its to its head­er file, learn how to use in­voke and write my first pro­gram us­ing it than I wast­ed chas­ing that glooey bug.

And now, the ques­tion­s:

  • Does it work well? How could I know, I on­ly wrote the bind­ing, I have not used it yet!
  • Will I main­tain it? I don't think it re­quires much main­tain­ing.
  • Will I re­lease it? Maybe. It's here, mixed up with oth­er stuff

... aaaaand some­one else had al­ready done it. http­s://pyp­i.org/pro­jec­t/raylib/ But that's raylib 2.6, cur­rent is 3.0 :-)

CobraPy: baby steps

Some con­text: I am do­ing a sort of mod­ern retro-pro­gram­ming en­vi­ron­men­t-thingie.

So ... I caved. I caved and start­ed typ­ing.

It's still just ex­plorato­ry, fool­ing around, but I want­ed to see whether the vague ideas I had about how this could, maybe work were right, and hey, they are!

Text Mode

I want­ed a text mod­e. Some­thing with N rows and M col­umns where you could just say "put this text there". Done. In the most ba­sic pos­si­ble way that work­s.

Implemented a print_at function that takes row, column and text, and does what it says in the label.

Immediate Graphics Mode

In these old com­put­ers you could just draw in the graph­ics mem­o­ry. In 2020 ... not so much. So, I im­ple­ment­ed a sort of off­screen buf­fer. You draw there, and it gets blit­ted a lot to screen. Ends up work­ing like a flick­er-free dou­ble-buffered screen! Nice!

Implemented ellipse which ... draws an ellipse. I know, surprising.

Interpreter / Prompt

It would not be 80s-­like if you could not do those things in­ter­ac­tive­ly. So, yes, you can.

Now that was in­ter­est­ing. you see, nowa­days you are sup­posed to have an event loop. The com­put­er is there, idling and when some­thing hap­pen­s, then it does some­thing. So, you clicked? It re­act­s. 10 mil­lisec­onds passed? It does its thing.

In the 80s it was not like that. Your pro­gram start­ed and it owned the ma­chine. It went through your code, run­ning it as fast as it could with its lit­tle two-mega­herz-­heart un­til it ran out of code and then it was done.

So, how to make it act like that?

  • Start the event loop.
  • Start a sec­ond thread with a promp­t.
  • Have the us­er in­ter­act with the promp­t.
  • When the user presses Enter ... send the command to the event loop via a queue.
  • When the event ar­rives, do the thing.

And yes, it work­s! It's prob­a­bly hor­ri­ble for per­for­mance, but it does work just fine, and it's much, much eas­i­er to make a work­ing pro­gram fast than it is to make a fast pro­gram work.

So, what's nex­t?

The Future

I may try to in­te­grate the prompt and the win­dow where the text and such is dis­played (right now it's in a ter­mi­nal) ... maybe sprites.

Af­ter that:

  • Make the API nice and use­ful (a few weeks of work)
  • Make the thing run well (a few days of work)
  • Do the jan­i­to­ri­al work to make it us­able by some­one else (a cou­ple days of work)
  • Sup­port it, doc­u­ment it, etc (8 to 30 years of work)

The Nerdy Details

  • To do the graph­ics I am us­ing py­glet
  • To do off­screen draw­ing I am us­ing Pil­low
  • Tool­ing in­cludes the usu­al sus­pect­s: Python 3.8, po­et­ry, pylin­t, flake8
  • Code (all 50 lines or so!) in GitHub

Yes, this means this "80s" thing is ac­tu­al­ly mul­ti­thread­ed hard­ware-ac­cel­er­at­ed OpenGL graph­ic­s. I know, I know.

Possible New Project

I'm Old

I have not start­ed a re­al se­ri­ous open source project in a while. Ok, that's a lie. I have start­ed a num­ber of things and aban­doned them, but the last soft­ware project I start­ed that had last­ing pow­er was Niko­la and that was in 2012!

I turned 7**2 a couple weeks ago, so I am officially old (it's the law!) and us olds get bored because we don't get all the tiktok and whatever you youn'uns do.

So, I am get­ting itchy, and have been think­ing of start­ing some­thing. Af­ter see­ing a num­ber of retro­com­put­ing videos, it turns out the ZX-81 of my child­hood is vin­tage enough that they are ac­tu­al­ly old­er than ENI­AC was when I got it.

And it got me think­ing ... was there any­thing in that kind of com­put­ers that is worth sav­ing for some­thing oth­er than nos­tal­gia's sake? Sure, play­ing Mon­ty on The Run is as fun as al­ways and peo­ple still re­lease soft­ware for C64 and sim­i­lar an­cient com­put­er­s.

How­ev­er ... well, that sort of reeks of masochis­m, be­cause de­vel­op­ing for those sys­tem was ab­surd­ly painful. You can get the same lev­el of pain cod­ing for pi­co8 and peo­ple can play your games much eas­i­er.

There's al­so the retro-hard­ware thing but ... hon­est­ly, I like mod­ern hard­ware much bet­ter! For ex­am­ple, a Col­or Maximite looks much more fun that a C64 to de­vel­op in.

But stil­l.

There is this feel­ing that cur­rent com­put­ers are miss­ing some­thing.

Why not ex­plore it a lit­tle? I have a the­o­ry.

The Theory

Mod­ern com­put­ers are made to run things, old com­put­ers were not.

Get­ting some­one else's soft­ware in­to your com­put­er in 1984 was ab­surd­ly dif­fi­cult.

  1. Get a com­put­er (try do­ing that while liv­ing in Ar­genti­na in 1984)
  2. Now what? There's no In­ter­net
  3. Read the man­u­al and start cod­ing (yes, the man­u­al for the com­put­er ex­plained how)
  4. Fail
  5. Find some­one else who had a com­put­er and had ac­tu­al soft­ware for it
  6. Get copies. That of­ten in­volved copy­ing au­dio tapes. That would take be­tween 10 and 20 min­utes.
  7. Try out the copy on your com­put­er. Load­ing it in­to the com­put­er would al­so take be­tween 10 and 20 min­utes.

And af­ter that you had ... a port of Man­ic Min­er to C64 with crap­py sound.

So, some of us, we stuck a lit­tle to the oth­er side of those re­mark­able ma­chines. That they boot­ed in­to a de­vel­op­ment en­vi­ron­men­t. That you could make them do shit.

And that's what cur­rent com­put­ers don't do. They don't do shit. They don't in­vite you to start do­ing your own shit. Which is per­fect­ly and ag­gres­sive­ly fine, I don't mind. But I do.

The Plan in My Head

What would the evo­lu­tion of an 80s com­put­er look like nowa­days?

  • It should in­vite you to code and do shit
  • It should run on cheap, com­mod­i­ty hard­ware that is cheap and easy to find and buy
  • It should not do much out of the box. It's a box to do shit not to run shit.

There­fore, how about ...

A disk im­age that you can pop in­to a rasp­ber­ry Pi and...

  • Boots to a lim­it­ed en­vi­ron­ment
  • Where you can do shit
  • With fixed APIs and a pro­vid­ed soft­ware suite so that:
    • You can do some graph­ic­s, eas­i­­ly
    • You can do some sound, eas­i­­ly
    • You can ed­it a pro­­gram, eas­i­­ly
    • You can share it some­how, eas­i­­ly

Why the Pi?

  • It's fixed, known, cheap, sup­port­ed hard­ware.
  • You have IO pins to do ex­tra shit
  • It's cheap
  • Al­so, in­ex­pen­sive

What APIs?

  • Di­rec­t-ad­dress text mode (fake)
  • One or two graph­ics modes. 720p and 1080p?
  • Graph­ic prim­i­tives
  • Sprites! (hey, it's not the 80s with­out sprites)
  • Ba­sic mod play­ing
  • Some beep­ing thingie

What language?

Python. Sor­ry. I am play­ing with it, it's not go­ing to be BA­SIC.

Any weird thing?

Oh yes.

  • No im­port. You get the APIs you get.
  • Pro­grams are one file. You can use pack­ages in your big­boy box over there that has chrome in it.
  • No in­ter­net (no web brows­ing at least) just use your phone.
  • In­clud­ed sprite en­di­tor
  • In­clud­ed Mu­sic track­er

Are you really going to write this?

Well, I'm go­ing to give it a try and see if it's fun to do. If it's not I won't.

Are you looking for collaborators?

Nope. I want to do this so­lo at least for the first few month­s. My cod­ing at ear­ly project stages is way too er­rat­ic and would make ev­ery­one hate me.

What's it called.

It's nos­tal­gic. It's 80s. It has snakes in it. It should be Co­bra Kai.

But be­cause copy­right ex­ist­s, it's Co­bra Py. Or maybe Co­bra Pie, be­cause there's al­so oth­er python things called Co­bra.

h/t to Gui­do de Ca­so for fig­ur­ing out the name.

Programming is not a goal.

I did a Q&A a few days ago, and one of the ques­tions was "How does one break the toy project / codecade­my cy­cle?" ... I am not sure what that mean­s, but I will take this as an op­por­tu­ni­ty to rant about some­thing I care about that seems (to me) vague­ly re­lat­ed.

You may be feel­ing like you are trapped in a cy­cle of just learn­ing things, us­ing them in a toy project and then... what? You learn some­thing else? And do an­oth­er toy pro­jec­t? And so on?

And you feel like that is to­tal­ly mean­ing­less and gives you no feel­ing of achieve­men­t, no mo­ti­va­tion, and end up feel­ing like you are go­ing to be a new­bie forever?

Well, if that's the case ... lis­ten to me.

Your toy projects feel mean­ing­less be­cause they are not re­al.

That feel­ing you have? It's just your in­ner pro­gram­mer telling you to stop play­ing around and start proogram­ming for re­al. And I am here to tell you how to do that.

STEP 1: Find something you need your computer to do that it doesn't do

You want your Youtube videos to ap­pear in your blog?

You want to be know how many peo­ple called Rober­to were born in 1934 in Ar­genti­na?

Well, imag­i­nary per­son, af­ter you found some­thing like that, you can move to step 2.

Let's say you have de­cid­ed to im­ple­ment a gad­get that drives away the birds that wake you up ev­ery morn­ing in this end­less night­mare we cur­rent­ly live in.

STEP 2: Decide some basic details about your goal

This is what is called a projec­t. Im­ple­ment­ing sort­ing al­go­rithms is not a pro­jec­t, that's an ex­er­cise. Im­ple­ment­ing the 200th ver­sion of a chat us­ing web­sock­ets for your "port­fo­lio" is not a pro­jec­t, it's, I don't know, a bor­ing ad­den­dum to your re­sumé or some­thing.

A project is a goal. A project is "I want my com­put­er to do THIS and in the holy name of Bil­ly Wilder, I in­tend to spend the ef­fort to make it do it!"

So: I want some­thing that when it de­tects bird sound­s, makes noise to drive them away.

  1. Lis­tens for nois­es
  2. De­cides whether they are bird nois­es
  3. An­swers with a noise that is un­pleas­ant to birds

STEP 3: Convince yourself that's a possible thing computers can do

Be­cause, you know, com­put­ers can do a lot of things, but com­put­ers can't do ev­ery­thing. So, you need a quick re­al­i­ty check. Make it very quick, you don't want to spend more than, like, half an hour on it.

  • Can com­put­ers lis­ten for sound­s? Yeah.
  • Can com­put­ers make sound­s? Yep.
  • Can sounds drive away bird­s? Yes sir!
  • Can a com­put­er de­cide whether the noise it hears is a bird or not? Well, may­be? I have seen stranger things!

STEP 4: Come up with a semi-rational mechanism to implement it

This has to be very vague. Like "yeah, I can do that us­ing this Google API and this piece of lint I found in my so­fa". A vague idea.

  • Im­ple­ment some­thing that lis­tens for noise.
  • Add some­thing in the mid­dle that de­cides if noise is bird-­like
  • Make noise de­tec­tion trig­ger code
  • Im­ple­ment some­thing that makes noise

STEP 5: Come up with the most stupid version of the goal you can imagine

So, you want to write a bird-de­tec­tor? Try writ­ing a noise-de­tec­tor, first. Or rather, try to find some­thing that can re­act when your mi­cro­phone de­tects noise. Or even, find a li­brary that gives you ac­cess to your mi­cro­phone.

So:

  • Find a li­brary to read sound from mi­cro­phone
  • De­tect noise
  • Find li­brary to make noise
  • Make noise
  • Con­nect both pieces

STEP 6: sit the fuck down and implement the stupid version

This should be done FAST. If you plan too much you are not go­ing to do any­thing oth­er than plan a lot. You want to be­come a pro­gram­mer, not a PM. I won­der what the PM ver­sion of this rant would look like.

STEP 7: Show the stupid version to someone you respect, and listen

Yes, this part is scary, but pro­gram­ming is, in large part, about peo­ple. Show­ing things to peo­ple, lis­ten­ing to peo­ple, find­ing out what peo­ple re­al­ly mean, and so on.

So: show it to some­one. Lis­ten. Make de­ci­sions about whether you were right in steps 3 and 4. Maybe ad­just a lit­tle what yoour goal is.

STEP 8: repeat step 5 to 7 with a slightly less stupid version

Do this un­til you run in­to some­thing you have no idea how to do. In this case that's prob­a­bly go­ing to be "de­cide if that's a bird's sound"

STEP 9: get help

Ask around. Again, pro­gram­ming is most­ly about peo­ple. In this case, you will prac­tice "get­ting help". You don't want some­one to just tell you how (or maybe yes?) but this is the crit­i­cal point.

You can run in­to a few sce­nar­ios.

  1. You fig­ure it out.
  2. You fig­ure out that it can't be done.
  3. You find out that it's doable but you just have no idea how.

If you fig­ure it out, then there is no prob­lem! Go back to step 5 and con­tin­ue un­til you are hap­py with the pro­jec­t, and you have learned some­thing new! Con­grat­u­la­tion­s!

The oth­er two out­comes lead to ...

STEP 10: get stuck

If you fig­ured out that it can't be done, then you have learned about one type of prob­lem that is cur­rent­ly in­tractable. Con­sid­er­ing you are new to this sort of thing, that is prob­a­bly not some­thing you are go­ing to solve, but ... if you re­al­ly were in­ter­est­ed in this pro­jec­t, it may point you to a whole kind of thing you want to learn about.

So, you can't de­cide if a giv­en noise is a bird ... why? Is there re­search be­ing done in that area? Would that in­volve ma­chine learn­ing? Hey, that sounds in­ter­est­ing. Usu­al­ly the ex­am­ples are about im­ages... is there any in­ter­est­ing work be­ing done about ap­ply­ing it to au­dio? Are there li­braries? Are there dataset­s? Are there tu­to­ri­al­s? Hm­mm ... and now you know some­thing you want to learn about. Have fun.

The third out­come is the com­pli­cat­ed one. Let's say it can be done by cre­at­ing a mod­el with ML and a dataset of ur­ban nois­es and a dataset of bird nois­es and both things ex­ist, and it has been done, and you know about it (a lit­tle) but you have no idea how to do it.

Well, in that case ... con­grat­u­la­tion­s, you have found the cur­rent lim­it of your com­pe­tence. You just need to ex­pand it. And that's what pro­gram­ming is like.

So, how does this whole convoluted process help you?

You are learn­ing dif­fer­ent things you won't learn do­ing ex­er­cis­es.

  • You learn to de­cide what to do.
  • You learn to ask for help.
  • You learn to present your work to oth­er­s.
  • You learn to process feed­back.
  • You learn to re­search your prob­lem space.
  • You learn to break down tasks.
  • You learn to make de­ci­sion­s.

And yes, you may learn a pro­gram­ming skill or two.

And, maybe (but it's un­like­ly) you will get rid of those pesky morn­ing bird­s.

PS: http­s://github.­com/karolpicza­k/BAD­C-2017


If you are in­ter­est­ed in a long com­ment thread about this, of which rough­ly 30% missed the point of this not be­ing some sort of uni­ver­sal ad­vice and there­fore tak­ing per­son­al of­fense at it, and 50% is me re­spond­ing to each and ev­ery com­men­t, see red­dit.


Contents © 2000-2020 Roberto Alsina