Ir al contenido principal

Ralsina.Me — El sitio web de Roberto Alsina

Publicaciones sobre linux

The perfect Raspberry Pi setup

I am do­ing some semi-se­ri­ous Rasp­ber­ry Pi de­vel­op­men­t, so it was time I fig­ured out how to do it com­fort­ably.

My desk­top set­up is a two-­mon­i­tor con­fig­u­ra­tion, with my note­book on the ta­ble and a larg­er mon­i­tor above it. I like it, it's nice. The point­er nat­u­ral­ly goes from one screen to the oth­er in the ob­vi­ous way.

Desktop setup

Spe­cial­ly nice is that the lap­top's screen is touch and has an ac­tive pen, so I can use it nat­u­ral­ly.

But now, with the Rasp­ber­ry, I want to oc­ca­sion­al­ly show its dis­play. And that means switch­ing the mon­i­tor to it. Since I hate plug­ging and un­plug­ging things, I use one of the­se:

HDMI switch

It's a cheap tiny black plas­tic box that takes up to 5 HD­MI in­puts and switch­es be­tween them to its one out­put by click­ing a but­ton. It on­ly goes through the in­puts that have sig­nal, so since I on­ly have the lap­top's and the Pi's the but­ton tog­gles be­tween them.

If your mon­i­tor has more than one HD­MI in­put you can prob­a­bly just use that, but mine has just one.

But... what about key­board and mouse?

I could get a mul­ti­de­vice key­board and mouse, but I like the ones I have.

I could use a USB switch and tog­gle be­tween the two de­vices, but ... I don't have one.

So, I use bar­ri­er and con­fig­ure it in both the rasp­ber­ry pi and in the lap­top so that when my point­er goes "up" in­put goes to the Pi, and when it goes "down" in­put goes to the lap­top. That's ex­act­ly the same as with the du­al-dis­play se­tup, but with two com­put­er­s. Neat!

So, go ahead and con­fig­ure bar­ri­er. It's easy and there are tons of tu­to­ri­al­s.

Nex­t, make sure bar­ri­er starts when I lo­gin in­to both com­put­er­s. They way I pre­fer to do these things is us­ing sys­temd.

Put this in ~/.local/share/systemd/user/barrier.service in both machines:

[Unit]
Description=Barrier server
[Service]
Environment=DISPLAY=:0
Type=simple
TimeoutStartSec=0
ExecStart=/usr/bin/barrier
[Install]
WantedBy=default.target

Now you can make it start with systemctl --user start barrier or stop with systemctl --user stop barrier and make it start on every login with systemctl --user enable barrier

But while this is nice, it presents a prob­lem. When I am us­ing both dis­plays for the lap­top, I don't want bar­ri­er run­ning! Since I can't see the Pi's dis­play, it makes no sense.

So, I want to start bar­ri­er when the lap­top is us­ing one mon­i­tor, and stop it when it's us­ing two.

To do that, the trick is udev in the laptop. Put this (replacing my username with yours) in /etc/udev/rules.d/90-barrier.rules:

ACTION=="change", \
    KERNEL=="card0", \
    SUBSYSTEM=="drm", \
    ENV{DISPLAY}=":0", \
    ENV{XAUTHORITY}="/home/ralsina/.Xauthority", \
    ENV{XDG_RUNTIME_DIR}="/run/user/1000", \
    RUN+="/home/ralsina/bin/monitors-changed"

Basically that means "when there is a change in the configuration of the video card, run monitors-changed. Change the 1000 by your user ID, too.

The last piece of the puzzle is the monitors-changed script:

if `xrandr --listmonitors | grep -q HDMI`
then
    # The HDMI output is connected, stop barrier
    su ralsina -c '/usr/bin/systemctl stop --user barrier'
else
    # The Pi is using the monitor, start barrier
    su ralsina -c '/usr/bin/systemctl start --user barrier'
fi

And that's it!

This is the be­hav­iour now:

  • When the lap­­top is us­ing both dis­­­plays, they work nor­­mal­­ly in a "ex­­tend­ed dis­­­play" con­­fig­u­ra­­tion. They be­have like a sin­­gle large screen.

  • When I click on the HD­­MI switch and change the top dis­­­play to show the Pi's desk­­top, au­­to­­mat­i­­cal­­ly bar­ri­er starts in the lap­­top, and now the point­er and key­board change from one com­put­er to the oth­­er when the point­er moves from one mon­i­­tor to the nex­t.

  • If I click on the HD­­MI switch again, bar­ri­er stops on the lap­­top and I have a sin­­gle two-screen desk­­top again.

