Blog
Page: 0 1 2 3 4 5 6 7 ... 10 ... 15 ... 20 ... 25 ... 30 ... 35 ... 40 ... 45 ... 50 ... 55 ... 60 ... 65 ... 70 ... 75 ... 80 ... 85 ... 90 ... 95 ... 100 ... 105
Apple and the curse of VNC
Date: 8/9/2017
Tags: mac vnc
For many years now it's annoyed me greatly that trying to connect a Windows VNC client to a MacOSX VNC server has resulted in terrible horrible slow and glitchy performance. Mac to Mac is fine, Windows to Windows is fine, but cross platform? Nope. In fact the Mac to Mac performance is better than any of the Windows or Linux implementations. The reason being that Apple has added a range of proprietary extensions to make that use case better than normal VNC. This is also why the Windows -> Mac case is sub-optimal. It seems that the fast VNC modes that everyone else talks aren't spoken by the Apple VNC server implementation. So what to do? Well the solution that I'm employing at the moment is to... not use the Apple VNC server implementation! Turn off screen sharing in the options and install VNC connect. The cross platform performance is quite decent, running the server and client from the same vendor. Maybe 90% as fast as the all Apple case?

Embrace, extend, extinguish am I right?

You either die a hero or you live long enough to see yourself become the villain.

(I will try and find a free solution in the medium term, and will update this post if/when I do)
(0) Comments | Add Comment

sem_post funkiness on Linux
Date: 9/8/2017
Tags: linux
I moved the Linux implementation of the GThreadEvent class (.h, .cpp) over to the sem_open, sem_post, sem_wait calls a little while back.

Initially I used named semaphores and that seemed to work ok. But after a few weeks I noticed that sometimes the call to sem_post would just quietly NOT increment the semaphore count, while still returning 0 (Success). Which causes the listening thread blocking in sem_wait to never wake up. Crucially this would break the destructor / exit loop of GEventTargetThread.

Googling this didn't turn up anything useful. I believe I was using the API correctly and the documentation is very sparse. Anyway I implemented the semaphores using the sem_init/sem_destroy (anonymous) and it seems to be robust. Still, I'd like to know what the deal is with the named ones. The general pattern of behaviour I would see is:
  • Thread 1: Create using sem_open
  • Thread 2: Block on sem_wait
  • Thread 1: Start shutdown - calls sem_post (returns 0, but no increment) to tell thread 2 that it needs to exit.
  • Thread 2: Still stuck blocking on sem_wait...
Fun times. I checked it under valgrind and no weird memory accesses. Sometimes it would work ok and exit gracefully. But most of the time it would hang.
(0) Comments | Add Comment

Visual Studio 2013 crash...
Date: 9/2/2017
Tags: vs2013
This is just awesome:



