reality is bullshit


20160319
do not install cpanm using the package manager on a debian server, then run this trying to port your installed modules list to a new install of perl:

perlbrew list-modules | perlbrew exec --with perl-5.22.1 cpanm
... at least not before you have installed App::cpanminus using 5.22.1's cpan and sourced perlbrew in your .bash_profile.

may be able to supply the full path to 5.22.1's cpanm too, but i didn't try that.
20150808
what do you call it when sleeping is a job and a half?

a high turnover rate.
20150506
"All along I said, 'You're crazy.' The PDP-11's a great Lisp machine. The PDP-10's a great Lisp machine. There's no need to build a Lisp machine that's not faster. There was just no reason to ever build a Lisp machine. It was kind of stupid." ken thompson in coders at work

moore's law means that attempts to compete against general-purpose tools with special-purpose tools are doomed. the only tool better than a sledgehammer is a bigger sledgehammer.

"Programmers waste enormous amounts of time thinking about, or worrying about, the speed of noncritical parts of their programs, and these attempts at efficiency actually have a strong negative impact when debugging and maintenance are considered. We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil." donald knuth, 1974 turing award lecture

people, programmers included, can't seem to stop thinking about things. sometimes, that's a problem. our machines are our extensions, but they are not like us. the beauty of our imagination does not make the jump. a machine cannot be designed to be imaginative. there is joy in designing a beautiful machine, and the work has value for that reason. but a machine is not good because it is beautiful. a beautiful machine has value only to those who like designing machines.



a lot of times we think that we can figure out a better solution—we think that being clever is helpful. a lot of times we are wrong.

it's good to think about things. it's good to wonder. but sometimes we become attached to ideas: we can't stop being human when it's no longer helpful.

"that which we desire we readily believe." i'm a skeptic, so i'm attracted to laziness, naivete, docility. i want to agree with those who say "you don't need to think."

but my bias notwithstanding, it is sometimes the best way—to let the machine be a machine, to make it mindless and brutal.
20150113
quick quiz: what is the output of the below program? yes or no?

#include <stdio.h> class A { public: int *get_address() { static int variable; return &variable; } }; int main() { A one, two; if (one.get_address() == two.get_address()) { printf("yes\n"); } else { printf("no\n"); } }
until today, i thought the answer was different.
20150110
i want an Encoder interface (in the java sense of the word) so i don't have so much duplication passing around video encoders, audio encoders, etc. an encoder is just something that takes in data and outputs data in another format. it should be possible to implement this in a generic way if the language is up to snuff.

a lot of times encoders block while doing their work so i want to put them in their own threads. in qt c++ you can communicate with objects in other threads without worrying about the concurrency usual suspects by using signals and slots.

so i want an Encoder interface that uses signals and slots.

#include <QObject> #include "devicedata.h" class Encoder : public QObject { Q_OBJECT public: explicit Encoder(QObject *parent = 0) : QObject(parent) {} ~Encoder() {} signals: virtual void encoded_data(DeviceData) = 0; public slots: virtual void open(DeviceData devicedata) = 0; virtual void encode_data(DeviceData devicedata) = 0; virtual void stop() = 0; };
so far so good. but compiling this results in a warning:

Signals cannot be declared virtual
it makes some sense if you think about what signals really are (i.e. their implementation is left to the moc).

okay fine, whatever, comment out the "signals:" line, and we compile without a warning.

but when something tries to connect() to the signal using the new syntax at runtime we get:

QObject::connect: signal not found in Video_Encoder
Video_Encoder of course being the class that implements the Encoder interface. so are we out of luck for an interface that describes signals?

not quite. although the new syntax is not working:

connect(encoder, &Encoder::encoded_data, [this](DeviceData encoded_data) { /* whatever */ });
... the old syntax works fine:

