numlockr

A Windows system tray application that monitors the state of the Num Lock key, restoring it to the active state if it is ever found to be inactive.

If you find your Num Lock key is being turned off by certain remote desktop applications, numlockr will prevent that.

Tested on Windows 10.

Download: https://sourceforge.net/projects/numlockr/

Circular Queue Class

While developing a streaming audio application, I found the need for a fast and reliable buffering mechanism. I developed a Queue Class and used it as a buffer, stuffing blocks of data in on one thread and pulling them out on another. The quality of the audio was greatly improved by this buffering mechanism. But I wanted something better, something that would perform as few conditional and allocation operations as possible. So I developed this circular queue class.

The number of elements in the queue is restricted to powers of two. Keeping track of front, back, overflow, and underflow requires only two internal member variables, one of which is incremented on every enqueue operation, the other is incremented on every dequeue operation (wrapping around to zero is expected and supported behavior). Applying a bitmask to one of these variables reduces the actual number to an “index” of the front or back of the queue, respectively. The bitmask value is calculated from the “size” (number of elements) specified during initialization. Allocation of the array of elements is also performed during initialization.

The only condition checked during an enqueue operation is an overflow test. The only condition checked during a dequeue operation is an underflow test. There is no “is initialized” test in these functions, so be sure to initialize an instance before using it!

Cross-platform permutations of the source (GitHub):
https://github.com/UniversalProgrammingOrganization/upo-lib/blob/master/upo-lib/CircularQueue.h
https://github.com/UniversalProgrammingOrganization/upo-lib/blob/master/upo-lib/CircularQueue.cpp

#define O void // for Object pointers (O*)
#define Z NULL // shorthand for NULL

class CQ // a circular queue class
{
public:
    DWORD m_dwNQs; // total number of enqueue operations
    DWORD m_dwDQs; // total number of dequeue operations
    DWORD m_dwIM;  // Index Mask - a bitmask
    O** m_ppE;     // pointer to array of elements

    CQ()
    {
        m_ppE = Z;
    };

    ~CQ()
    {
        Reset();
    };

    void Reset()
    {
        // free array of elements:
        if (m_ppE)
            delete [] m_ppE;
 
        m_dwNQs = 0;
        m_dwDQs = 0;
        m_dwIM = 0;
        m_ppE = Z;
    }
 
    bool Init(
        DWORD dwSize)
    {
        // allow object re-use:
        Reset();
 
        // verify size is not zero:
        if (dwSize == 0)
            return false;
 
        // calculate the bit mask:
        m_dwIM = dwSize - 1;
 
        // verify size is a power of 2:
        if (dwSize & (m_dwIM))
            return false;
 
        // allocate the queue elements:
        m_ppE = new O*[dwSize];
 
        // will return true only if all of the above succeeded:
        return (m_ppE != Z);
    };
 
    // enqueue function:
    O* NQ(O* pO)
    {
        // check for overflow:
        if (Size() > m_dwIM)
            return Z;
 
        // calculate the enqueue index:
        DWORD dwEi = (m_dwNQs & m_dwIM);
 
        // set the element value:
        *(m_ppE + dwEi) = pO;
 
        // increment enqueue count:
        m_dwNQs++;
 
        return pO;
    };
 
    // dequeue function:
    O* DQ()
    {
        // get the element value:
        O* pO = Peek();
 
        // increment dequeue count (if no peek error):
        if (pO != Z)
            m_dwDQs++;
 
        return pO;
    };
 
    O* Peek()
    {
        // check for underflow:
        if (Size() == 0)
            return Z;
 
        // calculate the dequeue index:
        DWORD dwDi = (m_dwDQs & m_dwIM);

        // return the element value:
        return *(m_ppE + dwDi);
    };
 
    // returns the distance between m_dwDQs and m_dwNQs
    // (the size of the actual queue contents):
    DWORD Size()
    {
        if (m_dwDQs < m_dwNQs)
            return (m_dwNQs - m_dwDQs);
        else
            return (m_dwDQs - m_dwNQs);
    };
};

The above “Size()” function would look shorter if it was constructed like this:

    DWORD Size()
    {
      return abs(m_dwDQs - m_dwNQs);
    };

But the “abs()” function is typically implemented like this:

    int abs(int n)
    {
        if (n >= 0)
            return n;
        else
            return -n;
    };

Unframed Architecture

After working with “microservices” and other top-heavy development frameworks for years, I think it is time to get down to the bare metal and define an architectural orientation that performs much better:

Unframed Architecture