The trace is something like this:
>	clr.dll!DontCallDirectlyForceStackOverflow(void)	Unknown
 	clr.dll!CLRVectoredExceptionHandler(struct _EXCEPTION_POINTERS *)	Unknown
 	clr.dll!CLRVectoredExceptionHandlerShim(struct _EXCEPTION_POINTERS *)	Unknown
 	ntdll.dll!RtlpCallVectoredHandlers()	Unknown
 	ntdll.dll!RtlDispatchException()	Unknown
 	ntdll.dll!_KiUserExceptionDispatcher@8()	Unknown
 	clr.dll!DontCallDirectlyForceStackOverflow(void)	Unknown
 	clr.dll!CLRVectoredExceptionHandler(struct _EXCEPTION_POINTERS *)	Unknown
 	clr.dll!CLRVectoredExceptionHandlerShim(struct _EXCEPTION_POINTERS *)	Unknown
 	ntdll.dll!RtlpCallVectoredHandlers()	Unknown
 	ntdll.dll!RtlDispatchException()	Unknown
 	ntdll.dll!_KiUserExceptionDispatcher@8()	Unknown
 	clr.dll!DontCallDirectlyForceStackOverflow(void)	Unknown
 	clr.dll!CLRVectoredExceptionHandler(struct _EXCEPTION_POINTERS *)	Unknown
 	clr.dll!CLRVectoredExceptionHandlerShim(struct _EXCEPTION_POINTERS *)	Unknown
 	ntdll.dll!RtlpCallVectoredHandlers()	Unknown
 	ntdll.dll!RtlDispatchException()	Unknown
 	ntdll.dll!_KiUserExceptionDispatcher@8()	Unknown
 	cpfe.dll!_corresp_init()	Unknown
 	ntdll.dll!ExecuteHandler@20()	Unknown
 	ntdll.dll!_KiUserExceptionDispatcher@8()	Unknown
 	cpfe.dll!_corresp_init()	Unknown
 	ntdll.dll!ExecuteHandler@20()	Unknown
 	....repeated a lot....
 	ntdll.dll!_KiUserExceptionDispatcher@8()	Unknown
 	cpfe.dll!_corresp_init()	Unknown
 	ntdll.dll!ExecuteHandler@20()	Unknown
 	ntdll.dll!_KiUserExceptionDispatcher@8()	Unknown
 	cpfe.dll!_corresp_init()	Unknown
 	ntdll.dll!ExecuteHandler@20()	Unknown
 	ntdll.dll!_KiUserExceptionDispatcher@8()	Unknown
 	KernelBase.dll!_RaiseException@16()	Unknown
 	[External Code]	
 	cpfe.dll!scout_parser::class_def_or_decl(struct a_source_point const &,struct a_type_specification &)	Unknown
 	cpfe.dll!scout_parser::tag_type_def_or_decl(struct a_source_point const &,struct a_type_specification &)	Unknown
 	cpfe.dll!scout_parser::type_specifier(struct a_type_specification &)	Unknown
 	cpfe.dll!scout_parser::type_specifiers(struct a_type_specification &)	Unknown
 	cpfe.dll!scout_parser::simple_declaration(struct a_type_specification &,class antlr::TokenRefCount)	Unknown
 	cpfe.dll!scout_parser::property_or_event_or_simple_declaration(struct a_type_specification &,class antlr::TokenRefCount)	Unknown
 	cpfe.dll!scout_parser::general_declaration(struct a_type_specification &,class antlr::TokenRefCount)	Unknown
 	cpfe.dll!scout_parser::general_declaration_with_error_recovery(struct a_type_specification &,class antlr::TokenRefCount)	Unknown
 	cpfe.dll!scout_parser::declaration(struct a_type_specification &,class antlr::TokenRefCount)	Unknown
 	cpfe.dll!scout_parser::declarations(void)	Unknown
 	cpfe.dll!scout_parser::translation_unit(void)	Unknown
 	cpfe.dll!_run_scout_parser()	Unknown
 	cpfe.dll!_corresp_init()	Unknown
 	cpfe.dll!_compute_il_prefix_size()	Unknown
 	cpfe.dll!_edg_main()	Unknown
 	cpfe.dll!_corresp_init()	Unknown
 	cpfe.dll!tag_parse(int,unsigned short const * *,unsigned short const *,bool,struct IEdgeSnapshotSession *,class a_scout_parser_interface *)	Unknown
 	vcpkg.dll!CExtStore::TagParseHelper(struct HBase,unsigned short const *,struct IEdgeSnapshotSession *,unsigned short const * * const,int,enum FileType)	Unknown
 	vcpkg.dll!CExtStore::TagParseCpp(struct HBase,unsigned short const *,struct IEdgeSnapshotSession *,unsigned short const * * const,int)	Unknown
 	vcpkg.dll!CCppParser::Parse(struct HBase,unsigned short const *,struct IEdgeSnapshotSession *,unsigned short const * * const,int,class CSharedPtr >)	Unknown
 	vcpkg.dll!CPopulateWorkItem::Work(void)	Unknown
 	vcpkg.dll!CWorkItem::InvokeWork(unsigned int)	Unknown
 	vcpkg.dll!CWorkQueue::Work(bool,unsigned int,unsigned int)	Unknown
 	vcpkg.dll!CWorkerThread::Work(void)	Unknown
 	vcpkg.dll!CWorkerThread::Work(void *)	Unknown
 	kernel32.dll!@BaseThreadInitThunk@12()	Unknown
 	ntdll.dll!__RtlUserThreadStart()	Unknown
 	ntdll.dll!__RtlUserThreadStart@8()	Unknown


I want to see if any one else is getting this...
(2) Comments | Add Comment

Ho ho ho
Date: 21/12/2016
Tags: scribe html-editor
The merry little elves at Memecode have been working away at all hours of the night to bring you a working Rich Text (HTML) editor in Scribe to put in your Christmas stockings.

