syntax highlight

Saturday, 3 August 2019

std::is_constant_evaluated: make debugging a little bit harder for yourself!

Let's pretend you find this:

const int a = foo();
int b = foo();

Would you be tempted to assume that a==b, always? I would. What if 'foo' actually depends on a global variable, and its return value depends on that global setting? Suddenly the code above will raise a few eyebrows in a code review session.

Coming to your friendly c++20 standard now:

constexpr int foo() { 
    return (std::is_constant_evaluated())? 42 : 24;
}

bool a() {
    const int x = foo();
    return x == foo();
}

I'm sure with careful usage, is_constant_evaluated will allow library writers to create much more performant code. I'm also sure I'll lose a lot of hair trying to figure out why my debug code (cout << foo(), anyone?) prints different values than my `production` code.

Saturday, 27 July 2019

Vim multiple search

I keep forgetting about this one. Maybe writing it down will help me remember: Vim can search for (and highlight) multiple patterns at the same time. Just start your search with \v and split the patterns with |. Eg:

:/\vfoo|bar

Thursday, 18 July 2019

Bash: Color in command line prompt PS1

I'm lately dealing with lots of hosts in different environments (eg local, dev, test, etc). Some actions are safe to perform in some of these hosts, in others not so much. To help quickly figure out which hosts are safe, I wanted to add a color to my Bash prompt (PS1) - for example green for dev, where it's unlikely I'll break anything other than my stuff, red for hosts where carelessness might result in a weekend spent at the office.

The first result I get in Google when trying to set Bash's PS1 to use colors seems to be wrong (or, rather, I wasn't smart enough to make it work). An escape sequence seems to be missing, resulting in weird behavior with new lines; colors work, but line wrapping gets broken. Took me a while to associate broken \n's with colors, but once I did the fix was easy. Check out here for the proper way to escape color commands in Bash: https://stackoverflow.com/questions/342093/ps1-line-wrapping-with-colours-problem

And here's my current setup:

export COLOR_SET='\[\e['$THIS_HOST_COLOR'm\]'
export COLOR_RESET='\[\e[0m\]'

# Example:
export PS1='\A '$COLOR_SET'\h'$COLOR_RESET':\w$ '

Tuesday, 11 June 2019

The bestest autocomplete for Vim

TL;DR: I like YouCompleteMe

A post in Hacker News drew me to look at autocompletion in Vim. After trying a few plugins years before, I settled for the available-by-default autocomplete in Vim. It's pretty dumb, but pretty dumb covers 90% of what I need: autocompletionForReallyUglyOrLongNames.

Vim's omnifunc completer is enough if no fancy features are necessary: fast, available, trivial to setup. I have successfully used omnifunc in fairly large projects, and while it requires familiarity with the codebase, some may argue that's a feature and not a bug.

Now I confess: I don't understand Vundle, Pathogen or any other Vim plugin handler. Second extravagant opinion in this post: I don't see the point of a plugin manager for Vim. I like knowing the source code of every plugin I use well enough so I can troubleshoot it when it breaks (*). I prefer to #include (or, rather, source) them manually. Keeping everything in Github, I rarely need to set up a plugin twice. The effort to install and configure a plugin is usually not a lot more than learning how to use that plugin in the first place.

