Last Updated: February 25, 2016
·
8.181K
· austinginder

Podcast in Wordpress using custom post types

This is a some rough code to setup a podcast from scratch. If someone is looking to create a plugin, this would be a good starting point.

I'm using multisite so I moved most of the url paths into the options section so I can configure them manually. The Podcast http location is a multisite url fix as ipad/iphones have trouble streaming from the /files folder.

Picture

theme-options.php

<?php

// Theme Options
// Chruch of the Word International
// http://www.churchoftheword.com

$themename = "Options";
$shortname = "cwi";
$version = "1.0";

// Create theme options
global $options;
$options = array (

array( "name" => "General",
 "type" => "section"),

array( "type" => "open"),

array( "name" => "iTunes Podcast",
 "desc" => "",
 "id" => $shortname."_podcast",
 "type" => "text",
 "std" => ""),

array( "name" => "Short Description",
 "desc" => "",
 "id" => $shortname."_shortdesc",
 "type" => "textarea",
 "std" => ""),

array( "name" => "Podcast local path",
 "desc" => "",
 "id" => $shortname."_podcastpath",
 "type" => "textarea",
 "std" => ""),

array( "name" => "Podcast file location",
 "desc" => "",
 "id" => $shortname."_podcastfile",
 "type" => "textarea",
 "std" => ""),

array( "name" => "Podcast http location",
 "desc" => "",
 "id" => $shortname."_podcasthttp",
 "type" => "textarea",
 "std" => ""),

array( "name" => "Podcast Title in iTunes",
 "desc" => "",
 "id" => $shortname."_podcasttitle",
 "type" => "text",
 "std" => ""),

array( "type" => "close"),

);

function p2h_add_admin() {

    global $themename, $shortname, $options;

    if ( isset ( $_GET['page'] ) && ( $_GET['page'] == basename(__FILE__) ) ) {

        if ( isset ($_REQUEST['action']) && ( 'save' == $_REQUEST['action'] ) ){

            foreach ( $options as $value ) {
                if ( array_key_exists('id', $value) ) {
                    if ( isset( $_REQUEST[ $value['id'] ] ) ) {
                        update_option( $value['id'], $_REQUEST[ $value['id'] ]  );
                    }
                    else {
                        delete_option( $value['id'] );
                    }
                }
            }
        header("Location: admin.php?page=".basename(__FILE__)."&saved=true");
        }
        else if ( isset ($_REQUEST['action']) && ( 'reset' == $_REQUEST['action'] ) ) {
            foreach ($options as $value) {
                if ( array_key_exists('id', $value) ) {
                    delete_option( $value['id'] );
                }
            }
        header("Location: admin.php?page=".basename(__FILE__)."&reset=true");
        }
    }

add_menu_page($themename, $themename, 'administrator', basename(__FILE__), 'p2h_admin');
add_submenu_page(basename(__FILE__), $themename . ' Options', 'Theme Options', 'administrator',  basename(__FILE__),'p2h_admin'); // Default
}

function p2h_add_init() {

$file_dir=get_bloginfo('template_directory');
wp_enqueue_style("p2hCss", $file_dir."/theme-options.css", false, "1.0", "all");

}