With the release of Scribe v2.1.33 there is enough functionality to write email with styles. The reply/forwarding side of things isn't as good as the composition of new email. For a variety of reasons. And the control is still definitely in "Alpha" (i.e. incomplete functionality, still contains bugs, possibly show stopping ones).

It would be a excellent idea to reset the reply/forward formats to their default values, because I've updated the default template for HTML reply/forward. If you have a custom template for plain text, save that before you reset the templates in File -> Options -> General -> Reply / Fwd templates -> Reset.

Also go into your signature settings and configure a HTML sig for each account with an identity.

I'll set some expectations first... with the pros:
  • You can edit and delete styles to the text: font, font size, bold/italic/underline, foreground and background colours.
  • The tool bar tracks the current style.
  • You can add and remove links.
  • Most common text editor operations work: deleting / adding text. Selecting regions. Copy / paste.
  • Text reflows to the space available.
And some cons:
  • No undo / redo.
  • Cut / Copy / Paste is plain text only.
  • Replies/forwards are by default converted to plain text, losing any source styling. This is on purpose until I rewrite the reply/forward template merge code to cope.
  • The cursor can get "stuck" sometimes. Reposition with the mouse or use a different key combination.
  • Screen updates might be flaky in some situations.
  • No support for multiple levels of quoting.
  • No support for images (yet, it's on the todo list).
  • No indent/outdent support yet.
  • No lists, bulleted or numbered.
  • Swapping between the text and HTML tabs after you create the email or reply doesn't work. You are locked into whatever control you start with. This will change in later releases.

To switch between plain text and HTML quickly use Edit -> Use HTML Editor.

Do not use the HTML control for production emails. If it matters, use the plain text compose control. Otherwise I'd like to hear how it goes.
(0) Comments | Add Comment

Rich Text / HTML support in Scribe
Date: 5/12/2016
Tags: scribe
There has been a lot of people asking about the Rich Text / HTML editing support in Scribe and so while not fixing crash bugs I'm actively developing a new control to support styled text editing.

So that those that are interested can track the progress I'm publishing my internal spreadsheet of bugs and features:



Broadly speaking my hope is to have a very basic control working by the end of the year. Good enough that you can write and reply to email with, even if there isn't a lot of support for styling. Maybe some basic stuff like bold, colours and font size.
(2) Comments | Add Comment

Refactoring for performance
Date: 26/8/2016
Tags: mc2
A few weeks into actually using the MC2 I realized that the response time of the expression pedal was quite poor, running in the 100-200ms range. After doing some tests I worked out that it was because of the way messages were passed from the hardware thread that received the events, like analog to digital reads for the expression pedal, to the user interface thread, where they would be processed and sent back out the hardware thread to the Axefx. The problem with this was the the Raspberry PI is quite slow (or at least the version I'm using) and the user interface update speed was lagging. If the user interface is being updated, it's not processing messages. Hence the delay. But fixing it wasn't straight forward, because all the user interface code and Axefx code were all jumbled up like this:


So I took all the code that relates to the Axefx, and all the code that updates the user interface and separated them out into their own source code files. I called the Axefx specific code the "logic". Now I had 3 separate bits of code:
  • The user interface code. Responsible for updating the screen. Changing settings, like IA button actions etc.
  • The Axefx logic code. Which responds to MIDI inputs, converts hardware events to outgoing MIDI etc.
  • The hardware interface code. This is responsible for talking to all the hardware, both inputs and outputs.
Now I originally had 2 threads. And I decided that unless I really had to I would stay with those 2 threads, but the logic had to move from the UI thread, into the hardware thread. This meant that responding to MIDI and hardware events was decoupled from the user interface updating. Like this:


So hardware events, like the expression pedal value changing, would by processed immediately in the same thread and an outgoing MIDI message could be sent almost immediately, even if the UI was busy doing something. The latency was hugely improved. It's got to the point that it no longer has an impact musically. It seems to respond instantly.

In doing this I realized that I could hide all the details of each block of code behind a message passing interface. Which is excellent for thread safety. There was a little shared data that I wrapped in a mutex. But all in all the design feels nice and clean.

In fact I loved the design so much I'm rewriting i.Ftp to use the same architecture. Oh yeah, and because it was kinda badly written and wouldn't port to modern UI systems that don't have thread safe UI APIs.
(0) Comments | Add Comment