While being Vundle illiterate may have made my experience a bit more complicated than necessary, I still found the experience of installing autocompletion plugins quite horrible (#). Deoplete had me chasing dependencies all over the place and Conquer of Completion seems to require such specific setup of version and plugins that I didn't even attempt to install it.

YouCompleteMe, though, was a pleasant surprise: its documentation explained how to install in three steps, and it is a mostly self-contained plugin. While YCM has a compiled dependency, setting it up is pretty trivial. It just works out of the box.

Took me years but I'm very happy to finally find an autocomplete plugin that "just works" for my basic Vim setup.

(*) For some reason, I only feel this way about Vim
(#) Disclaimer: Re-reading my own text, it may appear as I'm somewhat belittling Deoplete, CoC, Vundle, Pathogen, etc. That's not my intention. I have the maximum respect for these projects. The engineering effort in them is amazing, and I know for a fact they make life easier for a lot of people. I'm just not one of them.

Tuesday, 28 May 2019

Howto: shutdown a TV with HDMI CEC Chromecast

That's a long title just to say "how to turn off your TV". Only I want to show how to do it even if you lost your remote control.

Chromecast can turn your TV on and off, as long as it supports something called HDMI CEC. Of course the Chromecast itself needs to be powered, i.e. you can't plug it to a USB port in your TV.

The "on" part is easy: you just start casting something (your pictures, for example) and Chromecast automagically turns your TV on. The off part is a bit harder.

Turning off is, obviously, an implemented feature, as the Google assistant can do it. After some Wireshark sniffing, I couldn't find any URL you can call in a Chromecast to turn off the TV. Some people invested more time on this than me, so I assume there's just no simple way to directly use a Chromecast for this. Luckily you can use the Google assistant.

I wrote "simple way". The following maybe doesn't quite qualify as "simple", but it's not too time consuming. It's certainly not elegant, but hey (as of the date I'm writing this article) it works.

How to turn a TV off using a Chromecast

Part 1: Set up the Google assistant SDK

There's no easy way to make a Chromecast turn off a TV, so instead we'll interface with a Google assistant, then ask the assistant to do it for us. There's also no easy way to do this with an API, but the assistant's voice recognition is actually quite good. Let's start by installing the SDK:

  1. Follow the setup instructions for the Google Assistant library, with the changes described below.
  2. The assistant examples need a microphone present, but we're not going to use it. If you don't have one and you're doing this in a RaspberryPi, just fake one by putting this in ~/.asoundrc:
    pcm.!default {
      type asym
      capture.pcm "mic"
    }
    pcm.mic {
      type plug
      slave {
        pcm "null"
      }
    }
  3. The same may be needed for a speaker.
  4. Continue the setup guide: create a project in the Actions console. Register also a dummy model to download the json credentials.
  5. Follow the "Install the SDK and Sample Code" instructions. In May 2019, they work fine in a RaspberryPI 3 with Raspbian.
  6. Try running the sample code. googlesamples-assistant-hotword segfaults but googlesamples-assistant-pushtotalk works fine.

Part 2: Hack the sample to turn off a TV

You should now have the samples from the SDK running. At least those that don't crash. If you have a microphone, you can ask anything you normally ask the Google assistant like... the weather?

The assistant can turn off your TV if you say "Turn off $Chromecast_Name". But what if you don't like talking to your phone?

I'm sure you expect I'll reveal a nice, clean way to invoke the assistant and make it turn off your Chromecast. Sorry, that would take too long. There is a text interface for the assistant but I wasn't able to have it running in less than 15 minutes, so these are your options:

  • Use festival. echo "$Google assistant command" | text2wave -o cmd.wav will generate a command that (often) the assistant can understand. If you don't have such luck:
  • Just record yourself. Hackish? Sure, but if all you need is to shut down a TV, that's enough. Important note: Record yourself in mono 16KHz. Otherwise the assistant may not understand the wav file. If you run "file command.wav" it should look like this:
    command.wav: RIFF (little-endian) data, WAVE audio, Microsoft PCM, 16 bit, mono 16000 Hz

Whatever method you choose, create a wav file with the command you want to execute (i.e. "turn off $Chromecast_name) and put it in the directory where you installed the Google Assistant SDK.

Part 3: Throw your remote to the recycling bin!

You're ready now. Goto the directory where you installed the SDK and recorded your voice command, then try this:

$ source env/bin/activate
$ googlesamples-assistant-pushtotalk --device-model-id $AN_ID_YOU_GOT_FROM_GOOGLE --project-id $YOUR_GOOGLE_PROJECT_ID --once --verbose -i ./command.wav

With a bit of luck that should shut down your TV.

Linkdump:

  • https://developers.google.com/assistant/sdk/overview
  • https://developers.google.com/assistant/sdk/guides/library/python/
  • https://developers.google.com/assistant/sdk/guides/library/python/embed/setup

Tuesday, 14 May 2019

Say nice things

As software developers, we need to put much more emphasis on positive interactions with our peers. Engineering requires critical thinking. Looking for cases where something (code!) will break. Criticizing what we do, on the hope of doing it better, is a key and necessary aspect of our profession. However, even when done properly (already a hard enough job!) this practice emphasizes negative interactions. In a normal job, what would you say is the ratio of times you hear "this might be better if .." vs "I really liked X"?

Saying "this was good" is hard. More often than not, it's hard to even notice good code (and I'd go as far as saying that noticing good things is hard in general!). Unlike criticism, positive interactions don't lead to direct improvements. No code will be enhanced by saying "I liked this solution", though people may be more inclined to considering criticism if the positive aspect is also noted.

In the end, maybe someone just had a slightly better day because you said something nice. That's already a small victory.

Wednesday, 8 May 2019

GCC instrumentation flag: slow everything down!

Here's a nice gcc tip if you think your code is running too fast: instrument everything! (Ok, it may also work if you need to create a profile of your application but for some reason Valgrind isn't your thing).