function p2h_admin() {

    global $themename, $shortname, $version, $options;
    $i=0;

    if ( isset ($_REQUEST['saved']) && ($_REQUEST['saved'] ) )echo '<div id="message" class="updated fade"><p><strong>'.$themename.' settings saved.</strong></p></div>';
    if ( isset ($_REQUEST['reset']) && ($_REQUEST['reset'] ) ) echo '<div id="message" class="updated fade"><p><strong>'.$themename.' settings reset.</strong></p></div>';

?>

<div class="wrap ">
<div class="options_wrap">
<h2 class="settings-title"><?php echo $themename; ?></h2>
<form method="post">

<?php foreach ($options as $value) {
switch ( $value['type'] ) {
case "section":
?>
    <div class="section_wrap">
    <h3 class="section_title"><?php echo $value['name']; ?></h3>
    <div class="section_body">

<?php
break;
case 'text':
?>

    <div class="options_input options_text">

        <span class="labels"><label for="<?php echo $value['id']; ?>"><?php echo $value['name']; ?></label></span>
        <input name="<?php echo $value['id']; ?>" id="<?php echo $value['id']; ?>" type="<?php echo $value['type']; ?>" value="<?php if ( get_option( $value['id'] ) != "") { echo stripslashes(get_option( $value['id'])  ); } else { echo $value['std']; } ?>" />
        <div class="options_desc"><?php echo $value['desc']; ?></div>
    </div>

<?php
break;
case 'textarea':
?>
    <div class="options_input options_textarea">
        <span class="labels"><label for="<?php echo $value['id']; ?>"><?php echo $value['name']; ?></label></span>
        <textarea name="<?php echo $value['id']; ?>" type="<?php echo $value['type']; ?>" cols="" rows=""><?php if ( get_option( $value['id'] ) != "") { echo stripslashes(get_option( $value['id']) ); } else { echo $value['std']; } ?></textarea>
        <div class="options_desc"><?php echo $value['desc']; ?></div>
    </div>

<?php
break;
case 'select':
?>
    <div class="options_input options_select">
        <span class="labels"><label for="<?php echo $value['id']; ?>"><?php echo $value['name']; ?></label></span>
        <select name="<?php echo $value['id']; ?>" id="<?php echo $value['id']; ?>">
        <?php foreach ($value['options'] as $option) { ?>
                <option <?php if (get_option( $value['id'] ) == $option) { echo 'selected="selected"'; } ?>><?php echo $option; ?></option><?php } ?>
        </select>
        <div class="options_desc"><?php echo $value['desc']; ?></div>
    </div>

<?php
break;
case "radio":
?>
    <div class="options_input options_select">
        <span class="labels"><label for="<?php echo $value['id']; ?>"><?php echo $value['name']; ?></label></span>
          <?php foreach ($value['options'] as $key=>$option) {
            $radio_setting = get_option($value['id']);
            if($radio_setting != ''){
                if ($key == get_option($value['id']) ) {
                    $checked = "checked=\"checked\"";
                    } else {
                        $checked = "";
                    }
            }else{
                if($key == $value['std']){
                    $checked = "checked=\"checked\"";
                }else{
                    $checked = "";
                }
            }?>
            <input type="radio" name="<?php echo $value['id']; ?>" value="<?php echo $key; ?>" <?php echo $checked; ?> /><?php echo $option; ?><br />
            <?php } ?>
        <div class="options_desc"><?php echo $value['desc']; ?></div>
    </div>

<?php
break;
case "checkbox":
?>
    <div class="options_input options_checkbox">
        <?php if(get_option($value['id'])){ $checked = "checked=\"checked\""; }else{ $checked = "";} ?>
        <input type="checkbox" name="<?php echo $value['id']; ?>" id="<?php echo $value['id']; ?>" value="true" <?php echo $checked; ?> />
        <label for="<?php echo $value['id']; ?>"><?php echo $value['name']; ?></label>
        <div class="options_desc"><?php echo $value['desc']; ?></div>
     </div>

<?php
break;
case "close":
$i++;
?>
<span class="submit"><input name="save<?php echo $i; ?>" type="submit" value="Save Changes" /></span>
</div><!--#section_body-->
</div><!--#section_wrap-->

<?php break;
}
}
?>

<input type="hidden" name="action" value="save" />
<span class="submit">
<input name="save" type="submit" value="Save All Changes" />
</span>
</form>

<form method="post">
<span class="submit">
<input name="reset" type="submit" value="Reset All Options" />
<input type="hidden" name="action" value="reset" />
</span>
</form>
<br/>
</div><!--#options-wrap-->

</div><!--#wrap-->
<?php
}
add_action('admin_init', 'p2h_add_init');
add_action('admin_menu' , 'p2h_add_admin');
?>    

This is just some default styling for the theme's options page.

theme-options.css

.wrap{
width:98%;
}

.options_wrap h2{
margin-bottom:20px;
}
.options_wrap{
 width:750px;
 float:left;
 line-height:1.5em;
 height:auto;
}

.section_wrap{
 margin-bottom:35px;
 float:left;
 width:750px;
}

.section_body{
 border:1px solid #ddd;
 border-top:0;
 background:#fff;
 width:748px;
 float:left;
-moz-border-radius:0 0 6px 6px;

}

h3.section_title{
-moz-border-radius:6px 6px 6px 6px;
background:#F1F1F1;
border:1px solid #DDD;
color:#4E4C41;
cursor:pointer;
margin:0;
padding:7px 10px;
clear:both;
}

h3.section_title:hover{
background-color:#F2f2f2;
border:1px solid #CFCFCF;
}

h3.open {
-moz-border-radius:6px 6px 0 0;
}

h3.section_title span{
color:#AAAAAA;
float:right;
}

.options_input {
 padding:20px;
 clear:both;
 overflow:hidden;
 border-bottom: 1px solid #DDD;
}

.options_desc{
color:#777777;
float:right;
padding:15px;
width: 506px;
clear: both;
margin: 0 0 0 150px;
}

.labels{
 display:block;
 margin-bottom:5px;
 color:#555;
}

