HNHacker News
TopNewBestAskShowJobs

apankrat

984 karma · joined March 25, 2010

https://swapped.ch
submissionscomments
apankrat··on Show HN: P2P remote desktop – an alternative to TeamViewer / AnyDesk
The NAT traversal logic here is really basic and won't hold up well in practice.

A good chunk of NAT devices will pick external port based on [src ip/port, dst ip/port] combo, not just [src ip/port], so "WAN IP/port" you get from STUN will get you nothing useful. Not by itself.

STUNs should be used for discovering the pattern in NAT port overloading logic and then using it to predict which port your peer will use towards you if you were to try and connect now.

That is, you need to know the overloading pattern and then also time stuff correctly.

For that reason you will need a rendezvous server and it's also the best to let the server drive the whole process (as opposed to what STUN-based setups do, which is to let clients do it).

PS. In my past life I made a P2P VPN called Hamachi, which used all this stuff very extensively.

apankrat··on Every pricing page should have GIFs
If you are selling an UI option, a screencap is pretty much a must.

If you are selling non-UI options, simple click-to-view explainers go a long way too, e.g. https://backup2.com/features

apankrat··on Show HN: μGiffer
Cheers, thanks.

I completely forgot about LiceCap! Notable option of a very good provenance. Still a bit too much UI for my taste :)

apankrat··on Show HN: μGiffer
As a part of my work, I do UI/UX design for our products and post some snippets of the process to the development blog. Being able to show things _in action_ is a must, but I couldn't find a tool that was convenient for doing multiple back to back screen captures of the same sequence. Record, review, tweak this, change that, record again, review, rinse and repeat. Captures are short, so they must be perfect, so it usually takes a dozen of tries to get them right.

So I made a tool for the job. It is tailored to this specific workflow, but I think it's generic enough to be useful in other cases too.

I thought it'd be complicated, but it turned out to be dead simple - get the device context of the desktop, bitblt it on timer to a bitmap, draw the mouse cursor, see if it changed from the last time, save to the disk. Once the capture is done, go through the images and pack them into a GIF. The rest is just some UI work, to make things convenient, but out of the way at the same time.

For the reference, GifCam [1] was close, but it has palette encoding issues that create visible artifacts in the output. ScreenToGif [2] is a .Net app, asked to install 4.8, that asked to reboot the computer, etc. It also comes with a lot of extra stuff (it has a ribbon-style menu bar!) and requires quite a bit of clicking to get things done. Others were even worse off in comparison. So, as per usual, you want things to be done your way, you do it yourself.

[1] http://blog.bahraniapps.com/gifcam

[2] https://www.screentogif.com

apankrat··on Fast character case conversion, or how to really compress sparse arrays
Ha, indeed! Should've compressed the index too though :-P
apankrat··on Fast character case conversion, or how to really compress sparse arrays
You want a benchmark that shows that one >>, one &, two [] and a + are going to be fast?

The test loop that wraps the lookup code will likely take as much CPU as what's being benchmarked. Even if you are to use RDPMC and even if you are to use it very sparingly.

apankrat··on Fast character case conversion, or how to really compress sparse arrays
Say, we have our N blocks. We make these into the nodes in a graph. Every node is connected to all other nodes.

An edge leading from A to B is a case when block A precedes block B. The weight of that edge is the AB overlap. Note that the same edge may have a different weight in the opposite direction, because it will be that of the BA overlap.

So what we are after is the heaviest path through this graph that passes through all nodes exactly once. This can be reduced to finding the heaviest cyclic path for a specific starting point (and excluding the cheapest edge from the solution and then iterating through all points). This is pretty much TSP with an inverted goal.

apankrat··on Fast character case conversion, or how to really compress sparse arrays
Spotted the packing technique in the Wine's code and killed few days to see how much further it can be taken. Pretty much one of those rabbit holes that you'd occasionally run into in a course of regular programming and end up exploring instead of, you know, working. A good diversion, I suspect quite a few people can relate :)
apankrat··on Kanban board in one HTML using localstorage
See my reply here - https://news.ycombinator.com/item?id=26152103
apankrat··on Kanban board in one HTML using localstorage
It was written when I needed a kanban board done to my specs in a minimum amount of time using whatever things I was most comfortable with.
apankrat··on Kanban board in one HTML using localstorage
For this to happen the storage "module" needs to be redone and cleaned up, which in turn requires having a couple of free weekends and these are hard to come by.

