<![CDATA[Michael Bradshaw]]>http://mjb.io/+Ghost v0.3.3Sun, 31 May 2015 17:11:25 GMT60<![CDATA[How I Watch YouTube]]>For whatever reason, watching YouTube in Chrome sucks. Bad. As in, it's so bad I've stopped using Chrome for YouTube. Safari seems to have similar issues, and FireFox seems to be a bit better, but hasn't been bulletproof.

You know what's been bulletproof? youtuble-dl. This program rocks.

So here's how I watch YouTube (notice the first video doesn't even play in Chrome, and the second video freezes; I tried this at 6 different times and had the same results every time; oh yeah, and I often don't get audio to play on YouTube):

So, now, when I want to watch a YouTube video, I just download it (in HD) and watch it locally. It's way faster than streaming from YouTube.

]]>
http://mjb.io/+/+/how-i-watch-youtube/5997d943-1535-467e-89ea-f8246856b2a6Fri, 10 Jan 2014 07:04:19 GMT
<![CDATA[ActivityLifecycleCallbacks and Activity: Callback Calling Order]]>The documentation on ActivityLifecycleCallbacks is rather sparse, at best. It seems easy enough to use, but it's not obvious when the ActivityLifecycleCallbacks's functions are called in relation to the Activity's functions. I did a little test:

ActivityLifecycleCallbacks:

// ...
public void onActivityResumed(Activity activity) {  
    android.util.Log.w("test", "ActivityLifecycleCallbacks.onActivityResumed()");
}

public void onActivityPaused(Activity activity) {  
    android.util.Log.w("test", "ActivityLifecycleCallbacks.onActivityPaused()");
}
// ...

Activity:

// ...
@Override
protected void onResume() {  
    android.util.Log.w("test", "Activity.onResumed() (before super)");
    super.onResume();
    android.util.Log.w("test", "Activity.onResumed() (after super)");
}

@Override
protected void onPause() {  
    android.util.Log.w("test", "Activity.onPaused() (before super)");
    super.onPause();
    android.util.Log.w("test", "Activity.onPaused() (after super)");
}
// ...

And the output:

12-10 13:58:35.699: W/test(9794): Activity.onResumed() (before super)  
12-10 13:58:35.699: W/test(9794): ActivityLifecycleCallbacks.onActivityResumed()  
12-10 13:58:35.709: W/test(9794): Activity.onResumed() (after super)  
12-10 13:58:35.749: W/test(9794): Activity.onPaused() (before super)  
12-10 13:58:35.749: W/test(9794): ActivityLifecycleCallbacks.onActivityPaused()  
12-10 13:58:35.749: W/test(9794): Activity.onPaused() (after super)  

Now for the curious, it looks like ActivityLifecycleCallbacks's functions are called as part of the super call chain. So you can expect ActivityLifecycleCallbacks's callbacks to have fired by the time the Activity's super calls finish. Good to know!

]]>
http://mjb.io/+/+/activitylifecyclecallbacks-and-activity-callback-calling-order/4bd3239a-9b10-48fd-87b7-5a4dfe504093Wed, 01 Jan 2014 01:27:46 GMT
<![CDATA[WebGL: Fixing "INVALID_OPERATION: drawArrays: attribs not setup correctly"]]>I kept getting the WebGL: INVALID_OPERATION: drawArrays: attribs not setup correctly error in my simple WebGL app, which wasn't very helpful to me. Ok, I get it's not setup correctly, but what could be wrong? It turns out the problem was being caused by me using two different shader programs, with each program having a different number of attributes. I want to walk through this clearly, because most of the things I found online when searching for solutions were... lacking, to put it kindly. Let's look at my shaders:

Shader Program #1

It's a pretty simple program. Given a set of 2D vertices, make them all white.

Vertex shader:

attribute vec2 vertex;

void main(void)  
{
    gl_Position = vec4(vertex, 0.0, 1.0);
}

Fragment shader:

precision mediump float;

void main(void)  
{
    gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
}

Shader Program #2

Not too complicated. Given a set of 2D vertices and corresponding texture coordinates, render a textured object.

