Uncategorized

Solution for Poor Sound Quality using AirPods on MacOS

I tossed my AirPods in today and for some reason the sound quality while listening to music was a lot lower than normal. I’ve had this audio playback issue with other Bluetooth headphones, but never with the AirPods.

The issue: If your Bluetooth headphones are set as both the output audio device AND the input audio device, the OS has to lower the quality of the output sound because of the 2-way audio communication.

The solution: set your Mac’s audio input to the internal microphone, so it’s not trying to use the AirPods’ microphone. Open System Preferences and go to the Sound settings. Under the Input tab, select your Internal Microphone. The AirPods should re-sync and you’ll hear playback at full quality.

Upgrade Pains with 3rd Party Libraries in TypeScript

Most TypeScript developers know that one of the pain points of the ecosystem has traditionally been its integration with 3rd party libraries. As we begin 2018, the DefinitelyTyped project has finally matured to the point where grabbing a d.ts definition file for most libraries is only an npm install away (provided that you’re using TypeScript 2.0 or later). The problem has been solved well.

However, I recently tried to upgrade one of my Hapi.js projects from v16 to v17. Hapi v17 is a major rewrite of the entire framework, which includes a complete refactor to use async/await instead of callbacks. Upgrades like this generally have serious implications for the API (and therefore the typings) of the framework.

This is both good and bad.

The massive "win" is that by upgrading to the v17 typings TypeScript identifies all problem areas with my code. Much like when upgrading a DLL in a .NET project and your compilation breaks. I think this is a benefit that is often overlooked when most think about strong typing.

The downside is that the typings aren’t always available immediately, or even soon, after the official release of the new versions of libraries and frameworks. Upgrading libraries that haven’t made TypeScript support a priority will always incur delays. In this case, the typings for hapi v17 have been stuck in pull requests since December 11th, 2017, and were authored only shortly earlier by a very helpful contributor (for whom I have immense gratitude).

Because this PR hasn’t been merged yet, I’ve had to manually pull these typings and track the progress of the PR. While this is a good thing (we want high-quality typings), it’s a gap in the TypeScript world that has been frustrating for me.

This is not a complaint. The contributors putting together the typings for hapi have done a great job. If anything, this is a plea for framework and library developers to take a more active stance toward including TypeScript typings in-project or supporting the development of external typings in the DefinitelyTyped repository.

As a TypeScript developer it’s hard not to love a library for simply making rich and accurate typings available. Bring us typings and we will adopt!

Adding Advanced Custom Fields to WordPress REST API Response

There seems to be a lot of outdated information as to how to add your ACF fields into your WordPress REST API response, especially if you’re using the v2 API that’s now built into WordPress. The answer comes thanks to baptistebriel on a GitHub issue response for a plugin that seemed to work for API v1.

Here’s his code, slightly reworked.


$post_type = "post";

function my_rest_prepare_post($data, $post, $request) {
    $_data = $data->data;

    $fields = get_fields($post->ID);

    foreach ($fields as $key => $value){
        $_data[$key] = get_field($key, $post->ID);
    }

    $data->data = $_data;
    return $data;
}

add_filter("rest_prepare_{$post_type}", 'my_rest_prepare_post', 10, 3);

See below, where my custom fields maturity, traits, and variety are all part of the object that’s returned from the API.

Set MacBook Pro Touch Bar to Always Display Function Keys for Certain Apps

I’ve been wondering if there’s a way to lock the new MacBook Pro’s Touch Bar into "Function Key" mode, for use in applications like virtual machine hosts (such as VMWare Fusion) that can’t take full advantage of the Touch Bar or where it makes sense to have the function keys available.

To turn on function keys only for a particular app:

  1. System Preferences > Keyboard > Shortcuts > Function Keys
  2. Click the + button and select your application.
  3. Enjoy a Function Key-only experience in that application.

Calling C# Extension Methods on null references

Many C# developers are familiar with extension methods, but did you know that you can call extensions methods on null objects without fear of the dreaded Object reference not set to an instance of an object. error that comes along with invoking a method on a null reference.

Consider the extension method

public static bool IsNullOrEmpty(this string str)
{
    return string.IsNullOrEmpty(str);
}

Notice, we don’t actually try and invoke anything on str, we just pass it through to the string.IsNullOrEmpty() method for checking.