Ev­ery­thing be­haves per­fect­ly and I can switch be­tween com­put­ers by click­ing a but­ton.

Al­ter­na­tive­ly, we could start the bar­ri­er client when the rasp­ber­ry pi "get­s" the dis­play, and stops it when it goes away. The re­sult should be the same ex­cept for some cor­ner cas­es, but it has the added ben­e­fit of al­low­ing for a set­up with up to 5 de­vices :-)

Una semana usando tiling windows.

Ha pa­sa­do un po­co más de una se­ma­na des­de que de­ci­dí usar un ti­ling win­dow ma­na­ger "en se­rio­".

Cla­ro, es­toy ha­cien­do un po­qui­to de tram­pa por­que es­toy usan­do KDE más Kröhnki­te pe­ro mis ven­ta­nas ha­cen mo­sai­cos y me gus­ta.

Por qué es­to y no i3 u otra co­sa? Por­que no quie­ro cam­biar mi es­ti­lo de vi­da, na­da más quie­ro que mis ven­ta­nas no se so­la­pen to­do el tiem­po.

Kröhnki­te me da su­fi­cien­te fun­cio­na­li­dad "ti­lin­g" que ob­ten­go (creo) los be­ne­fi­cios sin el ma­si­vo des­pe­lo­te de aban­do­nar to­das las co­sas de mi es­cri­to­rio a las que es­toy acos­tum­bra­do. To­da­vía uso la te­cla Win­do­ws (o­k, ok, la te­cla "Me­ta") pa­ra lan­zar app­s, si­go te­nien­do un pa­nel de plas­ma con plas­moi­des en la par­te de aba­jo de mi mo­ni­to­r. ¡Pue­do ha­cer que las ven­ta­nas flo­ten si quie­ro! Pue­do usar la ma­yo­ría de los ata­jos de te­cla­do de mis 24 años usan­do KDE (sí, en se­rio) etc.

¿Cuá­les co­sas tu­ve que cam­biar pa­ra adap­tar­me?

  • Tu­­ve que pa­sar a fo­­­cus-­­fo­­­llo­­ws-­­mou­­se. PE­­RO por pri­­me­­ra vez des­­de que em­­pe­­cé a usar FVWM en 1993 me gus­­ta más que cli­­ck-­­to­­-­­fo­­­cus. Re­­su­l­­ta que la im­­ple­­men­­ta­­ción de KDE es­­tá bue­­­na y bá­­si­­ca­­men­­te "ha­­ce lo que uno quie­­re". Co­­­mo di­­ce en la do­­­cu­­men­­ta­­ció­­n, "es co­­­mo cli­­ck to fo­­­cus, pe­­ro no ha­­cés cli­­ck".

  • Sa­­qué las de­­co­­­ra­­cio­­­nes de las ven­­ta­­na­s. Sí, se pue­­den de­­ja­­r, pe­­ro se ve ra­­ro.

  • Pu­­se bo­r­­des más grue­­so­­s. Ca­m­­biar el ta­­ma­­ño de las ven­­ta­­nas con el te­­cla­­do no es­­tá bue­­­no, así que los bo­r­­des más grue­­sos ayu­­dan.

¿Cuá­les co­sas me gus­ta­ro­n?

  • Te­­ner la­­yout ti­­ling en un mo­­­ni­­tor y floa­­ting en el otro es­­tá muy bue­­no cuan­­do se ne­­ce­­si­­ta. Y lo pue­­do ac­­ti­­var o des­a­c­­ti­­var con una te­­cla. En ge­­ne­­ra­­l: la­­you­­ts di­­ná­­mi­­cos y se­­pa­­ra­­dos por pan­­ta­­lla son mu­­y, muy úti­­le­s.

  • Te­­ner un WM "ti­­li­n­­g" pe­­ro que to­­­da­­vía res­­pe­­ta las co­n­­ven­­cio­­­nes de la ma­­yo­­­ría de los WMs es­­tá bue­­no. Los po­­­pups flo­­­tan, ok?

  • El ata­jo Al­t+En­ter pa­ra ha­cer que una ven­ta­na sea la "im­por­tan­te" es­tá ge­nia­l.

  • Me en­­can­­ta co­­­mo ma­­ne­­ja ma­­xi­­mi­­za­­ció­­n/­­mi­­ni­­mi­­za­­ció­­n.