That said, if you will get to the point of doing anything with an aim of submitting a pull request - do ask me first. Chances are that it will take a very long time to accept the request, because that too requires a weekend to review.

apankrat··on Kanban board in one HTML using localstorage
This is mine.

It is something I wrote for my own use after looking at all existing options and finding them not to my liking. This is pretty much a weekend hack, it is from 2019 and it's still close to what I need. When I have time I plan to improve keyboard support, add color tags and archiving of completed items. It will also be redone to not use localStorage and to support a remote storage option. Shared use (with 2+ instances working with the same copy of the data) is also something that I'd like to do, but that's on a back burner.

The Show HN post from 2019 - https://news.ycombinator.com/item?id=20077177

apankrat··on Ask HN: What is your “I don't care if this succeeds” project?
Dead-simple GIF screen recorder for Windows - https://gist.github.com/apankrat/14b28656236d78407b28aef3102...

Real-time disk IO graphing thingy - https://bvckup2.com/wip/10042018

Both can be developed into proper products, but that'd be beyond what I actually need from these two for myself.

apankrat··on ECC matters
Aye. I have an assert in the code that fronts a very pedantic test of the context. In all cases when this assert was tripped (and reported) an overnight memtest86 test surfaced RAM issues.

- Edit -

Also, bit flips in the non-ECC memory are _the_ cause of the "bitrot" phenomenon. That is when you write out X to a storage device, but you get Y when you read it back. A common explanation is that the corruption happens _at rest_. However all drives from the last 30+ years have FEC support, so in reality the only way a bit rot can happen is if the data is damaged _in transit_, while in RAM, on the way to/from the storage media.

So, if you ever decide if to get an ECC RAM, get it. It's very much worth it.

apankrat··on Ask HN: What's a side project you built to make money that hasn't?
Digital time-stamping service called CertTime.

Here's the post-mortem - https://swapped.ch/certtime

apankrat··on C Template Library
Oh, well, good for it.

If I were to pick the reason, it'd be simply that I don't like Boost.

To me, Boost is an ultimate embodiment of all that went wrong with C++ when it evolved from being a better version of C into the multi-paradigm monstrosity that it is now. Just look at the man page linked above. How to get a clever little concept of intrusive containers and completely decimate it into a technically correct, but unpalatable formulistic piece of engineering that, above all else, is rid of any shred of elegance that made the original concept so great in the first place.

apankrat··on C Template Library
The reason is that the goal is not achievable using boost contraptions. At the very least it's not possible to use boost version without inheritance.

As to why to do what you wrote I have no idea. These two code snippets are unrelated.

apankrat··on C Template Library
It does, in the exact same sentence.
apankrat··on C Template Library
The post I linked to mentions it explicitly.
apankrat··on C Template Library
Nice, very nice. All of it. Long live C.

Being stuck with C++ I did something in reverse - ported C-style ("intrusive") containers to ++, making them a bit safer to use, but keeping the syntax nearly the same.

https://github.com/apankrat/notes/tree/master/intrusive-cont...

apankrat··on A Defer Mechanism for C
This will break the ABI indeed. That's given.
apankrat··on A Defer Mechanism for C
Every defer statement is ultimately pushing a lambda into some stack that is executed when the defer block is exited. With an exception of setjmp/longjmp, I can't think of an existing C construct with similar run-time complexity.
apankrat··on A Defer Mechanism for C
Aye, I've seen that.

IMO it would've been better (read, cleaner) to merge lambdas and function pointers into a single language construct. Throw in the partial application too and we'd be have a natively supported concept of a "callable" instance -

  void foo(int tick);
  void bar(int tick, int tock);

  void do_something( void (* progress)(int tick) );

  do_something( foo );
  do_something( bar(,1) );
  do_something( void (int tick) { /* lambda */ } );