.options_input input[type="text"], .options_input select{
 width:536px;
 padding:5px;
 color:#666;
 background:#FFF;
 border-color:#DFDFDF;
}
.options_input input:focus, .options_input textarea:focus{
 background:#fff;
}
.options_input textarea{
 float: left;
 width:536px;
 height:135px;
 padding:5px;
 color:#666;
 background:#FFF;
 border-color:#DFDFDF;
}

 span.submit{
 float:left;
 margin:0 30px 30px 0;
 padding:0;
 width:15%;
}

 .section_wrap span.submit{
 float:left;
 padding:20px;
 width:15%;
}    

Alright so the functions.php in a nutshell sets up a new post type for Audio. Each time a new Audio files is added or updated it writes out a new podcast.xml file based on it's configuration.

Picture

functions.php

<?php

//Theme Options
require_once ('theme-options.php');

function register_my_menus() {
  register_nav_menus(
    array( 'header-menu' => __( 'Navigation Menu' ),
                     'locations-menu' => __( 'Locations Menu' ))
  );
}
add_action( 'init', 'register_my_menus' );

/* begin custom post type */ 

add_action('init', 'audio_register');

function audio_register() {

    $labels = array(
        'name' => _x('Audio', 'post type general name'),
        'singular_name' => _x('Audio', 'post type singular name'),
        'add_new' => _x('Add New', 'audio'),
        'add_new_item' => __('Add New Audio'),
        'edit_item' => __('Edit Audio'),
        'new_item' => __('New Audio'),
        'view_item' => __('View Audio'),
        'search_items' => __('Search Audio'),
        'not_found' =>  __('Nothing found'),
        'not_found_in_trash' => __('Nothing found in Trash'),
        'parent_item_colon' => ''
    );

    $args = array(
        'labels' => $labels,
        'public' => true,
        'publicly_queryable' => true,
        'show_ui' => true,
        'query_var' => true,
        'rewrite' => true,
        'capability_type' => 'post',
        'hierarchical' => false,
        'menu_position' => null,
        'supports' => array('title','editor','thumbnail')
      ); 

    register_post_type( 'audio' , $args );
}

register_taxonomy("series", array("audio"), array("hierarchical" => true, "label" => "Series", "singular_label" => "Series", "rewrite" => true));
register_taxonomy("speakers", array("audio"), array("hierarchical" => true, "label" => "Speakers", "singular_label" => "Speakers", "rewrite" => true));
register_taxonomy("years", array("audio"), array("hierarchical" => true, "label" => "Years", "singular_label" => "Years", "rewrite" => true));

add_action("admin_init", "admin_init");

function admin_init(){
  add_meta_box("audio_meta", "Audio Details", "audio_meta", "audio", "side", "low");
}

function audio_meta() {
  global $post;
  $custom = get_post_custom($post->ID);
  $audio_file_english = $custom["audio_file_english"][0];
  echo '<input type="hidden" name="mytheme_meta_box_nonce" value="', wp_create_nonce(basename(__FILE__)), '" />';
  ?>
  <p><label>English Audio File:</label><br />
  <input type="text" name="audio_file_english" id="audio_file_english" value="<?php echo $audio_file_english; ?>" style="width:258px">
  <input type="button" name="pdf_button" id="pdf_button" value="Browse" class="browse" style="width:258px"></p> 
  <?php
}

function my_admin_scripts() {
wp_enqueue_script('media-upload');
wp_enqueue_script('thickbox');
wp_register_script('my-upload', get_bloginfo('template_url') . '/js/audio-upload.js', array('jquery','media-upload','thickbox'));
wp_enqueue_script('my-upload');
}
function my_admin_styles() {
wp_enqueue_style('thickbox');
}
add_action('admin_print_scripts', 'my_admin_scripts');
add_action('admin_print_styles', 'my_admin_styles');

add_action('save_post', 'save_details');

function save_details(){
  global $post;

  if( $post->post_type == "audio" ) {

        if(isset($_POST["audio_file_english"])) {
            update_post_meta($post->ID, "audio_file_english", $_POST["audio_file_english"]);
        }

  }
}

add_filter('upload_dir', 'ml_media_upload_dir');

/**
 * Changes the upload directory to what we would like, instead of what WordPress likes.
 */