connect(encoder, SIGNAL(encoded_data(DeviceData)), this, SLOT(my_slot(DeviceData))); [...] void MyClass::my_slot(DeviceData encoded_data) { //whatever }
so we can have what we want—sort of. we have to use the old connect() syntax, and that means no nice lambda. why? because comparing pointers to member functions to virtual functions is unspecified. so qt can't compare &Encoder::encoded_data to our virtual "signal" implemented by Video_Encoder.

thanks, c++! dat feel when the best is not good enough.
20140408
a word to the wise: function-static objects are not thread safe before c++11.
20130806
finally, i am successfully signing windows executables under mac os x.

first, install mono. trust me—it's worth it.

in order to use mono's signcode tool you will need your authenticode key in pvk format and the associated certificate in spc format. if you have a pfx file originally from e.g. globalsign (perhaps exported from your windows certificate store) you can convert it like this (note that i install a newer version of openssl than comes with mountain lion in order to complete the series of steps originally found here):

openssl pkcs12 -in 2nd_try.pfx -nocerts -nodes -out authenticode.pem brew install openssl openssl="/usr/local/Cellar/openssl/1.0.1e/bin/openssl" $openssl rsa -in authenticode.pem -outform PVK -pvk-strong -out authenticode.pvk $openssl pkcs12 -in 2nd_try.pfx -nokeys -out authenticode.cert $openssl crl2pkcs7 -nocrl -certfile authenticode.cert -outform DER -out authenticode.spc
you will have to enter the password you supply here every time you sign something. on top of that, mono's signcode binary echoes your password to the screen as you enter it. yes, really. i wasn't able to figure out how to avoid password entry with mono's signcode—it seems to prompt even if the private key is not password-protected, and it does not accept a blank password. as a workaround i wrote this script:

#!/bin/bash if [ $# -ne 3 ] ; then echo "usage: $0 prettyname url exefile" exit 1 fi cd /e || exit "can't cd" read -s -p 'Signing password: ' password echo echo $password | signcode -spc authenticode.spc -v authenticode.pvk -a sha1 -$ commercial -n "$1" -i "$2" -t http://timestamp.verisign.com/scripts/timstamp.dll -tr 10 "$3"
you still have to enter the password, but at least it isn't echoed to the screen now. enterprising individuals may discover a way of modifying the above script to avoid having to enter the password every time they sign something, but i do not believe that storing a password in cleartext is a particularly bright idea. perhaps the apple keychain api could be enlisted to store it instead.
20130624
time for "spot the bug":

01 QSqlQuery select_query; 02 select_query.prepare("select data from frames where frame_number = :frame_number"); 03 04 int out_image_width = blocks_wide * block_width; 05 int out_image_height = blocks_tall * block_height; 06 QImage out_image(out_image_width, out_image_height, QImage::Format_ARGB32); 07 out_image.fill(Qt::white); 08 QPainter painter(&out_image); 09 10 QHash<int, QImage> framenumber_frame; 11 QHashIterator<int, int> i(blocknumber_framenumber); 12 while (i.hasNext()) { 13 i.next(); 14 15 int block_number = i.key(); 16 int frame_number = i.value(); 17 18 int x = block_number % blocks_wide; 19 int y = block_number / blocks_wide; 20 21 QImage frame_image; 22 if (framenumber_frame.contains(frame_number)) { 23 frame_image = framenumber_frame[frame_number]; 24 } else { 25 select_query.bindValue(":frame_number", frame_number); 26 select_query.exec(); 27 int fieldNo = select_query.record().indexOf("data"); 28 select_query.next(); 29 QByteArray data = select_query.value(fieldNo).toByteArray(); 30 QImage frame_image = QImage::fromData(data); 31 frame_image = scaler.scale(frame_image, block_width, block_height); 32 framenumber_frame[frame_number] = frame_image; 33 } 34 35 painter.drawImage(block_width*x, block_height*y, frame_image); 36 37 if (framenumber_frame.size() > 100000) framenumber_frame.clear(); 38 } 39 40 painter.end(); 41 out_image.save("/Users/njahnke/Desktop/out.png");
need a hint?

look at line 30.
20130506
c++11 is here. haters gonna hate.

of course, most (all?) of the functionality was already present in qt.

lambdas are useful. i'm also a perl programmer, so i like functions as first-class guys. the situation's always been considerably less elegant in c++: lurking below the surface is the vague specter—the awesome shadow—the cruel lord, the pointer to a member function.

i've been chewed on by pointers to member functions many times, but this time was a little different in that i actually succeeded in the end.

here's what happens when you press ctrl-s in yua:

void Yua::screenshot_save() { if (screenshot_image.isNull()) return; QString out_path = QDesktopServices::storageLocation(QDesktopServices::DesktopLocation); QString out_name = "yua"; QString out_ext = "png"; QString out_filename = "/"; //this should always exist (20130411) int i = 1; QString i_string = ""; while (QFileInfo(out_filename).exists()) { out_filename = QString("%1/%2%3.%4").arg(out_path).arg(out_name).arg(i_string).arg(out_ext); ++i; i_string = QString("%1").arg(i); } QByteArray png_string = "PNG"; const char *png = png_string.data(); //can't pass a string constant to QtConcurrent::run() as an argument, at least under gcc 4.2 (20130412) QImage out_image = screenshot_image.copy(); //in case they move the slider while we're still saving the image (20130412) QtConcurrent::run(out_image, //this takes a while so we do it asynchronously in another thread (20130412) static_cast<bool (QImage::*)(const QString &, const char *, int) const>(&QImage::save), //cast is required to distinguish between the other QImage::save() overload (20130412) out_filename, png, 0); }
i have to specify the output image format ("PNG") explicitly in order to reach the third argument to QImage::save(), the compression level, which i set to the maximum possible (0—because it's small—get it?) in order to pre-emptively save space on my database server when people post their screenshots on the sda forum.

i learned that i needed the cast to get the right overload of QImage::save() fairly early on, but at that time i still had the second to last argument to QtConcurrent::run() as an inline string literal "PNG" instead of a pointer to equivalent data. with it this way attempting to compile yua with clang yielded:

In file included from ../Yua/yua.cpp:1: In file included from ../Yua/yua.h:4: In file included from /Library/Frameworks/QtGui.framework/Versions/4/Headers/QtGui:3: In file included from /Library/Frameworks/QtCore.framework/Headers/QtCore:62: In file included from /Library/Frameworks/QtCore.framework/Versions/4/Headers/qtconcurrentrun.h:51: /Library/Frameworks/QtCore.framework/Headers/qtconcurrentstoredfunctioncall.h:759:46: error: array initializer must be an initializer list or string literal : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2), arg3(_arg3){ } ^ /Library/Frameworks/QtCore.framework/Versions/4/Headers/qtconcurrentrun.h:264:17: note: in instantiation of member function 'QtConcurrent::StoredConstMemberFunctionCall3<bool, QImage, const QString &, QString, const char *, char [4], int, int>::StoredConstMemberFunctionCall3' requested here return (new QT_TYPENAME SelectStoredConstMemberFunctionCall3<T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3>::type(fn, object, arg1, arg2, arg3))->start(); ^ /Library/Frameworks/QtCore.framework/Headers/qtconcurrentcompilertest.h:57:23: note: expanded from macro 'QT_TYPENAME' # define QT_TYPENAME typename ^ ../Yua/yua.cpp:2137:9: note: in instantiation of function template specialization 'QtConcurrent::run<bool, QImage, const QString &, QString, const char *, char [4], int, int>' requested here QtConcurrent::run(out_image, //this takes a while so we do it asynchronously in another thread (20130412) ^
... right then. clang++ and clang++ operating in g++-4.2 mode under os x 10.8 both choke in this way. googling got me to some gcc bug that made me think about it enough to try passing in a pointer variable instead and suddenly, bam, working. almost like perl! or javascript! or another niche language. but, because it's c++, it's long and scary unless you know what you're looking at.

function comes before form for me here, though. i was nearly sure going in that i was going to have to write a class just to execute that one line in a thread and sprinkle thread control code in the usual two or three places throughout yua.cpp.

nope. not this time.
20130417
software is becoming less and less programmer-centered. as a programmer today i can still say "oh, the system won't allow me to implement that feature," but i do that at my own peril. unless it's a microsoft product, you as a user probably have a choice, and you're not going to choose my lazy ass's software when my competitor has a harder-working programmer on staff. it's a race to the top. all other things equal, users win and programmers lose.

now even microsoft is falling, and i have to maintain at least three different versions of my desktop software (mac os x intel 64-bit, linux intel 64-bit, windows intel 32-bit). at first glance, this seems trivial: write everything in qt c++, and when you have to go outside of qt c++, maintain standard build systems for your external libraries. pretty much everything compiles with mingw, so windows is not an obstacle here. and using virtual machines, you can do everything on a single workstation.

the trouble begins when it's time to deploy the software. the three operating systems each have their own conventions for loading dynamically-linked libraries, but for this post i'm going to concentrate on code signing, as it has proven far more challenging for me.

i'm not actually sure who started it, but apple and microsoft now both require signed binaries in certain cases: apple for programs available in its mac app store and microsoft for device drivers under the 64-bit versions of its operating systems. i don't care about the mac app store right now, but its reach extends in os x 10.8 even to programs users download from other sources: the default "gatekeeper" system setting only allows unsigned code to execute if the user right-clicks on the application bundle and chooses "open" from the context menu—something no perpetual intermediate user would ever think to try.

similarly, even though code signing is not technically required for windows userspace programs to run as of windows 7, the operating system warns the user on launch that the chosen program is unsigned and might not be from a reputable source. this is unacceptable in the business world. so code signing is really required under windows as well as os x. linux remains the last holdout of what some would call democracy on the desktop. but those who call it that are all developers. it's not the user's problem if the software doesn't run.

i received a code signing certificate (in the windows world sometimes called "authenticode") from my employer for signing our device drivers for users of 64-bit windows. this is a fairly standard security certificate from a fairly standard provider; i was able to use it also to sign my os x binaries using apple's commandline "codesign" tool under os x 10.6.

recently, i upgraded to a new system at home, and i elected to run os x 10.8 on it. in some ways, the transition wasn't as rough as i had anticipated—i discovered that i could disable inverted mousewheel scrolling and restore functionality to exposé by unchecking "group windows by application" in the mission control system preference panel. even compiling and installing qt was fairly straightforward. but i was not able to use my code signing certificate to sign my os x binaries—codesign -s "my company name here" path_to_bundle resulted in a "my company name here: no identity found" error, the exact same error one receives if "my company name here" is not associated with a certificate in their keychain. i was careful to import all of the required intermediate certificates; indeed, my code signing certificate displays with a green checkmark and a "this certificate is valid" message when viewed in my keychain.

researching the problem, i eventually located an assertion on a blog that one must now purchase a code signing certificate via apple in order to sign binaries under os x 10.8. certificates meant for microsoft authenticode no longer "work." i haven't been able to uncover the technical reason—it may be that the system only considers chains with apple-issued intermediate certificates valid for the purpose of signing code. registering as an apple developer to receive a certificate from apple is only $100 or something—the price is not what deters me. what deters me is that it was possible under os x 10.6 to purchase a single certificate from a single provider and to sign both windows and mac binaries with that certificate. very rarely does any of apple's stunts provoke anger from this lifelong mac user, but this one did.

after further consideration, i'm pretty sure i know why. apple, of course, is no different from microsoft. they are a fundamentally self-interested entity. and to argue with that is like arguing with the sun rising. but times are changing. at the risk of sounding like a determinist, no one can stop the advance of ~progress~—whatever that might mean in our postmodern world. right now, it means that programmers and their beloved ecosystems are less and less important. as i said near the top of this entry, if i don't release my software for windows, then someone else will. there is no such thing as "mac software." in truth, there never was, but hindsight is what they say it is. qt 5 is here for android and ios. when people think of "walled gardens," they think of ios, but that is not true. i simply found out the truth before they did.

i can't blame people for failing to pick up on it, because it's a convoluted situation fraught with emotional pitfalls. it's easy to hate apple or microsoft or whoever for doing the things they do, and then that hatred leads to substandard analysis. for example, people often say that apple wants to maintain control of their platform (ios/os x). one way of controlling the platform is to create a unified api that everyone writing software for that platform uses. from here it's easy to reach the illogical conclusion that apple will not allow software written using a different library to run on their platform. yet it is trivial to falsify. there are qt apps on the app store, and java (even though it gets disabled every few days due to security problems) continues to be available with a single-click install on os x 10.8. apple, for whatever reason, will not take the final step toward a truly closed system. it's true that they assume that you're only developing your software for their platform—an overly optimistic assumption from my perspective, but not one that is totally out of touch with reality ... for now.

i don't know whether their reluctance to create a truly closed system has anything to do with steve jobs, but i imagine that he was eager to adopt what seemed to him to be good ideas (two that come to mind are xerox parc's "contributions" to the classic mac os and carnegie mellon's for os x). if qt, for example, were that much better than cocoa, then cocoa would become more like qt. but without qt on os x, there would be no way to see, deep within the bowels of apple, that something better had come along. perhaps jobs was leery of the isolation and mediocrity that befell apple after he was forced out of the company he had founded. i imagine him welcoming someone like me—a pirate, without allegiance to any platform. i'm a power-hungry perfectionist. i struggle with things when i don't have to. i go where the good stuff is. so i am a better judge of what is good than a "mac user."

but that's just my speculation. to summarize: in blocking authenticode certificates from being used for code signing on their platform, apple became more like microsoft. as a programmer i am now working against the interests of not just microsoft but apple as well. even though i am ahead of the curve, life is getting harder for me.

i was depending on apple more than i should have been. maybe it's that simple.

i'm not planning on moving to linux anytime soon—it's probably a separate question anyway, which desktop operating system i prefer. but it means that i have to keep my old 10.6 machine around to deploy my software or else submit to apple's process and pray that a bundle signed on 10.8 will work on 10.6.

there's no guarantee.