The syntax is approximate, but for the code that is using callback-based flows this would've been very handy.
apankrat··on A Defer Mechanism for C
Re: Should object values be captured?

The results from 387 responses (to a Twitter poll) show a 2:1 preference for the value being read at the time the deferred statements are executed (66.9%) rather than when the defer statement encountered(33.1%).

Since both options - by value and by reference - may be viewed as reasonable or desirable, neither should be a default. Instead, they both should be using a special syntax. So if you write something likes this -

  guard {
    void * p = malloc(...);
    defer free(p);
  }
it simply won't compile. Instead you'd need to say something like this -

  guard {
    void * p = malloc(...);
    defer free(^p); // evaluate now
  }

  guard {
    void * p = malloc(...);
    defer free(p^); // evaluate later
  }
This may also be reused later for specifying lambda captures... should lambdas ever make their way into C.
apankrat··on Ask HN: Why do some timestamps on HN have a full stop at the end?
Just take it out of the <a> element and add a tooltip to it.

The pedants will inspect the source code first before asking.

apankrat··on What is your favorite C programming trick? (2009)
Ha, indeed. I had no need to use it with either, so I didn't bother to check. MSVC was the compiler.
apankrat··on What is your favorite C programming trick? (2009)

    #ifdef _DEBUG
    #define __REVIEW_ME      / ## / 
    #else
    #define __REVIEW_ME      $review_me$
    #endif
When reworking a large amount of code, this can be used to tag places that may need another pass or a review. The debug version will build fine, but the release won't until all review tags are removed.

This also allows adding free form comments if needed:

    foo += 13;    __REVIEW_ME -- why 13 ?!
apankrat··on File Descriptor Transfer over Unix Domain Sockets
FD transfer is also used when a process needs to work with files (or devices) that are out of its reach due to the account restrictions.

In this case, the process will talk to another process that does have required access, the latter would open the file of interest and pass the handle back.

This is needed very rarely, but in cases where it's a good fit, it provides a very elegant and simple solution for an otherwise hairy problem.

One such case is when the program uses an Engine + UI model, whereby the engine runs under a system account and the UI is under an interactive user. As the engine runs, it writes logs and the UI needs to display them. So one solution is to tweak permissions on the log files to make them universally readable. It's not hard to do, but it makes the whole thing more fragile - these permissions may get inadvertently stripped off, the UI process may be sandboxed by an antivirus, etc. That is, the program may end up in a state when the UI cannot access the logs, but the engine can.

The alternative here is for the UI process to ask the engine to open the logs and pass the handles back. Very simple to do and resistant to accidental breakage.

Another case was when we had to ship a pre-built Linux binary (a VPN client) that needed to open a TAP device. The latter normally requires a root access, but the client was closed-source, so it had to be able to run under restricted user accounts, because asking people to run it under the root was not an option. The solution was to make a small open-source daemon that listened on a domain socket for requests to open /dev/tapx, did that and passed tap FDs back to the requesting process.

apankrat··on Pianojacq, an easy way to learn to play the piano
Re: a virtual midi device - I don't know the specifics of WebMIDI, but I'd think it should be rather trivial to code on top of any pitch detector, including mine. In terms of licensing - the code is already BSD-2.

Re: the another note - yes, indeed. I too realized this, because mis-detected notes are usually off by a full octave.

As a side note, after going reading through various papers on the subject, it would seem that an ultimate note detector should really be based on a Const-Q spectrum analyzer feeding into an NN. Training the net, even from scratch, can be as simple as sitting in front of a piano and then repeatedly playing each note in all possible ways. Then, throw this detector in a group with waveform-based detectors, get a weighted consensus and that should, in theory, be pretty damn accurate.

apankrat··on Pianojacq, an easy way to learn to play the piano
Thanks, yours is very nice too :)

For what it's worth, the auto-correlation route is simpler and more reliable. FFT alone is not enough, because the spectrum tends to be rather ambiguous. There's still a pattern to it for every note played, so it should be possible to deduce a note with a neural net. But I just didn't have time for that, maybe later.

PS. Give my thingy a try if you have a moment. I'm curious if it actually works with any pianos other than mine.

← PreviousPage 2 of 7Next →