function ml_media_upload_dir($upload) {
  global $post;

  //if( $post->post_type == "audio" ) {
    $upload_base_dir = str_replace("/wp-content/uploads","",$upload['basedir']);
    $upload_base_url = str_replace("/wp-content/uploads","",$upload['baseurl']);
    //echo $upload_base_dir. "
    //";
    //echo $upload_base_url. "
    //";
    $upload['subdir']   = '/audio';
    $upload['path']     = $upload_base_dir . '/audio';
    $upload['url']      = $upload_base_url . '/audio';
    $upload['basedir']  = $upload_base_dir;
    $upload['baseurl']  = $upload_base_url;
  //}
  return $upload;

}

/* end custom post types */ 

function update_podcast($post_id) {
    global $post;

    // verify if this is an auto save routine. If it is our form has not been submitted, so we dont want to do anything
    if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) 
        return $post_id;

    // OK, we're authenticated: we need to find and save the data
    $post = get_post($post_id);
    if ($post->post_type == 'audio') { 

  require_once('_/inc/getid3/getid3.php');

    /* RSS 2.0 MP3 SUBSCRIPTION FEED

         "mp3feed.php" - version 1.1
         2005 - Canton Becker - canton@ontology.com

         Yeah, it's pretty basic. 
         But it's free.
         Here's where to get the latest version:
         http://www.ontology.com/canton/projects

         Use at your own risk, or don't use it at all...

    */

    // CONFIGURE THESE VARIABLES:

    // actual place where your mp3s live on your server's filesystem. TRAILING SLASH REQ'D.
    $musicDirectory="";

    // corresponding web URL for accessing the music directory. TRAILING SLASH REQ'D.
    $musicURL= get_option('cwi_podcasthttp');

    // name your feed
    $feedTitle = get_option('cwi_podcasttitle');

    // where every entry in your feed will link to, sort of like a "for more info" link
    $feedLink="http://www.churchoftheword.com";

    // describe your feed
    $feedDescription="Church of the Word Sermon Podcast";

    //Gets the current day for the copyright
    $currentday = getdate();

    // outline your copyright / creative commons / licensing terms
    $feedCopyright="Copyright " . $currentday[year] . " Church of the Word International, Inc. All rights reserved";

    // your email... if you dare!
    $authorEmail="info@churchoftheword.com";

    // how often should feed readers check for new material (in seconds) -- mostly ignored by readers.
    $ttl = 1440;



    // END OF STUFF YOU NEED TO CONFIGURE!

    /* Save this .php file wherever you like on your webserver.
       The URL for this .php file *is* the URL of your podcast feed
       for subscription purposes.

       For every mp3 that you want to podcast, create a correspondingly
       named .txt file that contains a little bit of information about
       the song. Just one or two lines is good.

       It can include basic HTML. My text files are usually something like this:

            Trance-techno, January 2005. Swirling strings and happy pads.
            <?xml version=\"1.0\" encoding=\"utf-8\"?>\r
    */

    $rss="<?xml version=\"1.0\" encoding=\"utf-8\"?>\r
<rss xmlns:itunes=\"http://www.itunes.com/dtds/podcast-1.0.dtd\" version=\"2.0\">

  <channel>

    <title>$feedTitle</title>
    <link>$feedLink</link>
    <description>$feedDescription</description>
    <language>en</language>
    <copyright>$feedCopyright</copyright>
    <ttl>$ttl</ttl>

    <!-- iTunes-specific channel tags //--> 
    <itunes:author>Church of the Word International</itunes:author> 
    <itunes:subtitle>Weekly podcast</itunes:subtitle> 
    <itunes:summary>$feedDescription</itunes:summary> 
    <itunes:owner> 
        <itunes:name>Church of the Word Sermon Podcast</itunes:name> 
        <itunes:email>$authorEmail</itunes:email> 
    </itunes:owner> 
    <itunes:category text=\"Religion\"> 
        <itunes:category text=\"Christianity\" /> 
    </itunes:category> 
    <itunes:explicit>no</itunes:explicit>
    <!-- end iTunes-specific channel tags //-->";

      $post_per_page = 225; // -1 shows all posts
      $args = array(
        'post_type' => 'audio',
        'orderby' => 'date',
        'order' => 'DESC',
        'posts_per_page' => $post_per_page
      );
        $temp = $wp_query;
      $wp_query= null;
        $wp_query = new WP_Query($args);

        while ($wp_query->have_posts()) : $wp_query->the_post(); 

            $custom = get_post_custom($post->ID);
            $file = $custom["audio_file_english"][0];
            $local_path = get_option('cwi_podcastpath');
            $local_url = site_url()."/";
            $localfile = str_replace($local_url,$local_path,$file);
            $file = str_replace($local_url,$musicURL,$file);
            if (file_exists($localfile)) {
                $getID3 = new getID3;
                // Analyze file and store returned data in $ThisFileInfo
                    $ThisFileInfo = $getID3->analyze($localfile);
                $length = filesize($localfile);
                $duration = @$ThisFileInfo['playtime_string']; 
                $title = get_the_title();
                $datetime = get_the_time('D, j M Y H:j:s e', $post->ID);
                $speakers = strip_tags(get_the_term_list( $post->ID, 'speakers','',' and ','' )); 
                $description = get_the_content();
                $rss .=" 
         <item>
            <title>$title</title>
            <link>$feedLink</link>
            <author>$authorEmail</author>
            <category>Christianity</category>
            <itunes:summary>$description</itunes:summary>
            <itunes:author>$speakers</itunes:author>
            <pubDate>$datetime</pubDate>
            <enclosure url=\"$file\" length=\"$length\" type=\"audio/mpeg\" />
            <guid>$file</guid>
            <itunes:duration>$duration</itunes:duration>
            <itunes:category> text=\"Christianity\"</itunes:category> 
            <itunes:explicit>no</itunes:explicit> 
         </item> 

                  ";
        }
        endwhile;

        $wp_query = null; 
        $wp_query = $temp;
    $rss .="
  </channel>
</rss>";

    // Write out the new file
    $path=get_option('cwi_podcastfile');
    $filenum=fopen($path,"w"); 
    fwrite($filenum,$rss); 
    fclose($filenum);
    }
}