Compile with

g++ foo.cpp -ggdb3 -finstrument-functions

You can get a list of symbols with nm and c++filt, or you can implement your own elf reader too for extra fun.

extern "C" {
    bool g__cyg_profile_enabled = false;
    stack g__cyg_times;

    void __cyg_profile_func_enter(void *, void *) __attribute__((no_instrument_function));
    void __cyg_profile_func_exit(void *, void *) __attribute__((no_instrument_function));
    void cyg_profile_enable() __attribute__((no_instrument_function));
    void cyg_profile_disable() __attribute__((no_instrument_function));

    void __cyg_profile_func_enter(void *this_fn, void *call_site) {
        if (not g__cyg_profile_enabled) return;
        cout << this_fn << endl;
    }

    void __cyg_profile_func_exit(void *this_fn, void *call_site) {
        if (not g__cyg_profile_enabled) return;
        cout << this_fn << endl;
    }

    void cyg_profile_enable() {
        g__cyg_profile_enabled = true;
    }

    void cyg_profile_disable() {
        g__cyg_profile_enabled = false;
    }
}

int a() {
    return 42;
}

int b() {
    return a();
}

int c() {
    int x = b();
    int y = a();
    return x+y;
}

int d() {
    return c() + b();
}

int main() {
    cyg_profile_enable();
    cout << d() << endl;
    cyg_profile_disable();
    return 0;
}

Friday, 5 April 2019

Chromecastic Slideshow

Plug for a new script I've been working on: https://github.com/nicolasbrailo/ChromecasticSlideshow

Slideshows in Chromecast directly from your filesystem, without going through any online service. No Google Photos, Facebook or anything else: plain old random files straight from your disk to your Chromecast.

Hope someone else finds this useful!

Tuesday, 26 February 2019

VimTip: Search and f(replace)

Pre-tip: When using search and replace in Vim, you don't need to use slashes

This works just fine:

%s#search#replace

Did you know $replace doesn't have to be a literal expression? You can also use Vim functions! For example:

%s#bar#\=line('.')

will replace every occurrence of 'bar' for its line number. You can get creative and use any other Vimscript function.

Tuesday, 2 October 2018

std::byte - great idea. Meh execution?

I love the idea of C++17's std::byte. A data-type that makes it explicit we're dealing with ugly low-level details? What's there not to love! One thing only, turns out.

First, the good part: separating character (human) representation from binary (low-level) representation is brilliant. No implicit conversion between the two separates the domains very well and creates a much clearer interface.

The bad part: std::byte is really really strict. It only accepts other std::bytes as operands(*). You'd hope this would work

auto f() {
  byte b{42};
  return b & 0b11;
}

It doesn't. std::byte only accepts other std::byte's as operands. The design goal behind it is good, sure. In practice, I've noticed this means casts are not limited to the interface between low-level and rest-of-the-world: casts and explicit byte's get sprinkled all over the place.

My prediction: most people will dislike the boilerplate std::byte adds and fall back to unsinged char's, until the type restrictions in std::byte are relaxed. I hope I'm wrong though!

(*) Yes, with the exception of shift operations. That was a good design decision!

Sunday, 30 September 2018

-Wmisleading-indentation