Vertex shader:

attribute vec2 vertex;  
attribute vec2 textureCoord;  
varying vec2 fragTextureCoord;

void main(void)  
{
    gl_Position = vec4(vertex, 0.0, 1.0);
    fragTextureCoord = textureCoord;
}

Fragment shader:

precision mediump float;  
uniform sampler2D sampler;  
varying vec2 fragTextureCoord;

void main(void)  
{
    gl_FragColor = texture2D(sampler, fragTextureCoord);
}

The problem

The problem is rooted in the shaders. The first vertex shader only has one attribute (vertex), while the second vertex shader has two attributes (vertex and textureCoord). When switching from one program to another, the enabled attributes weren't getting switched! In other words, when I loaded shader program #1 and called enableVertexAttribArray to enable the vertex attribute, and then later when I loaded shader program #2 and called enableVertexAttribArray to enable the vertex and textureCoord attributes, the enabling of the attributes isn't bound to a specific program. Enabling an attribute is a global operation, regardless of whether or not you create or use a different program. So when using shader program #1, the textureCoord attribute was still enabled! This resulted in an error (which seems sensible). There are two ways to work around this.

Solution #1: disableVertexAttribArray

One option is to just disable the extra attributes. When we use shader program #1, we can call disableVertexAttribArray to disable the extra attributes that shader program #2 uses. You have to watch out a little if you do this, because if you aren't explicitly assigning index numbers to your attributes, it's possible the vertex attribute in shader programs #1 and #2 will have different index values. One way to do this is to track which program you were using and which program you're going to use now, and then disable any extra attributes (or enable any missing attributes). Something like:

function switchPrograms(currentProgram, newProgram)  
{
    // Gets the number of attributes in the current and new programs
    var currentAttributes = gl.getProgramParameter(currentProgram, gl.ACTIVE_ATTRIBUTES);
    var newAttributes = gl.getProgramParameter(newProgram, gl.ACTIVE_ATTRIBUTES);

    // Fortunately, in OpenGL, attribute index values are always assigned in the
    // range [0, ..., NUMBER_OF_VERTEX_ATTRIBUTES - 1], so we can use that to
    // enable or disable attributes
    if (newAttributes > currentAttributes) // We need to enable the missing attributes
    {
        for (var i = currentAttributes; i < newAttributes; i++)
        {
            gl.enableVertexAttribArray(i);
        }
    }
    else if (newAttributes < currentAttributes) // We need to disable the extra attributes
    {
        for (var i = newAttributes; i < currentAttributes; i++)
        {
            gl.disableVertexAttribArray(i);
        }
    }

    // With all the attributes now enabled/disabled as they need to be, let's switch!
    gl.useProgram(newProgram);
}

Note that the above solution assumes all your attributes are array attributes. If you have an attribute that isn't an array (i.e. it shouldn't be enabled with enableVertexAttribArray), you'll have to come up with a more robust solution. Hopefully the above at least gives you some ideas and can help point you in the right direction in your quest to come up with a valid solution.

Solution #2: vertexAttribPointer

Enable all the attributes! Alright, so the whole reason we were getting this INVALID_OPERATION error comes from here (I suggest you read it and try to understand it!). The key here is in the last statement: "If a vertex attribute is enabled as an array, a buffer is bound to that attribute, but the attribute is not consumed by the current program, then regardless of the size of the bound buffer, it will not cause any error to be generated during a call to drawArrays or drawElements."

This means that if your program doesn't use the attribute, it's okay to fill it with a tiny junk array (note: not null, as that has other implications), as it won't actually be used. This means you can bind a tiny junk buffer with bindBuffer and then set the superfluous attribute to that tiny junk buffer with vertexAttribPointer, and then continue on your merry way. All WebGL wants is for your enabled array attributes to be associated with some valid (non-null) array (which is why you get the INVALID_OPERATION error if they're not). If you enable all the attributes, but your program doesn't actually use an enabled attribute, WebGL doesn't care how big the array is that's associated with it (so you won't get any out-of-bounds errors). It's just happy it has an array associated with the enabled attribute.

]]>
http://mjb.io/+/+/webgl-fixing-invalid_operation-drawarrays-attribs-not-setup-correctly/663534c1-8556-441c-98ea-a54c744dfaa8Wed, 01 Jan 2014 01:27:17 GMT
<![CDATA[Haskell Mandelbrot]]> I wrote a program (years ago) in Haskell that generated the image above of the Mandelbrot set. I really like Haskell, but I haven't spent enough time with it and never really wrapped my head around monads. I'd like to dive back into it when I get the time.