add_action('save_post', 'update_podcast');

?>    

js/audio-upload.js

jQuery(document).ready(function() {

    jQuery('.browse').click(function() {
     var current_field = jQuery(this).parent('p').children('input[type=text]');
     window.send_to_editor = function(html) {
         imgurl = jQuery(html).attr('src') || jQuery(html).find('img').attr('src') || jQuery(html).attr('href');
         jQuery(current_field).val(imgurl);
         tb_remove();
     }

     tb_show('', 'media-upload.php?type=audio&amp;TB_iframe=true');

     return false;

    });

});

Here are various view templates for recent, series, speakers and years.

index-recent.php

<?php
/*
Template Name: Recent Template
*/
get_header(); ?>

    <div id="page-title">
            <h2>Recent Messages</h2>
    </div>

    <?php 
    $temp = $wp_query;
  $paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
  $post_per_page = 100; // -1 shows all posts
  $args=array(
    'post_type' => 'audio',
    'orderby' => 'date',
    'order' => 'DESC',
    'paged' => $paged,
    'posts_per_page' => $post_per_page
  );
    $my_query = new WP_Query($args);

    if ($my_query->have_posts()) : while ($my_query->have_posts()) : $my_query->the_post();     
        $custom = get_post_custom($post->ID);  
        $audio_file_english = $custom["audio_file_english"][0];
        ?>

        <article <?php post_class() ?> id="post-<?php the_ID(); ?>">

        <?php get_template_part( 'content', 'media' ); ?>

        </article>

    <?php endwhile; ?>

    <?php include (TEMPLATEPATH . '/_/inc/nav.php' ); ?>

    <?php else : ?>

        <h2>Not Found</h2>

    <?php endif; ?>

<?php get_footer(); ?>

index-series.php

<?php
/*
Template Name: Series Template
*/
get_header(); ?>

    <?php if (have_posts()) : while (have_posts()) : the_post(); ?>

        <article <?php post_class() ?> id="post-<?php the_ID(); ?>">

            <h2><?php the_title(); ?></h2>

            <div class="entry">
                <ul class="list">
                    <?php
                    $args = array(
                      'orderby' => 'name',
                      'order' => 'ASC',
                      'taxonomy' => 'series'
                       );

                    $categories=get_categories($args);
                      foreach($categories as $category) { 
                        $id = $category->term_id;
                        $category_link = get_category_link( $id );

                    ?>
                    <li> <a href="<?php echo get_term_link($category->slug,'series') ?>"><?php echo $category->cat_name ?> (<?php echo $category->count ?>)</a></li>
                    <? } ?> 
                    </ul>
                <?php the_content(); ?>
            </div>

        </article>

    <?php endwhile; ?>

    <?php include (TEMPLATEPATH . '/_/inc/nav.php' ); ?>

    <?php else : ?>

        <h2>Not Found</h2>

    <?php endif; ?>

<?php get_footer(); ?>

index-speakers.php