This gcc switch is a few years old but I discovered it recently. I'm not sure if that means my code is always very clean or my toolchain too oudated... in any case, -Wmisleading-indentation (which you get with -Wall) warns about this gotcha:
if (foo)
   bar();
   baz();
Neat!

Tuesday, 4 September 2018

GitHub tip: Prefill a bug report

Getting feedback from users is hard. In a platform such as Android, with apps evaluated in a couple of seconds, it's even harder.

While trying to get bug reports for VlcFreemote I found a neat GitHub trick: you can pre-fill a bug report by using url parameters. For example, check this link: https://github.com/nicolasbrailo/VlcFreemote/issues/new?title=foo&body=bar

Awesome! Takes a second and makes life much easier for bug-reporters!

Sunday, 2 September 2018

Happiest bug report

Something is wrong: I'm happy over a bug report!

A few years back I developed a VlcRemote control app for Android. According to this chart, I didn't actually save any time doing so. The time I spent spent developing the app is more than the cumulative time I would have spent by getting up from the couch and manually controlling VLC. That said, not having to leave the coziness of a warm blanket in winter probably made it worth the investment.

Not long ago I decided to submit this app to F-Droid. I'm too cheap to pay the 20ish dollars for Google App Store, and since I don't have any commercial interest I don't see the point. I didn't think I'd actually get any users there, but today I got my first bug report. So much happiness! You'd think I shouldn't be happy about my crappy software not-working, but hey, someone actually took the time to try it out. Even more, someone cared enough to submit a bug report!

Open source rules!

Friday, 14 April 2017

Geotagging in Ubuntu: more broken than ever

This is depressing. All the geotagging tools in Ubuntu seem dead. Even mine, apparently the latest version of CEF Python changed something that breaks my app. Even worse, looking for "ubuntu geotagging" has my own blog as one of the top results... time to fix my code, I guess?

Wednesday, 18 January 2017

Fixing templates with constexpr's

For my hundredth (and a bit) c++ post I decided to do something I never did before: fix my old code!

A long time ago I wrote about template metaprogramming devices. There, I tried to explain that many atrocities have been commited in the name of performance and "compile time evaluation". Template metaprogramming is probably one of the worse culprits of job security. Its (ab)use can create monstrosities, all in the name of runtime performance. Like, for example, my template device to calculate e. Let's remember what that atrocious code looks like (follow the link if you want an explanation on how this works):

template <int N, int D> struct Frak {
        static const long Num = N;
        static const long Den = D;
};
  
template <int N, typename F> struct ScalarMultiplication {
    typedef Frak<N*F::Num, N*F::Den> result;
};
  
template <int X, int Y> struct MCD {
        static const long result = MCD<Y, X % Y>::result;
};
  
template <int X> struct MCD<X, 0> {
        static const long result = X;
};
  
template <class F> struct Simpl {
        static const long mcd = MCD<F::Num, F::Den>::result;
        typedef Frak< F::Num / mcd, F::Den / mcd > result;
};
  
template <typename X1, typename Y1> struct SameBase {
    typedef typename ScalarMultiplication< Y1::Den, X1>::result X;
    typedef typename ScalarMultiplication< X1::Den, Y1>::result Y;
};
  
template <typename X, typename Y> struct Sum {
    typedef SameBase<X, Y> B;
    static const long Num = B::X::Num + B::Y::Num;
    static const long Den = B::Y::Den; // == B::X::Den
    typedef typename Simpl< Frak<Num, Den> >::result result;
};

template <int N> struct Fact {
    static const long result = N * Fact<N-1>::result;
};
template <> struct Fact<0> {
    static const long result = 1;
};
 
template <int N> struct E {
    // e = S(1/n!) = 1/0! + 1/1! + 1/2! + ...
    static const long Den = Fact<N>::result;
    typedef Frak< 1, Den > term;
    typedef typename E<N-1>::result next_term;
    typedef typename Sum< term, next_term >::result result;
};
template <> struct E<0> {
    typedef Frak<1, 1> result;
};
 
int main() {
  typedef E<8>::result X;
  std::cout << "e = " << (1.0 * X::Num / X::Den) << "\n";
  std::cout << "e = " << X::Num <<"/"<< X::Den << "\n";
  return 0;
}