Anyway, the program I used to generate the fractal is below. I'm not a Haskell guru, so if the code is an abomination and you know how to improve it, please share in the comments! It would be cool to improve my Haskell skills. I wrote this years ago:

  
module Main where

import Data.Complex  
import Data.Char  
import qualified Data.ByteString.Char8 as C -- For file output

-- Constants
maxIter :: Int -- Max iterations  
maxIter = 750

width  :: Int -- Image width  
height :: Int -- Image height

width  = 400  
height = 400

-- Note: aspect ratio of (minX, minY), (maxX, maxY) must
-- match aspect ratio of (width, height)
minX :: Double -- Min x-coordinate of graph  
maxX :: Double -- Max x-coordinate of graph  
minY :: Double -- Min y-coordinate of graph  
maxY :: Double -- Max y-coordinate of graph

-- For the zoomed in part of the Mandelbrot:
--minX = -0.826341244461360116
--maxX = -0.8026423086165848822

--minY = -0.2167936114403439588
--maxY = -0.193094675595568725

--For a full view of the mandelbrot
minX = -2.5  
maxX = 1.5

minY = -2  
maxY = 2


-- The actual fractal part
-- It basically works on a matrix, which we will call M, that represents a grid of
-- points on the graph. Essentially, M[i, j] is (xList[j], yList[i])
xList :: [Double]  
yList :: [Double]

xList = [minX, (minX + ((maxX - minX) / (fromIntegral width  - 1)))..maxX]  
yList = reverse [minY,(minY + ((maxY - minY) / (fromIntegral height - 1)))..maxY]

row :: Double -> C.ByteString -- A row of image bytes for a given y-coordinate  
row y = C.pack [frac (x :+ y) (0 :+ 0) 0 | x <- xList] -- For Mandelbrot set  
--row y = C.pack [frac ((-0.1) :+ (0.8)) (x :+ y) 0 | x <- xList] -- For Julia set

etaFraction :: Complex Double -> Double  
etaFraction z = (log (log (magnitude z))) / log 2

smoothEta :: Int -> Complex Double -> Double -- Smooth escape time algorithm value  
smoothEta iter z = (fromIntegral iter - etaFraction z) / fromIntegral maxIter

color :: Int -> Complex Double -> Double -- Gets the color for the point, in range [0, 1]  
color iter z = 1 - smoothEta iter z -- Smooth escape time algorithm (and invert)  
--color iter z = fromIntegral iter / fromIntegral maxIter

interpolate :: Double -> Char -- Adds an interpolation curve for interpolating color  
interpolate v = chr (truncate ((v ^ 12) * 255)) -- Polynomial curve  
--interpolate v = chr (truncate(v * 255)) -- Linear

frac :: Complex Double -> Complex Double -> Int -> Char -- The actual fractal algorithm!  
frac c z iter  
     | iter >= maxIter = chr 255 -- never escaped, return color value of 255
     | otherwise = let z' = z * z + c
               in if ((realPart z') * (realPart z') + (imagPart z') * (imagPart z')) > 4
                  then interpolate (color iter z')
    else frac c z' (iter + 1)


-- The file output
pgmHeader :: C.ByteString  
pgmHeader = C.pack ("P5\n" ++ (show width) ++ " " ++ (show height) ++ "\n255\n")  
main = C.writeFile "fractal.pgm" (C.append pgmHeader (C.concat [(row y) | y <- yList]))  

And some pictures from this program (each image has had some constants tweaked):


The Mandelbrot set in pure black and white; only pixels considered "inside" the set are black.



A Julia set based on (0.285, -0.01i). I actually edited the brightness/contrast in post-processing on this one to really bring out the spirals.



A zoomed in portion of the Mandelbrot set. I edited this one's brightness/contrast settings in post processing to bring out some of the little details.
]]>
http://mjb.io/+/+/haskell-mandelbrot/8233de06-995f-4add-bcd2-b2cd0fc2e237Wed, 01 Jan 2014 01:26:48 GMT
<![CDATA[Building SFML 2 with C++11 on OS X]]>It's not a very difficult thing to do, but clear, simple instructions can be useful. Thankfully, there's a good Getting Started guide with official documentation for building SFML (and you really should read it). If, after reading that, you want things spelled out even more... here you go.