<?php
/*
Template Name: Speakers Template
*/
get_header(); ?>

    <?php if (have_posts()) : while (have_posts()) : the_post(); ?>

        <article <?php post_class() ?> id="post-<?php the_ID(); ?>">

            <h2><?php the_title(); ?></h2>

            <div class="entry">
                <ul class="list">
                    <?php
                    $args = array(
                      'orderby' => 'name',
                      'order' => 'ASC',
                      'taxonomy' => 'speakers'
                       );

                    $categories=get_categories($args);
                      foreach($categories as $category) { 
                        $id = $category->term_id;
                        $category_link = get_category_link( $id );

                    ?>
                    <li> <a href="<?php echo get_term_link($category->slug,'speakers') ?>"><?php echo $category->cat_name ?> (<?php echo $category->count ?>)</a></li>
                    <? } ?> 
                    </ul>
                <?php the_content(); ?>
            </div>

        </article>

    <?php endwhile; ?>

    <?php include (TEMPLATEPATH . '/_/inc/nav.php' ); ?>

    <?php else : ?>

        <h2>Not Found</h2>

    <?php endif; ?>

<?php get_footer(); ?>

index-years.php

<?php
/*
Template Name: Years Template
*/
get_header(); ?>

    <?php if (have_posts()) : while (have_posts()) : the_post(); ?>

        <article <?php post_class() ?> id="post-<?php the_ID(); ?>">

            <h2><?php the_title(); ?></h2>

            <div class="entry">
                <ul class="list">
                    <?php
                    $args = array(
                      'orderby' => 'name',
                      'order' => 'ASC',
                      'taxonomy' => 'years'
                       );

                    $categories=get_categories($args);
                      foreach($categories as $category) { 
                        $id = $category->term_id;
                        $category_link = get_category_link( $id );

                    ?>
                    <li> <a href="<?php echo get_term_link($category->slug,'years') ?>"><?php echo $category->cat_name ?> (<?php echo $category->count ?>)</a></li>
                    <? } ?> 
                    </ul>
                <?php the_content(); ?>
            </div>

        </article>

    <?php endwhile; ?>

    <?php include (TEMPLATEPATH . '/_/inc/nav.php' ); ?>

    <?php else : ?>

        <h2>Not Found</h2>

    <?php endif; ?>

<?php get_footer(); ?>

index-listen.php This template is used for the pop up listen box

<?php
/*
Template Name: Listen Template
*/
?>
<!DOCTYPE html>

<!--[if lt IE 7 ]> <html class="ie ie6 no-js" <?php language_attributes(); ?>> <![endif]-->
<!--[if IE 7 ]>    <html class="ie ie7 no-js" <?php language_attributes(); ?>> <![endif]-->
<!--[if IE 8 ]>    <html class="ie ie8 no-js" <?php language_attributes(); ?>> <![endif]-->
<!--[if IE 9 ]>    <html class="ie ie9 no-js" <?php language_attributes(); ?>> <![endif]-->
<!--[if gt IE 9]><!--><html class="no-js" <?php language_attributes(); ?>><!--<![endif]-->
<!-- the "no-js" class is for Modernizr. -->

<head profile="http://gmpg.org/xfn/11">

    <meta charset="<?php bloginfo('charset'); ?>">

    <!-- Always force latest IE rendering engine (even in intranet) & Chrome Frame -->
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">

    <title>
           <?php
              if (function_exists('is_tag') && is_tag()) {
                 single_tag_title("Tag Archive for &quot;"); echo '&quot; - '; }
              elseif (is_archive()) {
                 wp_title(''); echo ' Archive - '; }
              elseif (is_search()) {
                 echo 'Search for &quot;'.wp_specialchars($s).'&quot; - '; }
              elseif (!(is_404()) && (is_single()) || (is_page())) {
                 wp_title(''); echo ' - '; }
              elseif (is_404()) {
                 echo 'Not Found - '; }
              if (is_home()) {
                 bloginfo('name'); echo ' - '; bloginfo('description'); }
              else {
                  bloginfo('name'); }
              if ($paged>1) {
                 echo ' - page '. $paged; }
           ?>
    </title>

    <meta name="title" content="<?php
              if (function_exists('is_tag') && is_tag()) {
                 single_tag_title("Tag Archive for &quot;"); echo '&quot; - '; }
              elseif (is_archive()) {
                 wp_title(''); echo ' Archive - '; }
              elseif (is_search()) {
                 echo 'Search for &quot;'.wp_specialchars($s).'&quot; - '; }
              elseif (!(is_404()) && (is_single()) || (is_page())) {
                 wp_title(''); echo ' - '; }
              elseif (is_404()) {
                 echo 'Not Found - '; }
              if (is_home()) {
                 bloginfo('name'); echo ' - '; bloginfo('description'); }
              else {
                  bloginfo('name'); }
              if ($paged>1) {
                 echo ' - page '. $paged; }
           ?>">
    <meta name="description" content="<?php bloginfo('description'); ?>">

    <!--  Mobile Viewport meta tag
    j.mp/mobileviewport & davidbcalhoun.com/2010/viewport-metatag 
    device-width : Occupy full width of the screen in its current orientation
    initial-scale = 1.0 retains dimensions instead of zooming out if page height > device height
    maximum-scale = 1.0 retains dimensions instead of zooming in if page width < device width -->
    <!-- Uncomment to use; use thoughtfully!
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
    -->

    <link rel="shortcut icon" href="<?php bloginfo('template_directory'); ?>/_/img/favicon.ico">
    <!-- This is the traditional favicon.
         - size: 16x16 or 32x32
         - transparency is OK
         - see wikipedia for info on browser support: http://mky.be/favicon/ -->

    <link rel="apple-touch-icon" href="<?php bloginfo('template_directory'); ?>/_/img/apple-touch-icon.png">
    <!-- The is the icon for iOS's Web Clip.
         - size: 57x57 for older iPhones, 72x72 for iPads, 114x114 for iPhone4's retina display (IMHO, just go ahead and use the biggest one)
         - To prevent iOS from applying its styles to the icon name it thusly: apple-touch-icon-precomposed.png
         - Transparency is not recommended (iOS will put a black BG behind the icon) -->

    <!-- CSS: screen, mobile & print are all in the same file -->
    <link rel="stylesheet" href="<?php bloginfo('stylesheet_url'); ?>">

    <!-- all our JS is at the bottom of the page, except for Modernizr. -->
    <script src="<?php bloginfo('template_directory'); ?>/_/js/modernizr-1.7.min.js"></script>

    <link rel="pingback" href="<?php bloginfo('pingback_url'); ?>" />

    <?php if ( is_singular() ) wp_enqueue_script( 'comment-reply' ); ?>

    <?php wp_head(); ?>