While this is just a toy example to play with templates, it does illustrate code I've seen in the wild. Would this look cleaner in c++11? Yes, it would. Constexprs are, in my opinion, one of the most overlooked "killer" features of c++11.

Starting with a simple example:

constexpr int foo(int a, int b) { return a+b; }
static constexpr int n = foo(1, 2);
int bar() { return n; }

Try to compile it with "g++ -std=c++11 -fverbose-asm -O0 -c -S -o /dev/stdout" and see what happens. You should get the equivalent of "return 3" - just as anyone would expect - but note that no optimizations were enabled. What about loops? Let's try this:

constexpr int f(int n) {
    return (n<2)? 1 : n + f(n-1);
}

constexpr int n = f(999);

You'll probably get an error about maximum depth exceeded, but that's alright: we have loops in constexprs too! (note that some of these restrictions have been relaxed in C++17).

In general, if you can express your function as a single const return statement, it should be a valid constexpr. With this new knowledge, let's convert the template meta-atrocity above to something a bit less hideous:

struct PodFrac {
    int num;
    int den;
};

constexpr int mcd(int a, int b) {
    return (b==0)? a : mcd(b, a%b);
}

constexpr PodFrac simpl(const PodFrac &f) {
    return PodFrac{f.num / mcd(f.num, f.den), f.den / mcd(f.num, f.den)};
}

constexpr PodFrac sum(const PodFrac &a, const PodFrac &b) {
    return simpl(PodFrac{a.num*b.den + b.num*a.den, a.den*b.den});
}

constexpr int fact(int n) {
    return (n==0)? 1 : n*fact(n-1);
}

constexpr PodFrac e(int n) {
    return (n==0)? PodFrac{1, 1} :
                   sum(PodFrac{1, fact(n)}, e(n-1));
}

constexpr float e_num = 1.0 * e(8).num / e(8).den;

float get_e() {
    return e_num;
}

Disclaimer: while I explicitly stated this multiple times in my "C++ template metaprogramming introduction" article, it's worth re-stating it: this code is meant as an example to showcase a c++ feature, not as a proper way of deriving a mathematical constant in production code.

First thoughts after comparing the two versions: much, much [, much]*100 cleaner.

As you may notice, all constexprs need to be a return statement. There's no multi-statement constexpr in c++11, which explains why loops are not really supported. For the same reason the implementation of e() is a bit hindered by this limitation: its code would be much more readable splitting it in a few lines with proper names. Good news: some of these restrictions have been relaxed in C++17.

Note that if you analyze your compiler's output when building without optimizations, you may see either a const with e's value, or a static initializer that does some trivial operation, like loading e's value from a fraction: gcc seems to get tired of constexpr evaluation after a few recursive calls, so your results may vary (slightly).

I called constexpr's one of c++11's killer features, and hopefully you can see why I'm so enthusiastic about them now: there's much less incentive for people to write horrible template metaprogramming devices when simply adding a little keyword to a normal function has the same effect, only cleaner.

Wednesday, 4 January 2017

Quick refresher: argument dependent lookup

Since I wasted a few precious minutes stuck on an ADL problem, I figured I needed a quick reminder on how they work. Check this code: does it compile?

namespace N {
    int foo() {
    }
}

int main() {
    return foo();
}

Of course it doesn't! You'd expect a 'foo' not declared/out of scope error from your compiler. What about this other example?

namespace N {
    struct Dummy;

    int foo(Dummy*) {
        return 0;
    }

    int foo() {
    }
}

int main() {
    return foo((N::Dummy*)0);
}

You'd be tempted to say it won't work either. (Un?)fortunately, 'argument dependant lookup' is a thing, and the second code sample works. How? The compiler will look for 'foo' in the global namespace, and also in the namespace of the arguments to 'foo'. Seeing 'N::Dummy' in there, the compiler is allowed to peak into the namespace N for method 'foo'. Why? Short: operator overloading. Long: check here (the 'Why ADL' section is very good).

Wednesday, 21 December 2016

Google Test: Quarantine for tests?

Google Test: Putting a test under quarantine

