Wednesday, March 3, 2021

My custom Planning Center Services plan report. You're welcome.

To all my fellow Planning Center Services jockeys out there, I thought I'd share with you a custom Plan report that I created (using one of the built-in reports as a baseline, mind you) and have been using for years now. Now, before you assume that all I've done here is fiddle with colors and fonts and page layout, hear me out. There are some features of this template that I want you to know about.

First—and the primary reason that I love this template so much—is that it handles Plan and Item Note categories dynamically. Unlike the built-in templates, this report template doesn't have to be modified just because you use different Notes categories than the default Planning Center ones. In fact, it doesn't care what specific Notes categories you have at all. Rather, it examines the Plan and its Items and dynamically determines which Note types are actually employed. This means two things: that it doesn't waste any page/screen real estate on unused Note categories, and you can use the same template for entirely different Service Types with entirely different categories defined!

The second, admittedly minor, thing that I like about this template is that it adds a column for icons that appear next to certain Item types. So Songs show up with a music notes icon (♫) next to them; Media items show a "play" triangle (⏵). It's a little thing, but it draws the eye to certain Item types quickly.

Finally, the template itself allows some quick customization of the features it employs via a collection of boolean variables at the top.  This allows you to use the same basic template for multiple custom Reports, but with little easy tweaks to goven the feature set for each one.  So, for example, I have a Report that shows everything that I distribute to my A/V operators and band members.  But I have another one using this same template that I use for our Ushers and Greeters where the variables show_plan_people, show_plan_notes, and show_item_notes have been set to false.

So, without further ado, my template. Please feel free to copy, use, and modify this thing to better suit your church's needs!