¿Cuá­les co­sas no me gus­ta­ro­n?

  • El la­­yout "ti­­le­­d" tie­­ne múl­­ti­­ples ve­r­­sio­­­nes que se ca­m­­bian con Ctr­­l+I/D ... y a ve­­ces ni­n­­gu­­na es exa­c­­ta­­men­­te lo que quie­­ro? Ta­m­­bién sue­­le pa­sar que las mas "a­l­­ta­s" no pa­­re­­cen ha­­cer na­­da, pro­­­ba­­ble­­men­­te po­r­­que no ten­­go su­­fi­­cien­­tes ven­­ta­­nas en el mo­­­sai­­co.

  • Ya que no ten­go de­co­ra­cio­nes en las ven­ta­na­s, la in­con­sis­ten­cia bru­tal acer­ca de cual es el ata­jo pa­ra ce­rrar una apli­ca­ción es muy mo­les­to. Pue­de ser ctr­l+q o ctr­l+x o esc o nin­guno de ello­s. Ter­mino ha­cien­do al­t+­f4 que se sien­te co­mo Win­do­ws 3.11

  • La ex­­pe­­rien­­cia de scri­p­­ts pa­­ra KWin no es pe­r­­fe­c­­ta. In­s­­ta­­lé otro ha­­ce un tie­m­­po, lla­­ma­­do Qua­r­­te­­r-­­Ti­­li­n­­g, y lo de­­sin­s­­ta­­lé, ha­s­­ta do­n­­de sé no hay ra­s­­tros de él en mi sis­­te­­ma ... ex­­ce­p­­to por sus ata­­jos de te­­cla­­do, que van a en­­su­­ciar mi diá­­lo­­­go de ata­­jos pa­­ra sie­m­­pre.

El ex­pe­ri­men­to con­ti­núa!

El Server Mínimo

En­ton­ces hoy en la ho­ra del al­muer­zo me pu­se a lim­piar la ba­su­ra. Es­te post des­cri­be con qué ter­mi­né, que es el ser­ver mí­ni­mo que me sir­ve pa­ra al­go.

Hosting

Es un VPS ba­ra­to pro­vis­to por los ami­gos de burs­t.­net que no me pa­gan pa­ra de­cir co­sas bue­nas de su ser­vi­cio. Sin em­bar­go, las di­go igua­l:

  • Muy ba­­ra­­to (U$S 5.50 pe­­ro ten­­go 20% de des­­cuen­­to pa­­ra sie­m­­pre)

  • Ba­s­­tan­­te tran­s­­fe­­ren­­cia ca­­da mes

  • Mu­­cho es­­pa­­cio

  • Buen up­­ti­­me

  • Red rá­­pi­­da

  • Muy ba­­ra­­to

  • Pe­r­­fo­r­­man­­ce de­­cen­­te

  • Ba­­ra­­to

Distribución

Ya te­nía Cen­tOS 5, y si­gue ahí. Si burst al­gu­na vez ofre­ce Ubun­tu Pre­ci­se, ca­paz que cam­bio. O, ya que es­to an­da, ca­paz que no.

Lo bue­no de Cen­tO­S: es­ta­ble y abu­rri­do.

Lo ma­lo de Cen­tO­S: es un po­co de­ma­sia­do abu­rri­do. Mon­to­nes de co­sas sim­ple­men­te no es­tán em­pa­que­ta­da­s.

Web Server

Ten­go que ser­vir una canti­dad de do­mi­nio­s, pe­ro con una pe­cu­lia­ri­da­d: son to­dos si­tios es­tá­ti­co­s. Lo que quie­ro es:

  • Ba­­jo uso de re­­cu­r­­sos

  • Pe­r­­fo­r­­man­­ce de­­cen­­te (con ran­­gos y ne­­go­­­cia­­ción de co­n­­te­­ni­­do­­s)

  • Es­­ta­­ble

  • Con ín­­di­­ces de di­­re­c­­to­­­rio

  • Fá­­cil de co­n­­fi­­gu­­rar

  • Do­­­mi­­nios vi­r­­tua­­les por no­m­­bre