GTest works wonders for c++ testing, even more so when combined with GMock. I've been using these frameworks for a few side projects. I've seen them used in large scale projects too. In all cases, there is a very common problem for which (I think) there is no elegant solution: managing temporarily disabled tests.

It may be because you found a flaky piece of code or a test that exposes a heisenbug. Maybe the test itself is just unstable, or perhaps you are using TDD and want to submit a test to your CI before its implementation is ready. In these cases, you can choose to disable the offending test or let it run, possible halting your CI because of it. When that happens, you maybe masking other, real, problems.

Most people would stick a "DISABLED_" before the test name, to let GTest know not to run it. Maybe even stick a "// TODO: reenable" in there too. When run, GTest will generate a message to let you know there is a disabled test. Even so, I find that people -myself included- tend to forget to re-enable the disabled tests.

For one of my side projects, I hacked GTest to quarantine tests up to a certain date:

TEST(Foo, Bar) {
    QUARANTINE_UNTIL("16/8/22");
    EXPECT_EQ(1,2);
}

In my CI setup, that test will be showing a happy green (and a warning, which I will probably ignore) until the 22nd of August. By the 23rd the test will run again and fail if I haven't fixed the code. If I have indeed fixed it, it will print a warning to remind me that it's safe to delete the quarantine statement.

Is there any advantage in this approach over the usual _DISABLE strategy? In my opinion, there is: if you ignore warnings in your test, for whatever reason, a _DISABLE might go unnoticed and it may hide a real problem. In the same scenario, for a quarantined test, nothing bad happens: the warning just says "you should delete this line" but the quarantined test is again part of your safety net.

How does it work? The first caveat in my article mentions it: hackishly. There are a few facilities missing in GTest to make this implementation production-ready but, ugly as it looks, it should work as intended:

#include <ctime>
#include <string>
#include <sstream>
std::string now() {
    time_t t = time(0);
    struct tm *now = localtime(&t);

    std::stringstream formatted_date;
    formatted_date << (now->tm_year+1900) << '/'
                   << (now->tm_mon+1) << '/'
                   << now->tm_mday;

    return formatted_date.str();
}

#define QUARANTINE_UNTIL(date_limit)                                     \
        if (now() < date_limit) {                                        \
            GTEST_LOG_(WARNING) << "Test under quarantine!";             \
            return;                                                      \
        } else {                                                         \
            GTEST_LOG_(WARNING) << "Quarantine expired on " date_limit;  \
        }

If I find there is interest in this approach for real world applications, I may try to come up with a nicer interface for it.

Wednesday, 14 December 2016

Vimcrypt

Have you ever been working on your plans for world domination but got scared someone else might find them? It happens to me all the time. Or maybe you are so paranoid that you need to encrypt your grocery list. Perhaps you are sharing a semi-private text file through a public service? Good news, Vim has you covered. Just type ":X". Vim will ask you for a password. Save your file again and voila, your file is now encrypted. Open the same file with Vim to decrypt it. Your plans for world domination are now safe!

Thursday, 8 December 2016

Things you should never do

I think I may start a new series in my "Rants" category: things you shouldn't do. First one: Never ever use "strange" characters on your wifi's AP name, where strange is defined as non-ascii. I made the huge mistake of choosing a name with an ñ on it, then had to spend an entire evening hacking on a printer driver with no unicode support. No, I couldn't have changed the AP's name. That would have required me to physically connect a computer to my router, and I was too lazy to get up from the couch.

Tuesday, 6 December 2016

Self reminder: setting the default boot option in UEFI

Bought a new laptop (*) and I'm 100% sure I'll forget this if I don't put it here:

From http://askubuntu.com/questions/291905/how-can-i-make-ubuntu-the-default-boot-option-on-a-newer-laptop-uefi

To set Ubuntu as the default boot OS in a multi-OS setup (ie, dual boot Windows) with UEFI, goto Windows and exec (as admin) bcdedit /set {bootmgr} path \EFI\ubuntu\grubx64.efi

Why am I using Windows, you may ask? I'm still in the process of discovering which features will be broken and which hardware will work out of the box. So far I'm actually quite surprised, with only the video card and the touchpad not working. Luckily bash doesn't use either of those. Who needs a mouse anyway?