import com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl; import com.sun.org.apache.xml.internal.serialize.OutputFormat; import com.sun.org.apache.xml.internal.serialize.XMLSerializer; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.GregorianCalendar; import java.util.Hashtable; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.ParserConfigurationException; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; /** * Quick and dirty code to updates an RSS xml podcasting file. * Based on the example here: http://www.apple.com/itunes/store/podcaststechspecs.html#_Toc526931673 * * @author Maurice Walton, www.mauricewalton.com 2007 */ public class MythPodcastMaker { /** * Method comment. * * @param args */ public static void main(String[] args) { boolean error = false; if (args.length != 22) { StringBuilder sb = new StringBuilder(); sb.append("Usage:\n"); sb.append("-title \"podcast item title\"\n"); sb.append("-subtitle \"podcast item subtitle\"\n"); sb.append("-summary \"podcast summary\"\n"); sb.append("-holding \"holding url, i.e.\" \"http://myhomepage/podcasts\"\n"); sb.append("-keywords \"a list of keywords seperated by spaces\"\n"); sb.append("-starttime \"yyyyMMddHHmmss\"\n"); sb.append("-endtime \"yyyyMMddHHmmss\"\n"); sb.append("-author \"author, i.e. channel\"\n"); sb.append("-xml \"File name of the xml document to update\", i.e. \"mythtv.xml\"\n"); sb.append("-keep \"Number of items to keep in the podcast\", i.e. \"-1\" for keep all\n"); sb.append("-file \"Full path of file to be added\", i.e. \"/var/share/Just a Minute.m4a\"\n"); sb.append("\nNote that parameter values must be enclosed with \" marks if they contain spaces, parameter order does not matter\n"); System.out.println(sb.toString()); error = true; } Hashtable parameters = new Hashtable(); if (!error) { for (int argsIndex = 0; argsIndex < args.length; argsIndex += 2) parameters.put(args[argsIndex], args[argsIndex + 1]); if (!parameters.containsKey("-title")) { System.out.println("missing -title"); error = true; } if (!parameters.containsKey("-subtitle")) { System.out.println("missing -subtitle"); error = true; } if (!parameters.containsKey("-summary")) { System.out.println("missing -summary"); error = true; } if (!parameters.containsKey("-holding")) { System.out.println("missing -holding"); error = true; } if (!parameters.containsKey("-keywords")) { System.out.println("missing -keywords"); error = true; } if (!parameters.containsKey("-starttime")) { System.out.println("missing -starttime"); error = true; } if (!parameters.containsKey("-endtime")) { System.out.println("missing -endtime"); error = true; } if (!parameters.containsKey("-keep")) { System.out.println("missing -keep"); error = true; } if (!parameters.containsKey("-xml")) { System.out.println("missing -xml"); error = true; } if (!parameters.containsKey("-keep")) { System.out.println("missing -keep"); error = true; } if (!parameters.containsKey("-file")) { System.out.println("missing -file"); error = true; } } if (!error) { System.out.println("Values:"); for (String key : parameters.keySet()) { System.out.println(key + "=" + parameters.get(key)); } MythPodcastMaker mpc = new MythPodcastMaker(); mpc.updatePodcast(parameters); } if (error) System.exit(1); } private SimpleDateFormat pubDateFormat = new SimpleDateFormat( "EEE, dd MMM yyyy HH:mm:ss z"); private SimpleDateFormat sourceDateFormat = new SimpleDateFormat( "yyyyMMddHHmmss"); /** * Constructor comment. * * @param parameters */ public MythPodcastMaker() { super(); } /** * Update RSS XML. * @param parameters * @return */ public boolean updatePodcast(Hashtable parameters) { File file = new File(parameters.get("-file")); boolean success = true; try { DocumentBuilder db; db = DocumentBuilderFactoryImpl.newInstance().newDocumentBuilder(); try { Document document = db.parse(new File(parameters.get("-xml"))); NodeList channelNodeList = document.getElementsByTagName("channel"); Node channelNode = channelNodeList.item(0); // first remove any old items, keeping the number required // TODO complete this unused functionality by also optionally deleting the associated files int itemsToKeep = Integer.parseInt(parameters.get("-keep")); if (itemsToKeep > -1) { // remove items until "keep" number of items are left NodeList itemList = document.getElementsByTagName("item"); if (itemList.getLength() > itemsToKeep) { while (itemList.getLength() > itemsToKeep) { Node removeNode = itemList.item(0); channelNode.removeChild(removeNode); } } } // add new item to channel node Node itemNode = document.createElement("item"); Node titleNode = document.createElement("title"); titleNode.appendChild(document.createTextNode(parameters.get("-title"))); itemNode.appendChild(titleNode); Node authorNode = document.createElement("itunes:author"); authorNode.appendChild(document.createTextNode(parameters.get("-author"))); itemNode.appendChild(authorNode); Node subtitleNode = document.createElement("itunes:subtitle"); subtitleNode.appendChild(document.createTextNode(parameters.get("-subtitle"))); itemNode.appendChild(subtitleNode); Node summaryNode = document.createElement("itunes:summary"); summaryNode.appendChild(document.createTextNode(parameters.get("-summary"))); itemNode.appendChild(summaryNode); Element enclosureNode = document.createElement("enclosure"); enclosureNode.setAttribute("url", parameters.get("-holding") + "/" + file.getName()); enclosureNode.setAttribute("length", Long.toString(file.length())); enclosureNode.setAttribute("type", "audio/x-m4a"); itemNode.appendChild(enclosureNode); Node guidNode = document.createElement("guid"); guidNode.appendChild(document.createTextNode(parameters.get("-holding") + "/" + file.getName())); itemNode.appendChild(guidNode); Date startdate = new GregorianCalendar().getTime(); try { startdate = sourceDateFormat.parse(parameters.get("-starttime")); } catch (ParseException e) { e.printStackTrace(); success = false; } Node pubDateNode = document.createElement("pubDate"); pubDateNode.appendChild(document.createTextNode(pubDateFormat.format(startdate))); itemNode.appendChild(pubDateNode); Date enddate = new GregorianCalendar().getTime(); try { enddate = sourceDateFormat.parse(parameters.get("-endtime")); } catch (ParseException e) { e.printStackTrace(); success = false; } Node durationNode = document.createElement("itunes:duration"); long milliseconds = enddate.getTime() - startdate.getTime(); long seconds = milliseconds / 1000L; long minutes = seconds / 60L; seconds = seconds - (minutes * 60L); String secondsString = Long.toString(seconds); if (seconds < 10) secondsString = "0" + secondsString; durationNode.appendChild(document.createTextNode(Long.toString(minutes) + ":" + secondsString)); itemNode.appendChild(durationNode); Node keywordsNode = document.createElement("itunes:keywords"); keywordsNode.appendChild(document.createTextNode(parameters.get( "-keywords").replaceAll(" ", ", "))); itemNode.appendChild(keywordsNode); if (success) { channelNode.appendChild(itemNode); success = writeXmlFile(document, new File( parameters.get("-xml"))); } } catch (SAXException e) { e.printStackTrace(); success = false; } catch (IOException e) { e.printStackTrace(); success = false; } } catch (ParserConfigurationException e) { e.printStackTrace(); success = false; } return success; } /** * Write the xml document in a formatted manner for easier reading by humans. * * @param document * @param file * @return success */ public boolean writeXmlFile(Document document, File file) { boolean success = true; OutputFormat format = new OutputFormat(document); format.setIndenting(true); format.setIndent(2); format.setLineWidth(500); try { XMLSerializer output = new XMLSerializer( new FileOutputStream(file), format); output.serialize(document); } catch (FileNotFoundException e) { e.printStackTrace(); success = false; } catch (IOException e) { e.printStackTrace(); success = false; } return success; } } // template /* Maurice's MythTV DVB Radio Recordings http://www.YOURSERVER.co.uk/mythtv/index.html en-us ℗ & © 2007 Maurice Walton, content, probably the BBC. MythTV DVB Radio Recordings Maurice Walton MythTV DVB Radio Recordings Recorded from Freeview DVB using MythTV, converted to m4a using mplayer and faac Maurice Walton someone@somewhere.com */