A design pattern in which:

  • All executable components and libraries are compiled into native machine code
  • All executable components are not dependent on any kind of framework (“runtime” environment) or virtual machine
  • All network communications are in the form of full 8-bit binary data

Source code examples on BitBucket

Vortex-based Tuning

Background:

Cross-referencing the above three concepts yields a rather elementary description of the purity of Just Intonation.

Starting with the root note of A (432 Hz), which converts to 9 on the Vortex-based Math pattern (because 4+3+2 = 1+8 = 9), generate a Pure Fifth (3:2 ratio) with the formula 432*3/2 = 648. Since 648 converts to 9 on the Vortex-based Math pattern (because 6+8+4 = 1+8 = 9), a pattern becomes apparent: All of the following Just-intoned Diatonic musical frequencies convert to 9 on the Vortex-based Math pattern (the Just-intoned A Major Diatonic Scale):

        
Unison  ( 1/1): 432                         = 4+3+2 = 9
Fifth   ( 3/2): 432 *  3/2 = 648 = 6+4+8 = 18 = 1+8 = 9
Fourth  ( 4/3): 432 *  4/3 = 576 = 5+7+6 = 18 = 1+8 = 9
Sixth   ( 5/3): 432 *  5/3 = 720            = 7+2+0 = 9
Third   ( 5/4): 432 *  5/4 = 540            = 5+4+0 = 9
Second  ( 9/8): 432 *  9/8 = 486 = 4+8+6 = 18 = 1+8 = 9
Seventh (15/8): 432 * 15/8 = 810            = 8+1+0 = 9
Octave  ( 2/1): 432 *  2/1 = 864 = 8+6+4 = 18 = 1+8 = 9

Pythagorean Tuning produced some irrational numbers, so I experimented with other 12-tone systems:

Wendy Carlos 12-tone Just Intonation Scale (Key of A Major):

        
Note Ratio   Formula         Hz
A    (1:1)   432 * 1  / 1  = 432 = 4 + 3 + 2              = 9
A#   (17:16) 432 * 17 / 16 = 459 = 4 + 5 + 9 = 18 = 1 + 8 = 9
B    (9:8)   432 * 9  / 8  = 486 = 4 + 8 + 6 = 18 = 1 + 8 = 9
C    (19:16) 432 * 19 / 16 = 513 = 5 + 1 + 3              = 9
C#   (5:4)   432 * 5  / 4  = 540 = 5 + 4 + 0              = 9
D    (21:16) 432 * 21 / 16 = 567 = 5 + 6 + 7 = 18 = 1 + 8 = 9
D#   (11:8)  432 * 11 / 8  = 594 = 5 + 9 + 4 = 18 = 1 + 8 = 9
E    (3:2)   432 * 3  / 2  = 648 = 6 + 4 + 8 = 18 = 1 + 8 = 9
F    (13:8)  432 * 13 / 8  = 702 = 7 + 0 + 2              = 9
F#   (27:16) 432 * 27 / 16 = 729 = 7 + 2 + 9 = 18 = 1 + 8 = 9
G    (7:4)   432 * 7  / 4  = 756 = 7 + 5 + 6 = 18 = 1 + 8 = 9
G#   (15:8)  432 * 15 / 8  = 810 = 8 + 1 + 0              = 9
A    (2:1)   432 * 2  / 1  = 864 = 8 + 6 + 4 = 18 = 1 + 8 = 9

Diatonic Scale (Key of A Major):

Note Interval Ratio  Formula        Hz
A    Unison   (1:1)  432 * 1  / 1 = 432 = 4 + 3 + 2              = 9
B    Second   (9:8)  432 * 9  / 8 = 486 = 4 + 8 + 6 = 18 = 1 + 8 = 9
C#   Third    (5:4)  432 * 5  / 4 = 540 = 5 + 4 + 0              = 9
D    Fourth   (4:3)  432 * 4  / 3 = 576 = 5 + 7 + 6 = 18 = 1 + 8 = 9
E    Fifth    (3:2)  432 * 3  / 2 = 648 = 6 + 4 + 8 = 18 = 1 + 8 = 9
F#   Sixth    (5:3)  432 * 5  / 3 = 720 = 7 + 2 + 0              = 9
G#   Seventh  (15:8) 432 * 15 / 8 = 810 = 8 + 1 + 0              = 9
A    Octave   (2:1)  432 * 2  / 1 = 864 = 8 + 6 + 4 = 18 = 1 + 8 = 9