Ca­si cual­quier ser­vi­dor an­da pa­ra es­to. Has­ta Apa­che, ex­cep­to por eso de la con­fi­gu­ra­ción sen­ci­lla. Ter­mi­né con ga­tling por­que cum­ple esos cri­te­rios bas­tan­te bien.

  • Usa al­­re­­de­­dor de 1.4MB de RAM que es­­tá bue­­no en un VP­S.

  • Es ba­s­­tan­­te rá­­pi­­do

  • Lle­­va ho­­­ras sin caer­­se

  • Ge­­ne­­ra ín­­di­­ces

  • Es­­ta es la co­n­­fi­­gu­­ra­­ció­­n: "-c /s­r­­v/www -P 2M -d -v -p 80 -F -S" (no, no hay ar­­chi­­vo de co­n­­fi­­gu­­ra­­ció­­n)

  • Los do­­­mi­­nios vi­r­­tua­­les son ca­r­­pe­­tas y sy­­m­­li­nks aden­­tro de /s­r­­v/www que es lo más fá­­cil po­­­si­­ble.

  • So­­­po­r­­ta pro­­­xy in­­ve­r­­so pa­­ra cuan­­do quie­­ro pro­­­bar una we­­ba­­pp py­­thon en la que es­­toy tra­­ba­­jan­­do.

Mail Server

No quie­ro un mail ser­ve­r. Ten­go gmail y un ser­ver de ver­dad pa­ra eso. Lo que quie­ro son los mails de cro­n. Pa­ra eso usé ss­m­tp y una cuen­ta ex­tra de gmai­l. Fun­cio­na, y es­ta es to­da la con­fi­gu­ra­ció­n:

root=roberto.alsina@gmail.com
mailhub=smtp.gmail.com:587
UseTLS=YES
UseSTARTTLS=YES
AuthMethod=LOGIN
AuthUser=roberto.alsina.3@gmail.com
AuthPass=notputtingthetrueoneheredude

Lo me­jor que pue­do de­cir es que fun­cio­na, y no in­vo­lu­cra co­rrer un ser­ve­r.

Misc

Pa­ra cuan­do ten­go que es­tar en dos lu­ga­res al mis­mo tiem­po: Open­VPN es lo má­s, y no se acep­tan dis­cu­sio­nes. Ten­go un squid co­rrien­do a ve­ce­s, y hay un Qua­ssel co­re pa­ra IR­C. Ins­ta­lé mosh pa­ra que el ssh sea me­nos do­lo­ro­so, rs­ync ha­ce de­plo­y­men­ts y guar­da ba­ckup­s, cron eje­cu­ta co­sas, y na­da má­s.

Status

Mon­to­nes de RAM y CPU li­bres (sí, esa es la lis­ta com­ple­ta de pro­ce­so­s):

[root@burst1 ~]# ps aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.1   2156   664 ?        Ss   22:01   0:00 init [3]
root      1135  0.0  0.1   2260   576 ?        S<s  22:01   0:00 /sbin/udevd -d
root      1518  0.0  0.1   1812   572 ?        Ss   22:01   0:00 syslogd -m 0
root      1594  0.0  0.1   7240  1032 ?        Ss   22:01   0:00 /usr/sbin/sshd
root      1602  0.0  0.2   4492  1112 ?        Ss   22:01   0:00 crond
root      1630  0.0  0.1   5684   716 ?        Ss   22:01   0:00 /usr/sbin/saslauthd -m /var/run/saslauthd -a pam -n 2
root      1631  0.0  0.0   5684   444 ?        S    22:01   0:00 /usr/sbin/saslauthd -m /var/run/saslauthd -a pam -n 2
root      1636  0.0  0.2   3852  1372 ?        S    22:01   0:01 /opt/diet/bin/gatling -c /srv/www -P 2M -d -v -p 80 -F -S
root      1677  0.0  0.2   4284  1232 ?        Ss   22:02   0:00 SCREEN /root/quasselcore-static-0.7.1
root      1678  0.0  2.1  36688 11148 pts/0    Ssl+ 22:02   0:03 /root/quasselcore-static-0.7.1
root      3228  1.0  0.7  12916  4196 ?        Ss   23:28   0:13 mosh-server new -s -c 8
root      3229  0.0  0.3   3848  1588 pts/2    Ss   23:28   0:00 -bash
root      3275  0.0  0.1   2532   908 pts/2    R+   23:48   0:00 ps aux
[root@burst1 ~]# w
 23:49:03 up  1:47,  1 user,  load average: 0.00, 0.01, 0.00
