Welcome to EMC Consulting Blogs Sign in | Join | Help

Rob Henry's Blog

  • Control Spotify with AutoHotkey

    I’ve been using Spotify for a few months now. However, I’ve been thinking for a while it would be useful to have some keyboard shortcuts to manage Spotify without having to open the UI. I’ve taken some of the existing scripts on the AutoHotkey forums and made some alterations to come up with a small script to implement the requirements below. If you’re an AutoHotkey newbie I’ve also documented what each command in the script is doing.

    Requirements for the script
    Whilst listening to a list of tracks that a search returned I’d like to be able to move back and forward between tracks without opening the Spotify UI.

    When a song comes on that I really like I’d like to be able to hit a hot key to save this track to a playlist that keeps my favourite tracks of all time. I’d also like to carry on with my work and not have to open the Spotify UI.

    Solution
    To fulfil these requirements the script I’ve put together does the following:

    When the key combination Shift + Alt + right is pressed AutoHotkey maps this to Ctrl + right arrow and sends this directly to the Spotify window using the ControlSend command. The DetectHiddenWindows command is used to allow AutoHotkey to see Spotify if it is minimized to the system tray.

    +!Right::
    {
    DetectHiddenWindows, On
    ControlSend, ahk_parent, ^{Right}, ahk_class SpotifyMainWindow
    DetectHiddenWindows, Off
    return
    }

    To move to the previous track the same process is followed, but using Shift + Alt + left.

    +!Left::
    DetectHiddenWindows, On
    ControlSend, ahk_parent, ^{Left}, ahk_class SpotifyMainWindow
    DetectHiddenWindows, Off
    return

    Moving back and forward between tracks are very simple operations because Spotify has keyboard shortcuts for these. However, Spotify doesn’t have a keyboard shortcut for adding the playing track to a playlist. To achieve this requires more effort. If you wanted to do this manually you’d take the following steps:

    • Open the Spotify window
    • Right click on the track graphic in the left corner of the Spotify window. Right clicking the track graphic will open the menu options for this track.
    • Move down to “Save to”, in the menu, and then hit enter to add to the playlist you require.
    • Minimise Spotify and carry on with your work.

    All that’s required now is to automate these steps. One limitation of the script is that it will always save to the first playlist in the dropdown. So it’s important to drag the playlist you’d like to use to the top of the playlists section. In the below example the tracks would be saved to the Rob playlist as that’s the first playlist.

    clip_image008

    The script maps Alt + Shift + Up to add the playing track to the playlist. And here’s the commands that make up the script. I’ve added a comment above each command.

    ^!Up::
    {

    ;Tells the mouse to move instantly to the correct position.
    SetDefaultMouseSpeed, 0

    ;Set coordinates to be relative to the screen.
    CoordMode, Mouse, Screen

    ;Gets the current position of the mouse.
    MouseGetPos, original_mouse_x, original_mouse_y

    ;Gets the current active window.
    WinGetActiveTitle, original_window_title

    ;Tells AutoHotkey to detect hidden windows.
    DetectHiddenWindows, On

    ;Checks it Spotify is running.
    IfWinExist, ahk_class SpotifyMainWindow
    {

    ;If Spotify is in the system tray then restore it.
    WinRestore, ahk_class SpotifyMainWindow

    ;Activate the Spotify window.
    WinWaitActive, ahk_class SpotifyMainWindow

    ;Get the position of the Spotify window.
    WinGetPos, X, Y, Width, Height, ahk_class SpotifyMainWindow

    ;Click the right mouse button offset to be in the middle of the track image.
    MouseClick, right, X+50, Y+Height-70

    ;Sleep to give the command chance to execute.
    Sleep, 200

    ;Send “s” to move to “Save to”. Send “Right” to move to the first playlist. Send “enter” to confirm adding to the playlist.
    ControlSend, ahk_parent, {s}{RIGHT}{ENTER}, ahk_class SpotifyMainWindow

    ;Sleep to give the command chance to execute.
    Sleep, 200

    ;Minimise the Spotify window.
    WinMinimize, ahk_class SpotifyMainWindow

    ;Move the mouse back to the original position.
    MouseMove, original_mouse_x, original_mouse_y

    ;Activate the window you were originally working in.
    WinActivate, %original_window_title%
    }

    ;Tell AutoHotkey to stop detecting hidden windows
    DetectHiddenWindows, Off

    return
    }

    The full script can be downloaded from here.

     For more Developer productivity tips you can visit my other blog - The Home Row

  • Snippets Anywhere with AutoHotkey

    Most developers will be familiar with snippets from tools such as Visual Studio or ReSharper. Snippets can save you time by cutting out repetitive typing and also help to improve accuracy by using boilerplate text. Most snippet solutions work only within one specific application; however it’s sometimes desirable to have a solution that can work across multiple applications, this is where AutoHotkey can help. I’m going to describe an AutoHotkey script that will allow you to seamlessly add and use text snippets in any application. The script is made up of three parts: defining a snippet from the script, adding a snippet to the script, and reloading the script after a snippet is added.

    Defining a Snippet

    AutoHotkey has special functionality, called hotstrings, which can be used to support snippets. A very simple use of a hotstring is detailed below:

    ::blog::C:\Mydrop~1\Documents\Blogs\

    When the abbreviation “blog” is typed and then an ending character is pressed, such as space, tab or enter, the abbreviation is deleted and replaced with the full text. The text I’ve used in this example relates to a folder path. I can now retrieve this path and use it in any application I like; locating the file/folder in explorer, copying a file in PowerShell/CMD, launching an application from Executor or opening a file in Vim.

    To get this working in a more useful way I’ve added a few extra options to the hotstring:

    :*?:blog`t::C:\Mydrop~1\Documents\Blogs

    * - defines that an end character is not required for the hotstring, I’ll add my own.

    `t - defines that a tab press is now part of the hotstring. This means that only when blog is typed and tab is pressed the text expands. Also, now blog can be typed in any document without firing the script.

    ? – defines that the hotstring can be part of another word.

    Adding a Snippet

    Adding a snippet to your script is easy: open up your AutoHotkey script file and add a line with the syntax already discussed. I try to separate my scripts so that all my snippets live in a specific file. I then include this file in the main script by using AutoHotkey’s include syntax:

    #include %A_ScriptDir%\snippets.ahk

    The main script will now behave as if the snippet file contents are inserted in the same position as the include statement. This leaves you with an easily manageable file with just snippets. A_ScriptDir stores the full path of the currently loaded script.

    If you expect to add new snippets regularly then you can make this more seamless by using another useful hotstring helper script which can be found referenced at the bottom of this page. This script allows you to highlight a piece of text and then hit a hot key to quickly add a snippet. I’ve edited the script, addsnippet.ahk, to support a separate file for snippets and I've changed the hotkey to Windows key, represented by # in the script, + w. If you hit Win+w you will be presented with a dialogue box:

    image

    The cursor position will be set at the position you need to enter the abbreviation and the highlighted text will be added to the correct position in the hotstring. Enter the abbreviation and then hit enter, or click OK to add the new hotstring to your script. This will save you opening, editing, closing and reloading the script each time you need to add a new hotstring.

    Continuation Sections

    The examples shown above all deal with a simple plain text snippet. It’s worth mentioning that if you want to add multiline formatted snippets you’ll need to use a continuation section. The syntax is shown below:

    :*?:continue`t::
    (   
            public bool continuation_section_example()
            {
                return true;
            }
    )

    The replacement text should be wrapped by a start and end bracket. This will force AutoHotkey to retain the formatting you have specified.

    Running the Script

    The main script is snippets.ahk. You need to run this script which in turn references the other scripts: addsnippet.ahk to allow seamless adding of snippets and, a script that wasn’t discussed, reload.ahk. The reload script will force a refresh of the snippets script when you manually edit and save. This means the snippets will be available immediately. The reload script is a pretty neat piece of functionality which I use in the majority of the scripts I write. The final scripts can be downloaded from here.

    For more Developer productivity tips you can visit my other blog - The Home Row

  • Christmas Wireless Woes

    This Christmas I spent some time with my in-laws in Ireland. It was the standard Christmas chain of events, sit down on the sofa, turn on the TV, eat and drink. This went well for twenty minutes or so until the urge came over me to turn on the laptop (I was quite impressed I'd lasted so long). I couldn't see the wireless network from the front room - the most comfortable room in the house and no wireless to be found.

    Unhappy with my lack of wireless I decided to do some research online (in a cold bedroom closer to the router). Pretty quickly it became apparent that there may be a solution to my problems. Most routers transmit signals equally in all directions through an omnidirectional antenna. This makes sense for most home use scenarios, it eases setup problems as the router can be placed anywhere in the house and will transmit equally over a specific range. After reading a bit more I found that an omnidirectional antenna can be replaced with a directional antenna. By using a directional antenna a greater range can be achieved in a particular direction. This sounded perfect for this situation as the router was located on one side of the house and only needed to point in one direction. This discovery became even more interesting when I found you could download a template and make your own!

    After searching through a few template recommendations it seemed the most popular was the Ez-12 Parabolic Reflector from FreeAntennas.com. All that's required to make the antenna was: kitchen foil, scissors, card and glue. So in true Blue Peter style I followed the instructions and here's my masterpiece:

    router2

    It's probably not worth a Blue Peter badge, but it improved the signal enough to use the Internet in a previously out of range area of the house. The signal improved from zero bars to one bar, so not a massive improvement but not bad for virtually nothing!

  • Visual Studio - Keyboard Shortcuts for Debug Tool Tips

    When using Visual Studio I try to avoid using the mouse as much as possible, however there are some functions, such as debug tool tips, that can't be mapped to keystrokes. These neat tool tips allow Visual Studio to display the value of variables when you hover over them with your mouse. I like to leave my code editing window with as much screen space as possible so I try not to have windows pinned open if I can avoid it (more on this in another post).  If I don't have one of the debug windows open and I want to quickly see what value a variable has I need to grab for the mouse, which can be frustrating.

    After finding that a keystroke couldn't be mapped to display the debug tool tips I decided to look towards AutoHotkey, which among other things, allows a user to write a script to simulate keystrokes and mouse movements. I created a script in AutoHotkey that moves the mouse cursor to the position of the text cursor on a keystroke. The script is quite simple and I've described the steps below:

    The Script
        1 #IfWinActive, ,Visual Studio
        2         #n::
        3         MouseGetPos ,currentX, currentY
        4         MouseMove, A_CaretX, A_CaretY + 15
        5         KeyWait, LWin
        6         MouseMove, currentX, currentY
        7         return

    Line 1 - Checks that the current window is Visual Studio.

    Line 2 - Checks that the keystroke is the windows key + n.

    Line 3 - Gets the current position of the mouse cursor and assigns the x and y values to currentX and currentY. The + 15 allows them to line up evenly.

    Line 4 - Moves the mouse cursor to the current position of the text cursor, which will cause Visual Studio to display the tool tip.

    Line 5 - Wait for the windows key to be released.

    Line 6 - Moves the mouse back to its original position.

    Limitations

    This script will allow you to quickly move around and display the value of the variable you're hovering over, but it won't allow you to drill down through the object tree. Therefore, if I need to do something a bit more in depth I'm happy enough to open a Quick Watch window with Ctrl+Alt+Q.

    Using the Script

    To use this script take the following steps:

    • Install AutoHotkey.
    • Right click the AutoHotkey icon in the system tray, ahk and select "Edit This Script".
    • Paste the script into the main script and save.
    • Right click the AutoHotkey icon again and select "Reload This Script".

    To use this script in Visual Studio: Move your keyboard cursor over the variable you wish to see the value of, and hold down the windows key + n. The mouse cursor will temporarily move over the variable and display the tool tip. When you release the windows key the mouse cursor will return to its original position and the tool tip will disappear.

    AutoHotkey is a powerful tool and I hope, even if you mostly use your mouse, you can see that it could be a neat solution to other tasks that require keyboard or mouse automation.

    For more Developer productivity tips you can visit my other blog - The Home Row

  • Managed Extensibility Framework (MEF)

    The Managed Extensibility Framework (MEF) is a new library being developed by Microsoft to offer an easy way to add extensibility to applications. MEF will be a new feature of .NET 4  but will also work on 3.5. MEF is currently available in CTP on Codeplex.  To show some of the core functionality MEF offers I've created a sample application. The sample application demonstrates how MEF can be used to create a plug-in architecture for custom text formatting. The sample application contains a simple form that has two text areas, one for the input of the source article text and the other to display the text after formatting. In this example we will use MEF to bind plug-in parts to add custom formatting functionality. The application will show how easy it is to create extension points in your application that can be used later with no recompilation required.

    SampleWindow

     

    The three main steps to add MEF to your application are:

    Exports: Create the components you would like to export. These are the parts that will plug-in to your application.

    Imports: Define where you would like to import the exported parts into your application.

    Configuration: Configure where the imports and exports will be found and add them to the Composition Container.

     

    Exports

    I've added two example formatters as exports, one for removing offensive words and one for adding advertisements. The user can select the required formatters form the list and click "Format Article" to run the specified formatters over the source text. The formatted text then appears in the processed text area. Each formatter that appears in the list box is dynamically loaded by MEF at runtime.

    To create a new formatter for export take the following simple steps:

    • Create a new class library project in Visual Studio and add a reference to the contracts assembly that contains the IArticleFormatter interface and add a reference to the MEF assembly System.ComponentModel.Composition.
    • Create a new class that implements the IArticleFormatter interface. Add functionality to format the received text in its Format method and implement the Name property to give the formatter a display name.
    • Now for the MEF part. Add the Export attribute to the class definition to tell the composition container that this should be exported.
    • When you've created the custom formatter, just drop it in to the directory that MEF is configured to reference.

    Here is the code from the sample offensive word formatter. The format method replaces all instances of offensive words with a message stating the word has been removed.

     

        [Export(typeof(IArticleFormatter))]
        public class OffensiveWordFormatter : IArticleFormatter
        {
            private List<string> offensiveWords;
     
            public OffensiveWordFormatter()
            {
                offensiveWords = new List<string>();
                offensiveWords.Add("mankini");
                offensiveWords.Add("arrrrgh");
            }
     
            public string Name
            {
                get { return "Offensive Word Formatter"; }
            }
     
            public string Format(string article)
            {
                StringBuilder builder = new StringBuilder(article);
     
                foreach (string word in offensiveWords)
                {
                    builder.Replace(word, "[offensive word removed]");
                }
     
                return builder.ToString();
            }
        }
     

    The main point to notice in the above code is that we specify the name of the interface as the type we wish to export. If we just added the Export tag with no type it would be exported as an OffensiveWordFormatter and not the base interface we will require for our imports.

     

    Imports

    To allow for Exported objects to be bound they require a matching Import. Below is the code that specifies we wish to import any IArticleFormatters. Although we could have used a standard Import attribute on a public property we instead use the ImportingConsrtuctor attribute to allow for the dependencies to be injected into the constructor. You should also notice that we use an IEnumerable of IArticleFormatters which means that the composition container will inject all instances of IArticleFormatter as an IEnumerable. If we had only one article formatter the import could just specify the interface to be imported and not request an IEnumerable, however the composition container will throw an exception if it has more than one object that can satisfy a single dependency.

     

        [Export("MainWindow")]
        public partial class Window1 : Window
        {
            [ImportingConstructor]
            public Window1([Import(typeof(IArticleFormatter))] IEnumerable<IArticleFormatter> articleFormatters)
            {
                InitializeComponent();
                lstArticleFormatters.ItemsSource = articleFormatters;
                lstArticleFormatters.DisplayMemberPath = "Name";
            }
     
            private void btnFormatArticle_Click(object sender, RoutedEventArgs e)
            {
                txtDestination.Text = txtSource.Text;
     
                foreach (var formatter in lstArticleFormatters.SelectedItems)
                {
                    txtDestination.Text = ((IArticleFormatter)formatter).Format(txtDestination.Text);
                }
            }
        }
     
    Configuration

    Now that we've specified our imports and exports, we just need to configure the composition container to include them for composition. This has been implemented in the Compose method on the application. To add our parts we need to create a catalog to reference them. We've created an AggregatingComposablePartCatalog which acts as a catalog of catalogs, this allows us to use two different catalogs. The first catalog is an AttributedAssemblyCatalog which we can use to add all imports and exports from a specified assembly. The second is a DirectoryPartCatlog which points to a specific directory that will be used for all future IArticleFormatter parts to be added to. You'll also notice that after the creation of the catalogs we explicitly add the application object as it must have its dependency on the main window satisfied. When the catalogs are created we add them to the composition container and call its Compose method.

        private bool Compose()
        {
            var catalog = new AggregatingComposablePartCatalog();
            catalog.Catalogs.Add(new AttributedAssemblyPartCatalog(Assembly.GetExecutingAssembly()));
            catalog.Catalogs.Add(new DirectoryPartCatalog(@"..\..\..\PluginArticleFormatters\", true));      
            container = new CompositionContainer(catalog.CreateResolver());
            container.AddPart(this);   
     
            try
            {
                container.Compose();
            }
            catch (CompositionException compositionException)
            {
                MessageBox.Show(compositionException.ToString());
                return false;
            }
            return true;
        }

     

    This short example has shown the simple steps of adding MEF to an application. You can download the sample solution from here. If you want to investigate MEF further I'd highly recommend Glenn Blocks' excellent PDC session that you can download here.

    del.icio.us Tags:

    Posted 11 November 2008 21:21 by Rob.Henry | 4 Comments
    Filed under:
Powered by Community Server (Personal Edition), by Telligent Systems