<!-- QUICK CUSTOMIZATION: {% assign show_plan_notes = true %} {% assign show_plan_people = true %} {% assign show_item_times = true %} {% assign show_item_length = true %} {% assign show_item_description = true %} {% assign show_item_notes = true %} --> <html> <head> <title>{{ }}:: {{ plan.dates }}</title> <link href=",wght@0,400;0,600;1,400;1,600&display=swap" rel="stylesheet"> <style> body { padding: 0; margin: 5px; color: #222; font-family: Roboto, sans-serif; font-size: 14pt; } h1 { font-size: 1.5em; font-weight: normal; text-shadow: 0 -1px 1px rgba(0, 0, 0, 0.9); } h2 { font-size: 1.1em; font-weight: normal; padding: 20px 35px; margin: 0; line-height: 1em; text-shadow: 0 1px 0 white; } h3 { font-size: 0.9em; text-shadow: 0 1px 2px rgba(0, 0, 0, 0.4); } pre { margin: 0; padding: 0; white-space: pre-wrap; font-size: .9em; } table#plan { width: 100%; border-collapse: collapse; margin-top:0px; margin-bottom: 15px; font-size: 10pt; } table#plan tr { border-bottom: 1px solid #ddd; } table#plan thead { display: table-header-group; } table#plan th { color: white; background: #444; font-weight: bold; padding: 0.5em 1em; vertical-align: middle; } table#plan td { text-align: center; padding: 0.5em 1em; } table#plan .icon { padding: 0; } table#plan .preservice .time, table#plan .preservice .length { color: #aaa; } table#plan .time { width: 3em; text-align: center; } table#plan .length { width: 3em; text-align: center; } table#plan .note_column { text-align: left; background: #f8f8f8; border-left: 2px solid white; } table#plan .header { text-align: left; font-weight: bold; color: black; background: #ddd; } table#plan .note { font-weight: bold; text-align: left; vertical-align: middle; min-width: 1in; } table#plan .element { min-width: 3in; text-align: left; } table#plan .element .description { font-size: 0.86em; color: #444; font-style: italic; } table#header { width: 100%; border: none; padding: 0; border-collapse: collapse; } table#header td { padding: 2px; vertical-align: top; } .artwork { float: left; margin-right: 15px; height: 40px; } .note_content { background: yellow; padding: 4px 8px 0; border-radius: 0.3em; } #header { padding: 5px 20px; background: #000; color: white; line-height: .8em; margin: 0; } #header img { float: right; height: 60px; margin-right: -15px; } #titles { color: #333; font-size: 1.1em; font-weight: normal; padding: 10px 20px; margin: 0; line-height: 1.1em; text-shadow: 0 1px 0 white; min-height: 45px; } #plan_title { font-style: normal; font-size: 0.8em; display: block; color: #666; margin: 4px 0 0 0; } #plan_notes, #plan_people { background: #f8f8f8; margin: 1em 0; border-left: 4px solid black; padding: 0.5em 0 1em 2em; } #plan_notes { font-size: 0.8em; background: #ffffd0; } #plan_notes .plan_note { margin-top: 1em; } #plan_notes .plan_note_category { font-weight: bold; } #plan_people { font-size: 0.9em; } #plan_people .person { font-size: 0.7em; margin-right: 15px; display: inline-block; } #plan_people .person_status_U { opacity: 0.5; } #plan_people .person_category { clear: both; padding-top: 1em; } #plan_people .person_category p { font-size: 0.8em; margin: 0; } #plan_people .person_position { font-style: italic; } #plan_people .position { font-weight: bold; } </style> </head> <body> <!-- If showing item notes, first build a list of item note categories in use. --> {% if show_item_notes %} {% assign used_item_note_categories = '' | split: '' %} {% for item in plan.items %} {% for note in item.notes %} {% assign category = | split: '|' %} {% assign used_item_note_categories = used_item_note_categories | concat: category %} {% endfor %} {% endfor %} {% assign used_item_note_categories = used_item_note_categories | uniq | sort %} {% endif %} <div id="header"> <h1>{{ }} - {{ plan.dates }}</h1> </div> <div id="titles"> <img class="artwork" onerror="'none'" src="{{ plan.series_artwork_url }}" /> <div id="series_title">{{ plan.series_title }}</div> <div id="plan_title">{{ plan.plan_title }}</div> </div> <!-- If showing plan notes, first build a list of plan note categories in use, then iterate. --> {% if show_plan_notes %} {% assign used_plan_note_categories = '' | split: '' %} {% for note in plan.notes %} {% assign category = | split: '|' %} {% assign used_plan_note_categories = used_plan_note_categories | concat: category %} {% endfor %} {% assign used_plan_note_categories = used_plan_note_categories | uniq | sort %} {% unless used_plan_note_categories == empty %} <div id="plan_notes"> {% for plan_note_category in used_plan_note_categories %} <div class="plan_note"> <div class="plan_note_category">{{plan_note_category}}</div> {% for note in plan.notes %} {% if note.category_name == plan_note_category %} <div>{{note.note}}</div> {% endif %} {% endfor %} </div> {% endfor %} </div> {% endunless %} {% endif %} <table id="plan"> <thead> <tr> {% if show_item_times %} {% for time in plan.plan_times %} <th class="time">@{{ time.starts_at | date: '%I:%M' }}</th> <!-- {% increment colspan %} --> {% endfor %} {% endif %} <th class="icon"></th> <!-- {% increment colspan %} --> <th align="left">Element</th> <!-- {% increment colspan %} --> {% if show_item_notes %} {% for category in used_item_note_categories %} <th class="note">{{ category }}</th> <!-- {% increment colspan %} --> {% endfor %} {% endif %} {% if show_item_length %} <th class="length">Length</th> <!-- {% increment colspan %} --> {% endif %} </tr> </thead> <tbody> {% for item in plan.items %} {% case item.item_type %} {% when 'Header' %} <!-- Header rows --> <tr> <td colspan="{{ colspan }}" class="header">{{ item.title }}</td> </tr> {% else %} <!-- Non-header rows --> {% assign item_class = ''%} {% if item.is_preservice or item.is_postservice %} {% assign item_class = 'preservice ' %} {% endif %} <tr class="{{ item_class }}"> {% if show_item_times %} {% for time in plan.plan_times %} <td class="time item {{ item_class }} {{ item.item_type }}"> {% for item_time in item.times %} {% if item_time.time_id == %} {{ item_time.actual_time | date: '%I:%M' | downcase }} {% endif %} {% endfor %} </td> {% endfor %} {% endif %} <td class="item icon"> {% if item.item_type == "Song" %}&#9835;{% endif %} {% if item.item_type == "Media" %}&#9205;{% endif %} </td> <td class="item element {{ item_class }} {{ item.item_type }}"> {{ item.title }}{% if %} [{{ item.arrangement.music_key }}]{% endif %} {% if show_item_description %}<div class="description">{{ item.description }}</div>{% endif %} </td> {% if show_item_notes %} {% for category in used_item_note_categories %} <td class="item note note_column {{ item_class }} {{ item.item_type }}"> {% for note in item.notes %} {% if note.category_name == category %} {{ note.note }} {% endif %} {% endfor %} </td> {% endfor %} {% endif %} {% if show_item_length %} <td class="item length {{ item_class }} {{ item.item_type }}">{{ item.length }}</td> {% endif %} </tr> {% endcase %} {% endfor %} </tbody> </table> {% if show_plan_people %} <!-- If showing plan people, first build a list of person categories in use, then iterate. --> {% assign used_person_categories = '' | split: '' %} {% for plan_person in plan.plan_people_not_declined %} {% assign category = | split: '|' %} {% assign used_person_categories = used_person_categories | concat: category %} {% endfor %} {% assign used_person_categories = used_person_categories | uniq | sort %} {% unless used_person_categories == empty %} <div id="plan_people"> {% for plan_person_category in used_person_categories %} <div class="person_category"> <p><strong>{{ plan_person_category }}</strong></p> {% for plan_person in plan.plan_people_not_declined %} {% if != null %}{% if == plan_person_category %} <div class="person person_status_{{ plan_person.status }}"> &bull; <span class="person_name">{{ }}</span> <span class="person_position">({{ plan_person.position }})</span> </div> {% endif %}{% endif %} {% endfor %} </div> {% endfor %} </div> {% endunless %} {% endif %} </body> </html>

As of a few minutes ago, I've submitted this report template back to the fine folks that develop Planning Center Services so that they may consider integrating its enhancements into the core product itself.

Wednesday, December 30, 2020

"O For a Thousand Tongues"

Way back in January 2016, I was working to create a modernized arrangement of the Public Domain hymn, "O For a Thousand Tongues to Sing" by Charles Wesley.  I'd hope to preserve the original melody and lyrics, and maybe just add a bridge or something.  I ended up adding a sort of bridge for each stanza.  Unfortunately, while I was really happy with my additions, they never really paired well with the feel of the original hymn.  So I shelved the idea, revisiting it from time to time over the years in further failed attempts to shoehorn together two incompatible ideas.

On June 30, 2020, however, I gave up trying to make fit what never would, and instead restructured the whole song around my additions.  I heavily edited the original hymn lyric and melody while still trying to preserve the essence of what it said.  After all, to wish that one had a thousand tongues to sing God's praise all the louder is a beautiful sentiment!  So that, as well as the general message of the hymn's stanzas, remain the core of what is now essentially a brand new song.

As I intend to share the song with my local church, I needed to whip up a demo of it.  Last night I spent about an hour tracking acoustic guitar, electric guitar, and bass guitar.  After my son Aidan finished watching a movie with his friends, I asked him to come upstairs and lay down a drum track.  Then this morning, I was able to get my wife Amy in front of a microphone to track the lead vocals, with me laying down some harmonies immediately thereafter.

The result of those three-and-a-half hours of recording and mixing are available on my SoundCloud page:

I've licensed the song under the Creative Commons Attribution 3.0 Unported License.  And as part of my commitment to reducing barriers to adoption for music truly written for the church (rather than for a paycheck), I've posted the sheet music for the song to my GitHub repository.

And here are the lyrics for the song:

O For a Thousand Tongues All-gracious Master, glorious God, Give me the words to proclaim. Spread thru the whole earth, here and abroad, The honor of Your holy name. Father, You give me the choice, But Your grace compels me to lift up my voice. If I was mute, I'd still make joyful noise to Thee. O, for a thousand tongues to sing! Jesus, your name calms the deepest of fears. You bid every sorrow to cease. Your mercy is music in this sinner's ears— Your love is the source of my peace. Savior, You knew all along That you'd trade perfection for all I'd do wrong. Lord, may my life make a beautiful song to Thee. O, for a thousand tongues to sing! O, for a thousand tongues to sing my great Redeemer's praise! Sing of the glories of my King; the triumph of His grace! Jesus you've broken the power of sin. Your blood sets the prisoners free. Dying you saved us, then rising again Accomplished supreme victory! O, for a thousand tongues to sing our great Redeemer's praise! Sing of the glories of our King; the triumph of His grace! Your church in heav'n and earth below, this sacrifice we bring! O, for a thousand tongues to sing. O, for a thousand tongues to sing. O, for a thousand tongues to sing. Spirit of God, fill this place. Write on our hearts songs of mercy and grace. Oh, God, we're desperate to give every praise to Thee. O, for a thousand tongues to sing! O, for a thousand tongues to sing! O, for a thousand tongues to sing!

Wednesday, July 15, 2020

Ambassadors for Christ?

Ugh. Today, besides feeling physically subpar (hello, tick bite!), I feel spiritually defiled. In a moment of weakness and morbid curiosity, I made the mistake of reading some of the Facebook feeds of a handful of people in my church. I think we might have a problem.

The Word of God tells Christians that they are citizens of a new kind of Kingdom. This Kingdom is not one with physical, geographical boundaries, a two-party political system, checks and balances, and a (merely) 200-year-old governing document. It's God's Kingdom, existing outside the physical Universe and governed by God Himself:
But our citizenship is in heaven, and from it we await a Savior, the Lord Jesus Christ, who will transform our lowly body to be like his glorious body, by the power that enables him even to subject all things to himself. [Phillippians 3:20-21 ESV]
One cool thing is that when we become citizens of that Kingdom, God leaves us in place, planted in the physical realm to serve His purposes. Our job? To be His ambassadors:
Therefore, we are ambassadors for Christ, God making his appeal through us. We implore you on behalf of Christ, be reconciled to God. [2 Corinthians 5:20 ESV]
But as I read post after hate-filled post on Facebook, it became crystal clear to me that either the Kingdom has fewer citizens than I'd hoped, or those citizens grossly misunderstand their roles as ambassadors. Were I to judge by what I saw (and have heard), I would calculate that "ambassador for Christ" has come to mean "culture warrior". We Christians line up on political, sociological, idealogical, racial, or any other "-al" line we can find, dig in our heels, crane our necks and bend our ears for the sound of the charge!

What if we revisit the idea of ambassador-ship with a new objective: to make—by our every word, thought, and deed—the Kingdom of heaven and the God who governs it so glorious and attractive that its opponents simply emigrate to it. No need for blood shed. No anger. No insults. Just love and faithful representationambassadorshipof the King of Kings.

Wednesday, August 28, 2019

Oreos and Milk Done Right

For far too long, I've held an absolutely essential piece of knowledge—a life skill that every person should have—and I've failed to share it with the world.  Today I repent of that, beg your forgiveness, and offer reparation by sharing with you now this critical information.  Today, I want to tell you the proper way to eat Oreos with milk.

It goes without saying that in order to accomplish this, you'll need Oreos, milk, and a cup or mug to contain the milk.  But lest we assume too much, let me clarify some things.
  • These instructions assume you can eat an entire Oreo in one mouthful.  If you can't, you're clearly not built for eating Oreos and should probably take up Veggie Straws or something else instead.
  • Don't use a cup or mug that's too small.  You need at least a depth of milk sufficient to completely submerge the cookie.  And you need enough width in your container to do the same.
  • Don't use skim milk.  The higher the fat content of the milk, the better.  I strongly suggest whole milk.  And don't use warm milk.  You want your milk as cold as possible.  If, when you pour your milk, it looks like Elmer's white glue and chills the hand that holds your cup or mug, that's a good sign.
  • Don't use fake Oreos.  Seriously.  I'm all for generic brands of most things, but ... no.
Okay, on to the life-changing instructions.

First, grasp an Oreo cookie between your thumb and forefinger, with each making contact on one of the Oreo logos on either side of the cookie.  (If you don't see an Oreo logo, you're using fake Oreos.  And I literally just told you not to do that.)  Put some real pressure on the cookie with your fingers—not enough to crush it, but pretty close to it.  Now, submerge the Oreo completely in the milk while maintaining this pressure.  Yes, your fingers are going to get wet—deal with it.

All this might sound pretty obvious, but as any seasoned Oreo-milk-dunker knows, the trick is figuring out how long to keep the cookie submerged.  And you might be wondering why must we maintain this solid finger pressure on the cookie.  After all, they hardly weigh anything and are unlikely to attempt to escape our grasp on their own.

The answer lies in the sheer importance of getting these two seemingly incompatible foods—one a natural byproduct by which nearly all mammals are initially nursed; the other a completely unnatural, highly processed junk food—to unite properly at or near the molecular level[*].  If your Oreo is in the milk for too short a time, then what was the point?  You're merely eating a damp Oreo.  But to linger for too long will have you watching your disintegrating cookie's disparate parts sinking out of sight into the milky white abyss.

As it turns out, the pressure you're putting on those Oreo logos gives you all the tactile feedback you need to know exactly when to remove the cookie from the milk.  As soon as that logo begins a crush a bit under your firm-but-non-damaging bit of finger pressure, the time is right.  Remove the cookie from the milk, shove it into your awaiting mouth, and rejoice as you've never rejoiced before.

Once again, this is not for those who lack a certain degree of fortitude.  Your thumb and forefinger will get wet with milk.  They will also pick up the debris of the crushed Oreo logos.  You'll have to open your mouth a bit wider than high society might advise.  Sometimes, doing things properly involves some risk-taking.  This is such a time.

Now, there's no need to e-mail me your thanks.  It's my great pleasure to serve my fellow man in this way, sharing the results of my years of experimentation in this field.  My hope is simply that you'll do the same.

Oh!  But I nearly forgot the final step in the instructions:  grab another cookie and repeat!

[*] No real scientists were consulted while authoring this article.

Monday, March 4, 2019

Self-publishing my worship songs

I've talked about it forever, but this past weekend I decided to finally act.  I've setup a GitHub repository to which I intend to commit sheet music for the various Christian worship songs that I compose.  You can visit the project at:
I've added the music from my recent "Shepherd of My Soul" composition (which my worship team at Providence introduced to our congregation brilliantly this past weekend, I might add!), plus a few other songs.  I also have placeholders for several other tunes that I'm committing to self-publish here, too.

Those who know me well know that I can be pretty outspoken about copyrights and licensing and such, especially as regards music written (at least ostensibly) "for God" or "for the Church".  This is why every worship song I've written carries a Creative Commons license.  But while it's all well and good to say, "My songs I offer without restrictive licensing," it matters little if there are other barriers to sharing and re-use.  This self-publishing effort is a way for me to remove some more of those barriers.  I genuinely want folks to take and use these songs with minimal impediment if they find them worth taking and using, and I'm willing to put in the extra effort to encourage as much.

My goal is to keep for each song MuseScore files withat a minimumlead sheets for the songs, plus MusicXML and PDF exports of the same.  I could, of course, just use PDFs, but that would discourage getting corrections submitted by folks who are far better at musical transcription than I am.  It would also prevent easy transposition of the songs into alternate keys.  At the moment, you can load the score into MuseScore, select the whole score (Control-A), and then use the Notes > Transpose... menu to put the song in whatever key you wish.  It's that simple!  Someday I may also include links to recorded demos of the songs, specific hints for individual instruments, etc.

May God bless this tiny little human's effort to make His praise even more widespread.

Friday, March 1, 2019

"Feel Just Fine"

Perhaps one of the most enjoyable musical recording experiences I've ever been a part of began in June 2009, when friend and former bandmate Christopher Bunn emailed me to say that he had an opportunity to contribute a song for an independent film project to which he had personal connections and wanted to rope me into the process.  Naturally, I was all in!

We started with his demo of a song he'd written called "Feel Just Fine", and then iterated lyrically and musically across the miles (me in North Carolina, he in California, and the Internet in between) for about three months, passing around emailed suggestions and audio files and such.  I held the master recordings (as a Cakewalk Sonar project), and tracked all the instruments plus my own and my wife's background vocals.  Christopher was taking drops of the backing stuff from me, tracking his own lead vocals atop them, and then sending me back the vocal tracks.  All in all, the process ran incredibly smoothly, even for a time when "broadband Internet" wasn't anything like the blazing speeds we enjoy today.  We ended up keeping most of Christopher's original song, but dropped a verse that didn't fit as well thematically with the film and introduced a new bridge section that I wrote.

As I review my email history, it looks like it was December 2009 when we learned that the filmmakers were interested in our song, but it wouldn't be until several years later that we finally got to see the finished film, Rise of the Fellowship, and hear our song playing in full during the credit roll.  Some time after the film itself released, the producers released the film's soundtrack, and now you, too, can hear "Feel Just Fine".

Christopher Bunn - original song concept, lead vocals
C. Michael Pilato - arrangement, all instruments, background vocals
Amy Pilato - angelic background vocals
Christopher has his original demo of the song posted online, too.  Check it out at

Tuesday, February 26, 2019

"Shepherd of My Soul"

While on a recent out-of-state trip to visit family, I found myself mentally reflecting on the twenty-third Psalm.  You know the one I'm talking about:
The Lord is my shepherd; I shall not want.  He maketh me to lie down in green pastures: he leadeth me beside the still waters.  He restoreth my soul: he leadeth me in the paths of righteousness for his name's sake.  Yea, though I walk through the valley of the shadow of death, I will fear no evil: for thou art with me; thy rod and thy staff they comfort me.  Thou preparest a table before me in the presence of mine enemies: thou anointest my head with oil; my cup runneth over.  Surely goodness and mercy shall follow me all the days of my life: and I will dwell in the house of the Lord for ever.
Yes, I realize that I posted the King James Version above.  I almost never use that translation myself, but I can't deny that as a child every bit of the Holy Bible that I memorized was memorized from that translation.  And that childhood memorization turns out to have been important, because I was reflecting on the psalm while in a musical frame of mind ... and while driving my family's minivan around West Virginia!

So with no instrument in hand (unless the steering wheel counts...) I began morphing Psalm 23 into a singable tune.  By repeating the song in my mind over and over again, I managed to retain the concept until I was able to get back to North Carolina and see how it felt over an instrumental accompaniment.  A few days later, I recorded a demo version (with my son Aidan providing the drum tracks) to capture the idea.  Here's that demo version, imperfections and all:

In an unexpected twist, I plan to introduce the song to my church family this coming Sunday.  This fact pushed me to try my hand at using MuseScore 2 to transcribe the vocal parts for the song so I can get the rest of my worship team up to speed on the song quickly.  Writing sheet music is still not something I claim as a talent of mine, but MuseScore certainly makes it easy enough, especially since it runs flawlessly on the Linux and Windows platforms that occupy all my desktop computing devices.  If you care, here's what I whipped up in MuseScore:

Finally, here are the song's lyrics.  Feel free to sing along!
Shepherd of My Soul

You are my Shepherd.  I'll want for nothing.
You make me lie down in pastures of green.
Beside still waters and down paths of righteousness
All for Your name's sake, Shepherd, You lead.

You restore my soul. You restore my soul.
Surely goodness and mercy will follow.
And I will dwell in the house of the Lord forever.
There with my Shepherd, the Shepherd of my soul.

Even when walking down through the valley,
There in death's shadow no evil I'll fear.
You're always with me.  Your rod and staff comfort me.
Jesus, my Shepherd, You're always near.

You restore my soul. You restore my soul.
Surely goodness and mercy will follow.
And I will dwell in the house of the Lord forever.
There with my Shepherd, the Shepherd of my soul.

You set a table before me with my enemies all around.
Let your anointing fall on me.  Let my cup overflow with your pow'r.

© 2019 C. Michael Pilato; License: cc-by-3.0

UPDATE (2/28/19): We ran the new song at our full worship team practice last night, and thanks to the extra layers of intrumentation and my super-talented fellow singers, it sounded A-MA-ZING!  I'm so excited for Sunday!