USER     TTY      FROM              LOGIN@   IDLE   JCPU   PCPU WHAT
root     pts/2    186.153.52.253   23:28    0.00s  0.01s  0.00s w
[root@burst1 ~]# free
             total       used       free     shared    buffers     cached
Mem:        524800      49100     475700          0          0          0
-/+ buffers/cache:      49100     475700
Swap:            0          0          0

Te­nien­do en cuen­ta to­do, bas­tan­te con­ten­to con el re­sul­ta­do.

APIs de Ubuntu One en Ejemplos (parte 1)

Así que acá va un pe­que­ño tu­to­rial acer­ca de co­mo usar al­gu­nas de esas APIs. Lo hi­ce usan­do Py­thon y Py­Qt por va­rios mo­ti­vo­s:

  • Son ex­­ce­­len­­tes he­­rra­­mien­­tas pa­­ra pro­­­to­­­ti­­pos

  • Tie­­nen ex­­ce­­len­­te so­­­po­r­­te pa­­ra las co­­sas que ne­­ce­­si­­to (DBus, HTTP, OAu­­th)

  • Es lo que sé y me gus­­ta. Lo hi­­ce un do­­­mi­n­­go, no lo pien­­so ha­­cer en PHP y Gtk.

Di­cho eso, no hay na­da es­pe­cí­fi­co de py­thon o de Qt en es­te có­di­go. Don­de ha­go un re­quest HTTP usan­do QtNe­two­rk, po­dés usar lib­soup o lo que fue­re.

Va­ya­mos a los bi­fes en­ton­ce­s. Las pie­zas más im­por­tan­tes de Ubun­tu One, des­de el pun­to de vis­ta de in­fra­es­truc­tu­ra, son Ubun­tu SSO Clien­t, que se en­car­ga de lo­gi­n, re­gis­tra­ció­n, etc, y Syn­c­Dae­mos que ma­ne­ja la sin­cro­ni­za­ción de ar­chi­vo­s.

Pa­ra in­te­rac­tuar con ella­s, en Li­nu­x, ofre­cen in­ter­fa­ces DBus. Así que, por ejem­plo, es­te es un frag­men­to mos­tran­do co­mo ob­te­ner las cre­den­cia­les de Ubun­tu One (es­to nor­mal­men­te se­ría par­te del __i­ni­t__ de un ob­je­to­):

# Get the session bus
bus = dbus.SessionBus()

:
:
:

# Get the credentials proxy and interface
self.creds_proxy = bus.get_object("com.ubuntuone.Credentials",
                        "/credentials",
                        follow_name_owner_changes=True)

# Connect to signals so you get a call when something
# credential-related happens
self.creds_iface = dbus.Interface(self.creds_proxy,
    "com.ubuntuone.CredentialsManagement")
self.creds_proxy.connect_to_signal('CredentialsFound',
    self.creds_found)
self.creds_proxy.connect_to_signal('CredentialsNotFound',
    self.creds_not_found)
self.creds_proxy.connect_to_signal('CredentialsError',
    self.creds_error)

# Call for credentials
self._credentials = None
self.get_credentials()

Tal vez no­tas­te que ge­t_­cre­den­tials no de­vuel­ve las cre­den­cia­le­s. Lo que ha­ce es, le di­ce a Syn­c­Dae­mon que las ob­ten­ga, y en­ton­ce­s, si/­cuan­do apa­re­cen, se emi­te una de esas se­ña­le­s, y uno de los mé­to­dos co­nec­ta­dos se lla­ma. Es­to es­tá bue­no por­que no te­ne­mos que preo­cu­par­nos de que se nos blo­quee la apli­ca­ción mien­tras Syn­c­Dae­mon es­tá bus­can­do las cre­den­cia­le­s.

¿Y qué hay en esos mé­to­do­s? ¡No mu­cho!