Provided that we’re working with a string variable (which provides us with our IsNullOrEmpty() extension method, we can invoke the method without fear:

string str = null;
Console.WriteLine("Is null or empty?: {0}", str.IsNullOrEmpty());

// OUTPUT:
Is null or empty? True

Generating PNGs in JavaScript

A project I’m working on allows the user to construct their own exterior home design using a set of provided colors, sidings, and trims. Due to technical limitations, I needed to be able to generate a solid-color image on-the-fly in JavaScript to set as a background-image on the element we overlay on the base layer in order to color that section of the home.

A Google search led me to PNGLib by Robert Eisele, which makes creating these images a lot easier. In my case, I needed to convert a hex RGB value into a valid value for background-image, url(...) and all. My code below includes a function imageUrlForColor() accepting three arguments: the hex color string (e.g. "#CE1126"), width, and height and returns the rule value as a string.

BONUS: One of the limitations of the CSS background-blend-mode is that is only works when one of the elements has a background-image, not just a background-color. The technique shown in the example below shows that you can use background-blend-mode on these elements without issue.

See the Pen Generate PNG in JavaScript by Cody Sand (@marpstar) on CodePen.

HTML5 File Uploads with FileAPI by Mail.ru

During a recent hunt for a nice HTML file upload library, I came across FileAPI by Mail.ru. In particular, I was looking for a library that was completely framework-independent. jQuery File Upload is a very nice plugin that I’ve used in the past, but for this particular project we needed something not based on jQuery.

What’s particularly cool about this library is that it includes a handful of functions for manipulating images directly. We wanted to generate an image thumbnail before we sent the file to the server for storage. FileAPI can generate a <canvas> thumbnail for you and you can generate a Base64 string of the image by calling .toDataURL() on the <canvas> element.

I took the simple example from the FileAPI docs and tossed them in a CodePen for you to play with. In my example, I filter any selected files to only images, generate a thumbnail for each one, and append it to the document.

Check it out:

See the Pen FileAPI Preview by Cody Sand (@marpstar) on CodePen.

FileAPI also includes functions for transporting the files to your server, capturing images from webcam, drag-and-drop, and a bunch of other stuff you’d expect from an upload library, dependency-free.

Bulk Updating S3 Files in F# with AWS .NET SDK

I’ve been working with a client to enhance an existing site the users could go to and create “playlists” of videos that would be burned to DVD and then mailed to the user. Now we’re adding the ability to download the files directly, which we’re storing on Amazon S3.

After uploading the files to my bucket and linking to them in the site, clicking on a link to the video file resulted in the browser playing the file instead of prompting the user to save the file.

The key to making this happen is the Content-Disposition: attachment header in the response of GET request for the file. Amazon does allow you to set this in the AWS Management Console, but not across multiple files simultaneous. Because we’ve got over 100 videos, I needed to automate it.

Enter the AWS .NET SDK and F#. Most of the code samples you’ll see for the AWS SDK for .NET are C#-based, but it works just as well in F#.

First things first, you’ll need to grab the AWSSDK NuGet package and reference it appropriately. Then we need to open a few namespaces from the SDK.

open Amazon  
open Amazon.S3  
open Amazon.S3.Model  
open Amazon.S3.IO

Next, we’ll need to set up our keys. These can be created from your AWS Management Console.

let accessKey = "YOUR_AWS_ACCESS_KEY"  
let secretKey = "YOUR_AWS_SECRET"

Then, let’s get our environment set up. I had to set Amazon.AWSConfigs.LoggingConfig.LogTo to LoggingOptions.SystemDiagnostics to prevent the SDK from complaining about log4net not being available.

// Set the AWS SDK to log using built-in .NET logging. 
Amazon.AWSConfigs.LoggingConfig.LogTo <- LoggingOptions.SystemDiagnostics;

// Instantiate a new S3 client
let client = new AmazonS3Client(accessKey, secretKey, RegionEndpoint.USEast1); 

Now that I’m connected, I want to get a list of files in my bucket.

let bucket = "my-bucket-name";  
let files = S3DirectoryInfo(client, bucket).GetFiles(); 

With each of my files, I want to configure it such that the Content-Disposition header will be set to attachment to force the browser to prompt for download.

Below, I declare a processFile function that will take an AmazonS3Client (our client from above) and each individual S3FileInfo object representing my files.

One thing worth noting is that S3 doesn’t support the idea of “updating” an object. To achieve this, you must make a “copy” of an object. There’s nothing to stop you from copying over the same object.


let processFile (client: AmazonS3Client, file: IO.S3FileInfo) = 

    // AWS requires you to "copy" a file in order to change details about it. Here we just copy over the original file.
    let copyRequest = new CopyObjectRequest(SourceBucket = bucket, 
                                            DestinationBucket = bucket, 
                                            SourceKey = file.Name, 
                                            DestinationKey = file.Name, 
                                            CannedACL = S3CannedACL.PublicRead);

    // I want the browser to prompt for a file download when a user requests this file.
    copyRequest.Headers.ContentDisposition <- "attachment"

    //
    // Perform any other updates here.
    //

    try
        printf "Processing: %s..." file.Name
        let resp = client.CopyObject(copyRequest);      // perform the "copy", which updates the file.
        printfn "Done!"
    with
        | ex -> printfn "Failed while processing!! %s" ex.Message

Finally, we iterate over our S3FileInfo array, sending each file along with our client into our new processFile function to perform the update.

files |> Array.iter(fun file -> processFile(client, file))

You’ll see the output in your console.

Processing My_First_Video.mp4...Done!  
Processing My_Second_Video.mp4...Done!  
...
Processing My_Final_Video.mp4...Done!  

This code updates files one-at-a-time, but this could be made parallel for even faster processing using the F# Parallel.iter function. I would’ve done this, but YAGNI.

/