Step 1: Prepare Xcode

Make sure you have Xcode downloaded and installed. Make sure you have your command line tools set up. You do this by doing Xcode -> Preferences -> Downloads and making sure you have Command Line Tools downloaded and installed.

Step 2: Prepare Cmake

I won't go into what Cmake is, but download and install the latest version. SFML needs it.

Step 3: Download SFML 2

Go to SFML's download page and download the SFML source code (either the SFML 2.1 source code or the latest snapshot of the Git repository).

Step 4: Open a Terminal

Hopefully you've got the Terminal sitting on your dock, but in case not it can be found under Applications -> Utilities -> Terminal.app.

Step 5: Get Ready to Build

Next, do the following in your terminal:

cd <sfml folder>  
mkdir build  
cd build  

In the first line, replace <sfml folder> with the path to the folder where you downloaded and extracted the SFML source to. mkdir build just creates the directory build where we can do our dirty work, and cd build moves into that folder.

Step 6: Run Cmake

Now run the following (you can copy and paste):

cmake -G 'Unix Makefiles' \  
      -DCMAKE_OSX_ARCHITECTURES='i386;x86_64' \
      -DCMAKE_CXX_COMPILER='/usr/bin/clang++' \
      -DCMAKE_C_COMPILER='/usr/bin/clang' \
      -DSFML_BUILD_FRAMEWORKS='ON' \
      -DSFML_INSTALL_XCODE4_TEMPLATES='ON' \
      -DCMAKE_CXX_FLAGS='-stdlib=libc++' \
      -DCMAKE_C_FLAGS='-stdlib=libc++' ../

This runs Cmake and tells it to do a few things. Particularly, it's saying (going down the options one by one):

  • Use Makefiles instead of Xcode
  • Build for x86 and x86_64 (i.e. 32-bit and 64-bit)
  • Use clang++ for compiling the C++ code
  • Use clang for compiling the C code
  • Build as frameworks (instead of just dynamic libraries)
  • Install the Xcode SFML templates (so you can easily create SFML projects)
  • Link to the libc++ standard library implementation (necessary for C++11)

This doesn't actually build SFML, but it sets everything up so we can run the next two commands...

Step 7: Build!

Now run:

make -j4  

make is a fancy program that will actually do all the building of SFML for you. The -j4 option just says "Use 4 threads to do this." If you don't want to use multiple threads to build (which is sloooow), you can omit this option. If you want to use more threads, like 8, you can change it to -j8 (I personally use 8 threads).

Step 8: Install!

The last step:

sudo make install  

This will prompt you for your password. Give it your password. It'll place all the SFML files in their final resting place on your system, and it needs some elevated privileges to write the files to the necessary folders. If you're curious where it's writing the files to, just look at the output. Anyway, now you're done!

Bonus Step: Making an Xcode Project

What good is building and installing SFML if you don't use it? We'll set up a simple project now. Open Xcode. Then create a new project. Then select the SFML App template:

In the next screen, give your project a name. Make sure to say you want to use C++11! The "C++ Compiler and Standard Library" option does not default to Clang and C++11. You have to set this yourself. Assuming you followed my instructions and made SFML a universal framework for 32-bit and 64-bit, the rest of the options can stay the same.

You should now be able to run the created project!

]]>
http://mjb.io/+/+/building-sfml-2-with-c11-on-os-x/795cfc73-a4c3-44b9-8263-c5b6d0d5022cWed, 01 Jan 2014 01:26:19 GMT