</head>

<body <?php body_class(); ?> id="listen">


<?php
    $id_from_url = $_GET['id'];
    $temp = $wp_query;
  $paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
  $post_per_page = 100; // -1 shows all posts
  $args=array(
    'post_type' => 'audio',
    'p' => $id_from_url
  );
    $my_query = new WP_Query($args);
    if( $my_query->have_posts() ) : while ($my_query->have_posts()) : $my_query->the_post();
 ?>
                <?php get_template_part( 'content', 'listen' ); ?>
    <?php endwhile; else: ?>
    <?php endif; wp_reset_postdata(); $wp_query = $temp; ?>

    <?php wp_footer(); ?>


<!-- here comes the javascript -->

<!-- jQuery is called via the Wordpress-friendly way via functions.php -->

<!-- this is where we put our custom functions -->
<script src="<?php bloginfo('template_directory'); ?>/_/js/flowplayer-3.2.10.min.js"></script>
<script src="<?php bloginfo('template_directory'); ?>/_/js/functions.js"></script>

</body>

</html>

taxonomy-series.php

<?php get_header(); ?>

    <div id="page-title">
            <h2>Series &#8216;<?php single_cat_title(); ?>&#8217;</h2>
    </div>

    <?php
    global $wp_query;
    $args = array_merge( $wp_query->query, array( 'order' => 'asc' ) );
    query_posts( $args );

     if (have_posts()) : while (have_posts()) : the_post(); ?>

        <article <?php post_class() ?> id="post-<?php the_ID(); ?>">

        <?php get_template_part( 'content', 'media' ); ?>

        </article>

    <?php endwhile; ?>

    <?php include (TEMPLATEPATH . '/_/inc/nav.php' ); ?>

    <?php else : ?>

        <h2>Not Found</h2>

    <?php endif; ?>

<?php get_footer(); ?>

taxonomy-speakers.php

<?php get_header(); ?>

    <div id="page-title">
            <h2>Speaker &#8216;<?php single_cat_title(); ?>&#8217;</h2>
    </div>

    <?php 
    global $wp_query;
    $args = array_merge( $wp_query->query, array( 'order' => 'asc' ) );
    query_posts( $args );
    if (have_posts()) : while (have_posts()) : the_post(); ?>

        <article <?php post_class() ?> id="post-<?php the_ID(); ?>">

        <?php get_template_part( 'content', 'media' ); ?>

        </article>

    <?php endwhile; ?>

    <?php include (TEMPLATEPATH . '/_/inc/nav.php' ); ?>

    <?php else : ?>

        <h2>Not Found</h2>

    <?php endif; ?>

<?php get_footer(); ?>

taxonomy-years.php