def get_credentials(self):
    # Do we have them already? If not, get'em
    if not self._credentials:
        self.creds_proxy.find_credentials()
    # Return what we've got, could be None
    return self._credentials

def creds_found(self, data):
    # Received credentials, save them.
    print "creds_found", data
    self._credentials = data
    # Don't worry about get_quota yet ;-)
    if not self._quota_info:
        self.get_quota()

def creds_not_found(self, data):
    # No credentials, remove old ones.
    print "creds_not_found", data
    self._credentials = None

def creds_error(self, data):
    # No credentials, remove old ones.
    print "creds_error", data
    self._credentials = None

Así que bá­si­ca­men­te, se­l­f._­cre­den­tials con­tie­ne unas cre­den­cia­le­s, o No­ne. Fe­li­ci­ta­cio­nes, ya en­tra­mos a Ubun­tu One.

¡Ha­ga­mos al­go úti­l! ¿Que tal pre­gun­tar cuán­to es­pa­cio li­bre hay en la cuen­ta? Pa­ra eso, no po­de­mos usar las APIs lo­ca­le­s, si no co­nec­tar­nos a los ser­ver­s, que son los que sa­ben si es­tás ex­ce­di­do de quo­ta o no.

El ac­ce­so se con­tro­la via OAu­th, por lo que pa­ra ac­ce­der a esa API ne­ce­si­ta­mos fir­mar nues­tros pe­di­do­s. Aquí se ve co­mo se ha­ce. No es par­ti­cu­lar­men­te ilu­mi­na­do­r, yo no lo es­cri­bí, so­la­men­te lo uso:

def sign_uri(self, uri, parameters=None):
    # Without credentials, return unsigned URL
    if not self._credentials:
        return uri
    if isinstance(uri, unicode):
        uri = bytes(iri2uri(uri))
    print "uri:", uri
    method = "GET"
    credentials = self._credentials
    consumer = oauth.OAuthConsumer(credentials["consumer_key"],
                                   credentials["consumer_secret"])
    token = oauth.OAuthToken(credentials["token"],
                             credentials["token_secret"])
    if not parameters:
        _, _, _, _, query, _ = urlparse(uri)
        parameters = dict(cgi.parse_qsl(query))
    request = oauth.OAuthRequest.from_consumer_and_token(
                                        http_url=uri,
                                        http_method=method,
                                        parameters=parameters,
                                        oauth_consumer=consumer,
                                        token=token)
    sig_method = oauth.OAuthSignatureMethod_HMAC_SHA1()
    request.sign_request(sig_method, consumer, token)
    print "SIGNED:", repr(request.to_url())
    return request.to_url()

¿Y có­mo pe­di­mos el es­ta­do de quo­ta? Ac­ce­dien­do al pun­to de en­tra­da http­s://o­ne.u­bun­tu.­co­m/a­pi/­quo­ta/ con la au­to­ri­za­ción ade­cua­da, se ob­tie­ne un dic­cio­na­rio JSON con el es­pa­cio to­tal y el usa­do. Acá hay una mues­tra de co­mo ha­cer­lo:

    # This is on __init__
    self.nam = QtNetwork.QNetworkAccessManager(self,
        finished=self.reply_finished)

:
:
:

def get_quota(self):
    """Launch quota info request."""
    uri = self.sign_uri(QUOTA_API)
    url = QtCore.QUrl()
    url.setEncodedUrl(uri)
    self.nam.get(QtNetwork.QNetworkRequest(url))

De nue­vo: ge­t_­quo­ta no de­vuel­ve la quo­ta. Só­lo lan­za un pe­di­do HTTP a los ser­vers de Ubun­tu One, que (e­ven­tual­men­te) res­pon­den con los da­to­s. No que­rés que tu app se que­de ahí tra­ba­da mien­tras tan­to, por eso QNe­two­rkAc­ce­ss­Ma­na­ger va a lla­mar a se­l­f.­re­pl­y_­fi­nis­hed cuan­do ten­ga la res­pues­ta:

def reply_finished(self, reply):
    if unicode(reply.url().path()) == u'/api/quota/':
        # Handle quota responses
        self._quota_info = json.loads(unicode(reply.readAll()))
        print "Got quota: ", self._quota_info
        # Again, don't worry about update_menu yet ;-)
        self.update_menu()