Notice how the diatonic scale has all but two of the corresponding note frequencies in common; the exceptions being a difference of 9 Hz for the notes F# and D.

Data Organizer

The Data Organizer application was created to save a user’s time by providing a hierarchical scratch-pad that allows the creation and organization of textual data, without the need for repeating the steps of creating folders and files or editing and saving those files in a text editor window. It automatically saves the content of the text window when switching nodes (control-S can also be used to save the current content). The standard “edit” key combinations are also supported, and always apply to the text window (rather than the tree control): Select All (control-A), Copy (control-C), and Paste (control-V). Selecting a word with a double-click will automatically disregard a trailing space character, so that passwords or usernames can be pasted from the clipboard without errors.

The Data Organizer application uses a folder named “data” to store all data (created in the folder where the EXE is installed), arranging it in a tree of folders containing text files:

This design makes it possible to safeguard the contents of the “data” folder tree using a source control system.

The Data Organizer application supports the renaming of nodes, which changes the underlying folder names:

Feel free to Download and try Data Organizer out.

The Source Code is also available if you prefer reviewing the source before building and using Data Organizer.

Happy organizing!

 

Hexagonal Buttons

When creating the Musician’s Calculator iPhone app for ToruSound, I wanted the buttons to be more ergonomic and also wanted to be able to render them in patterns that made sense with regard to the underlying science, such as a “circle” of fifths surrounding “triangular” base-10 digit buttons, as well as piano-style buttons for producing actual musical pitches.

The source code for the hexagonal buttons (which is compatible with the Xcode interface designer) is up on GitHub:

https://github.com/DanielLewisRandall/iOpenCalculator/blob/master/OpenCalculator/OpenCalculator/UIHexButton.h

https://github.com/DanielLewisRandall/iOpenCalculator/blob/master/OpenCalculator/OpenCalculator/UIHexButton.m

WCF Service Schema Design

For a landmark location WCF service, I wanted to create a method, “GetLandmarks(lat, lon, radius)”, that returned a list of complex types to the caller. The prior art on this was very scattered at the time of this writing, so I have unified my findings in this post for future reference.

This is the schema definition for the “Landmark” complex type:

This is the schema definition for the “Landmarks” type, which is nothing more than a list of “Landmark” items:

This is the schema definition for the response message for the GetLandmarks() method call:

Purify That XML

Processing XML using XPATH or XSLT is much more difficult when the XML contains namespaces; sometimes the namespaces are a very necessary part of the data structure and should be left intact; it is when namespaces are used arbitrarily (and contribute nothing to the underlying data structure) that they become a problem. For the latter case, I have developed this XML purifier routine, which processes an XML string prior to parsing, translating, or even viewing the content. Even the presence of only the “default” namespace is enough to break MSXML XPATH parsing as well as MSXML XSLT transformations or using the .NET XslCompiledTransform class.

using System;
using System.Text.RegularExpressions;
namespace Utilities
{
    public class XmlPurifier
    {
        public static string Purify(string input)
        {
            string output = input;
             
            //
            // remove all "xmlns" attribute assignments:
            //
 
            string xmlns = "(?i)xmlns\\s*=\\s*\\\"[^\\s]*\\\"";
             
            Regex regex = new Regex(xmlns);
 
            MatchCollection nsCollection = regex.Matches(output);
             
            foreach (Match match in nsCollection)
            {
                output = output.Replace(match.Value, String.Empty); 
            }                      
             
            //
            // find and remove all namespace references:
            //
 
            string nsr = "(?i)xmlns:(([a-z0-9_]+))\\s*=\\s*\\\"[^\\s]*\\\"";
             
            Regex nsrx = new Regex(nsr);
 
            MatchCollection nsrCollection = nsrx.Matches(output);
 
            foreach (Match match in nsrCollection)
            {
                // remove the namespace reference:
                output = output.Replace(match.Value, String.Empty);
 
                // remove all namespace prefixes:
                output = output.Replace(match.Groups[1].ToString() + ":", String.Empty);
            }
             
            return output;
        }
    }
}

Stored Procedure Design

When creating stored procedures, I like to use in and out parameters that report possible internal problems. I also like to design a simple “create record if it does not exist and return ID” procedure:

USE [THE_DATABASE]
 
GO
 
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[ReadOrAddUser]') AND type in (N'P', N'PC'))
DROP PROCEDURE [dbo].[ReadOrAddUser]
GO
 
SET ANSI_NULLS ON
GO
 
SET QUOTED_IDENTIFIER ON
GO
 