<?php get_header(); ?>

    <div id="page-title">
            <h2>Year &#8216;<?php single_cat_title(); ?>&#8217;</h2>
    </div>

    <?php
     global $wp_query;
     $args = array_merge( $wp_query->query, array( 'order' => 'asc' ) );
     query_posts( $args );
     if (have_posts()) : while (have_posts()) : the_post(); ?>

        <article <?php post_class() ?> id="post-<?php the_ID(); ?>">

        <?php get_template_part( 'content', 'media' ); ?>

        </article>

    <?php endwhile; ?>

    <?php include (TEMPLATEPATH . '/_/inc/nav.php' ); ?>

    <?php else : ?>

        <h2>Not Found</h2>

    <?php endif; ?>

<?php get_footer(); ?>

content-media.php

<?php 
$custom = get_post_custom($post->ID);  
$audio_file_english = $custom["audio_file_english"][0];
$series = get_the_terms($post->ID, 'series');
?><div class="media-post">
    <div class="media-post-heading-border">
    <div class="media-post-heading">
        <h1><?php the_title(); ?></h1>
        <div class="date"><?php the_time('l F j, Y') ?></div>
        <div class="tags">
            Speaker: <span class="tag-speakers"><?php the_terms( $post->ID, 'speakers', '', ' ', ' ' ); ?></span><br /><?php if ($series) { ?>
            Series: <span class="tag-series"><?php the_terms( $post->ID, 'series', '', ' ', ' ' ); ?></span><?php } ?>
        </div>
    </div>
    </div>
    <div class="media-post-body">
        <?php the_content(); ?>
    </div>
    <div class="media-post-links">
     <a href="<?php echo $audio_file_english; ?>" class="download">Download</a><a href="<?php echo $audio_file_english; ?>"></a></li>
     <a href="javascript:void(0)" onclick="window.open('/listen/?id=<?php echo $post->ID; ?>',
'StreamingAudio','width=500,height=420')" class="listen">Listen</a><a href="<?php echo $audio_file_english; ?>"></a>
      <?php edit_post_link( __( 'Edit' ), '<span class="edit-link">', '</span>' ); ?>
  </div>    

content-listen.php

<?php 
$custom = get_post_custom($post->ID);  
$audio_file_english = $custom["audio_file_english"][0];
?><div class="media-post">
    <div class="media-post-heading-border">
    <div class="media-post-heading">
        <h1><?php the_title(); ?></h1>
        <div class="date"><?php the_date('l F j, Y') ?></div>
        <div class="tags">
            Speaker: <span class="tag-speakers"><?php the_terms( $post->ID, 'speakers', '', ', ', ' ' ); ?></span>
            </div>
    </div>
    </div>
    <div class="media-post-links">
        <div class="myPlayer" href="<?php echo $audio_file_english ?>"></div>
  </div>
    <div class="media-post-body">
        <?php the_content(); ?>
        <?php edit_post_link( __( 'Edit' ), '<span class="edit-link">', '</span>' ); ?>
    </div>

single-audio.php

<?php get_header(); ?>

    <?php if (have_posts()) : while (have_posts()) : the_post(); ?>

        <article <?php post_class() ?> id="post-<?php the_ID(); ?>">

        <?php get_template_part( 'content', 'media' ); ?>

        </article>

    <?php endwhile; ?>

    <?php include (TEMPLATEPATH . '/_/inc/nav.php' ); ?>

    <?php else : ?>

        <h2>Not Found</h2>

    <?php endif; ?>

<?php get_footer(); ?>

Lastly, I'm using FlowPlayer to generate the audio player on the listen pop up page. It looks like FlowPrayer just did a major update to their script. Here is some code I was using for their old version 3.1.5.

Picture

js/functions.js

// remap jQuery to $
(function($){})(window.jQuery);


/* trigger when page is ready */
$(document).ready(function (){

    flowplayer("div.myPlayer", "http://releases.flowplayer.org/swf/flowplayer-3.1.5.swf", { 
            // fullscreen button not needed here 
            plugins: { 
                controls: { 
                    fullscreen: false, 
                    height: 30,
                                timeBgColor: '#303030',
                                timeColor: '#D8D8D8',
                                durationColor: '#D8D8D8',
                                backgroundColor: '#e1e1e1',
                                buttonColor: '#db561d',
                                buttonOverColor: '#000',
                                sliderColor: '#D8D8D8',
                                progressColor: '#db561d',
                                bufferColor: '#555555',
                                backgroundGradient: 'none'
                }
            }, 
            canvas: { 
                // configure background properties 
                backgroundColor: '#222222', 

                // remove default canvas gradient 
                backgroundGradient: 'none', 
            },
            clip: { 

                autoPlay: true, 
                backgroundColor: '#222222'

            }

        })

});