¿Qué más que­re­mo­s? ¿Qué tal no­ti­fi­ca­ción cuan­do cam­bia el sta­tus de Syn­c­Dae­mo­n? Por ejem­plo, cuan­do la sin­cro­ni­za­ción es­tá al día, o cuan­do te des­co­nec­ta. De nue­vo, esas son se­ña­les DBus a las que uno se co­nec­ta en __i­ni­t__:

self.status_proxy = bus.get_object(
    'com.ubuntuone.SyncDaemon', '/status')
self.status_iface = dbus.Interface(self.status_proxy,
    dbus_interface='com.ubuntuone.SyncDaemon.Status')
self.status_iface.connect_to_signal(
    'StatusChanged', self.status_changed)

# Get the status as of right now
self._last_status = self.process_status(
    self.status_proxy.current_status())

Y es­ta es sta­tus_­chan­ge­d:

def status_changed(self, status):
    print "New status:", status
    self._last_status = self.process_status(status)
    self.update_menu()

la fun­ción pro­ce­ss_s­ta­tus is có­di­go abu­rri­do pa­ra con­ver­tir la in­fo de sta­tus de syn­c­dae­mon en una co­sa le­gi­ble co­mo "S­ync is up-­to­-­da­te", así que guar­da­mos eso en se­l­f._­las­t_s­ta­tus y ac­tua­li­za­mos el me­nú.

¿Qué me­nú? ¡Un me­nú con­tex­tual de un QS­ys­te­m­Tra­yI­co­n! Lo que le­ye­ron son las pie­zas prin­ci­pa­les que se ne­ce­si­tan pa­ra crear al­go úti­l: una apli­ca­ción de Sys­te­m­Tray pa­ra Ubun­tu One que se pue­de usar en KDE, XFCE u Open­bo­x. O, si es­tás en uni­ty y te­nés sni-­qt ins­ta­la­do, un app in­di­ca­to­r.

http://ubuntuone.com/7iXTbysoMM9PIUS9Ai4TNn

El in­di­ca­dor en ac­ció­n.

El có­di­go fuen­te del ejem­plo com­ple­to es­tá en mi pro­yec­to u1-­to­ys en laun­ch­pad y és­te es el có­di­go fuen­te com­ple­to (ex­cep­to los ico­nos, ba­jen­se el re­po, me­jo­r)

Vi­nien­do pron­to (es­pe­ro­), más apps de ejem­plo, y co­sas co­pa­das que se pue­den ha­cer con nues­tras APIs.

$HOME is where .bashrc is

¿Có­mo pa­só es­to? ¿Qué me pa­só? ¿Qué es­ta­ba pen­san­do? Es una his­to­ria abu­rri­da y po­co in­te­re­san­te.

En­tré a tra­ba­jar a Ca­no­ni­ca­l. A mi no­te­book vie­ja no le da­ba el cue­ro. La nue­va no que­ría que le ins­ta­la­ra Ubun­tu. Di­je "ma sí, me voy a vi­vir a una VM". La VM era más len­ta que el Che­cho Ba­tis­ta. Te­nía que de­sa­rro­llar co­sas en Win­do­ws (sí). Al­gu­nas co­sas no fun­cio­na­ban bien en la VM. Y de a po­qui­to, las co­sas y los ar­chi­vos se jun­ta­ban en win­do­ws, en el har­dwa­re rea­l, Win­do­ws 7 Ho­me Pre­miu­m.

En ge­ne­ra­l, Win­do­ws 7 es no ho­rri­ble. La ma­yo­ría de las co­sas an­dan. Lo que sí, pa­ra un pro­gra­ma­do­r, es cul­ti­var en el de­sier­to. Po­dés ha­cer que crez­can co­sas, pe­ro hay que po­ner­le mu­chas ga­na­s.

Así que hoy ins­ta­lé Ku­bun­tu Onei­ric (¡­nin­gún pro­ble­ma!), jun­té to­dos los da­tos de la no­te­book vie­ja, de la Vm, de win­do­ws, bo­rré win­do­ws, y me mu­dé a Li­nu­x, y aho­ra Win­do­ws es la VM.

Ex­tra­ña­ba.


Contents © 2000-2020 Roberto Alsina