CREATE PROCEDURE [dbo].[ReadOrAddUser]
(
 @in_GroupID integer,
 @in_UserName nvarchar(50),
 @in_UserData nvarchar(MAX),
 @out_UserID integer OUTPUT,
 @out_error_code integer OUTPUT,
 @out_error_message nvarchar(2000) OUTPUT
)
AS
BEGIN
 
 SET NOCOUNT ON
 
 -- populate standard variables
 SELECT @out_error_code = 0,
 @out_error_message = NULL
  
 Select @out_UserID = [ID]
 from [dbo].[Users]
 where [UserName] = @in_UserName AND [GroupID] = @in_GroupID
  
 BEGIN TRANSACTION
 
 BEGIN TRY
 
 -- if Group User is not in table, insert. Return ID in all cases.
 IF ( @out_UserID is null )
 BEGIN
 
 -- insert into table
 INSERT INTO dbo.Users
 (
 GroupID,
 UserName,
 UserData
 )
 VALUES
 (
 @in_GroupID,
 @in_UserName,
 @in_UserData
 )
 
 -- set parameter to value of new record
 SET @out_UserID = SCOPE_IDENTITY()
 
 END
 
 -- else update the data and return the ID.
 ELSE
 BEGIN
 UPDATE [dbo].[Users]
 SET [UserData] = @in_UserData
 WHERE [ID] = @out_UserID
 END
 
 END TRY
 BEGIN CATCH
 
 SET @out_UserID = NULL
 SET @out_error_code = 5000
 SET @out_error_message = ERROR_PROCEDURE() + ': ' + CAST(ERROR_NUMBER() AS VARCHAR(10)) + ' (line ' + CAST(ERROR_LINE() AS VARCHAR(10)) + ') ' + ERROR_MESSAGE()
  
 ROLLBACK TRANSACTION
 RETURN 1
 
 END CATCH
 
 COMMIT TRANSACTION
 
 RETURN 0
 
END
 
GO

C# code for calling the above procedure:

private const string OUT_ERROR_CODE = "@out_error_code";
private const string OUT_ERROR_MESSAGE = "@out_error_message";
 
public int ReadOrAddUser(
    string userName,
    string userData,
    int GroupID)
{
    SqlConnection con = new SqlConnection(_connString);
    SqlCommand cmd = new SqlCommand("ReadOrAddUser", con);
 
    addInParam(ref cmd, "@in_UserName", userName);
 
    addInParam(ref cmd, "@in_UserData", userData);
 
    addInParam(ref cmd, "@in_GroupID", GroupID);
 
    return ExecuteProcedure(ref con, ref cmd, "@out_UserID");
}
 
 
// supporting code:
 
public void addInParam(
    ref SqlCommand cmd,
    string name,
    string value)
{
    cmd.Parameters.Add(name, SqlDbType.Text);
    cmd.Parameters[name].Value = value;
}
 
public void addInParam(
    ref SqlCommand cmd,
    string name,
    int value)
{
    cmd.Parameters.Add(name, SqlDbType.Int);
    cmd.Parameters[name].Value = value;
}
 
public void addOutIntParam(
    ref SqlCommand cmd,
    string name)
{
    cmd.Parameters.Add(new SqlParameter(name, SqlDbType.Int));
    cmd.Parameters[name].Direction = ParameterDirection.Output;
}
 
public int ExecuteProcedure(
        ref SqlConnection con,
        ref SqlCommand cmd,
        string outVarName = "")
{
    bool getResult = (outVarName.Length > 0);
 
    int result = 0;
 
    cmd.CommandType = CommandType.StoredProcedure;
 
    if (getResult)
    {
        addOutIntParam(ref cmd, outVarName);
    }
 
    addOutIntParam(ref cmd, OUT_ERROR_CODE);
 
    cmd.Parameters.Add(new SqlParameter(OUT_ERROR_MESSAGE, SqlDbType.NChar));
    cmd.Parameters[OUT_ERROR_MESSAGE].Direction = ParameterDirection.Output;
    cmd.Parameters[OUT_ERROR_MESSAGE].Size = 2000;
 
    con.Open();
 
    cmd.ExecuteNonQuery();
 
    int code = (int)cmd.Parameters[OUT_ERROR_CODE].Value;
 
    if (code != 0)
    {
        string message = (string)cmd.Parameters[OUT_ERROR_MESSAGE].Value;
 
        throw new Exception(message);
    }
    else if (getResult)
    {
        result = (int)cmd.Parameters[outVarName].Value;
    }
 
    con.Close();
 
    return result;
}