Package: hpodder Version: 0.99.1 Severity: wishlist Tags: patch In some circumstances, it's useful or necessary to postprocess podcasts after downloading them. For instance, my little music player can play videos too, but only if they're in a very particular format. A posthook could be used to
The attached patch implements this by adding a "setposthook" command, which takes the full pathname of a script to execute after downloading a podcast. The script should take a single argument, the full pathname of the podcast. Daniel -- System Information: Debian Release: 4.0 APT prefers unstable APT policy: (500, 'unstable') Architecture: i386 (i686) Shell: /bin/sh linked to /bin/bash Kernel: Linux 2.6.18-4-686 Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8) Versions of packages hpodder depends on: ii curl 7.15.5-1 Get a file from an HTTP, HTTPS, FT ii id3v2 0.1.11-3 A command line id3v2 tag editor ii libc6 2.3.6.ds1-13 GNU C Library: Shared libraries ii libgmp3c2 2:4.2.1+dfsg-4 Multiprecision arithmetic library ii libsqlite3-0 3.3.8-1.1 SQLite 3 shared library hpodder recommends no packages. -- no debconf information
New patches: [Add space in the database and in the Podcast data structure for a possibly-missing "posthook" field. Daniel Burrows <[EMAIL PROTECTED]>**20070312023823] { hunk ./Commands/Add.hs 37 + postHook = Nothing, hunk ./Commands/ImportIpodder.hs 100 + postHook = Nothing, hunk ./DB.hs 71 -upgradeSchema dbh 3 _ = return () +upgradeSchema dbh 4 _ = return () + +upgradeSchema dbh 3 tables = + do dbdebug "Upgrading schema 3 -> 4" + dbdebug "Adding posthook column" + run dbh "ALTER TABLE podcasts ADD posthook STRING NULL DEFAULT NULL" [] + setSchemaVer dbh 4 + commit dbh + upgradeSchema dbh 4 tables hunk ./DB.hs 159 - run dbh "UPDATE podcasts SET castname = ?, feedurl = ?, pcenabled = ?, \ + run dbh "UPDATE podcasts SET castname = ?, feedurl = ?, posthook = ?, pcenabled = ?, \ hunk ./DB.hs 162 + toSql (postHook podcast), hunk ./DB.hs 175 - do res <- quickQuery dbh "SELECT castid, castname, feedurl, pcenabled, lastupdate FROM podcasts ORDER BY castid" [] + do res <- quickQuery dbh "SELECT castid, castname, feedurl, posthook, pcenabled, lastupdate FROM podcasts ORDER BY castid" [] hunk ./DB.hs 180 - do res <- quickQuery dbh "SELECT castid, castname, feedurl, pcenabled, lastupdate FROM podcasts WHERE castid = ? ORDER BY castid" [toSql wantedid] + do res <- quickQuery dbh "SELECT castid, castname, feedurl, posthook, pcenabled, lastupdate FROM podcasts WHERE castid = ? ORDER BY castid" [toSql wantedid] hunk ./DB.hs 197 -podcast_convrow [svid, svname, svurl, isenabled, lupdate] = +podcast_convrow [svid, svname, svurl, svposthook, isenabled, lupdate] = hunk ./DB.hs 199 + postHook = fromSql svposthook, hunk ./Types.hs 47 + postHook :: Maybe String, } [Run the podcast posthook, if any, in the "I finished downloading" callback. Daniel Burrows <[EMAIL PROTECTED]>**20070312042724] { hunk ./Commands/Download.hs 22 +import Data.Foldable(for_) hunk ./Commands/Download.hs 38 +import System.Posix.IO( + OpenMode(..), + closeFd, + defaultFileFlags, + dupTo, + openFd, + stdOutput + ) hunk ./Commands/Download.hs 165 + let pcPostHook = postHook $ podcast ep + for_ pcPostHook (runPostHook finalfn) hunk ./Commands/Download.hs 179 +-- | Given a podcast's post-hook and a downloaded episode of that podcast, run the +-- podcast's post-hook on the episode. +-- +-- stdout is redirected to /dev/null. +runPostHook :: String -- | The file-name of the episode to process. + -> String -- | The post-hook to execute. + -> IO () +runPostHook epFileName postHookCmd = + do kid <- forkProcess startPostHook + (Just status) <- getProcessStatus True False kid + case status of + Exited ExitSuccess -> return () + Exited (ExitFailure n) -> error $ "Post-hook " ++ postHookCmd ++ " exited with status " ++ (show n) ++ "\n" + Terminated sig -> error $ "Post-hook " ++ postHookCmd ++ " was killed by signal " ++ (show sig) ++ "\n" + Stopped _ -> error "The world is coming to an end: I didn't ask to be woken when my child stopped, yet I was!" + where startPostHook = + do bracket (openFd "/dev/null" ReadOnly + Nothing defaultFileFlags) + closeFd + (\devNull -> + do dupTo devNull stdOutput) + executeFile postHookCmd False [epFileName] Nothing + } [Add a command "setposthook" that sets the posthook of a podcast. Daniel Burrows <[EMAIL PROTECTED]>**20070312042748] { hunk ./Commands.hs 49 +import qualified Commands.SetPostHook hunk ./Commands.hs 68 + Commands.SetPostHook.cmd, addfile ./Commands/SetPostHook.hs hunk ./Commands/SetPostHook.hs 1 +{- hpodder component +Copyright (C) 2006 John Goerzen <[EMAIL PROTECTED]> + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +-} + +module Commands.SetPostHook(cmd, cmd_worker) where +import Utils +import System.Log.Logger +import DB +import Download +import FeedParser +import Types +import Text.Printf +import Config +import Database.HDBC +import Control.Monad +import Utils +import Data.String +import System.IO +import System.Console.GetOpt +import System.Console.GetOpt.Utils +import Control.Exception + +i = infoM "setposthook" +w = warningM "setposthook" +d = debugM "setposthook" + +cmd :: (String, Command) +cmd = simpleCmd "setposthook" + "Alter the posthook of a podcast" helptext + [Option "c" ["castid"] (ReqArg (stdRequired "castid") "ID") + "Podcast ID to modify", + Option "p" ["posthook"] (ReqArg (stdRequired "posthook") "CMD") + "Command to run after downloading episodes of this podcast", + Option "d" ["delete"] (NoArg ("delete", "")) + "Remove any currently set post-hook for this podcast"] + cmd_worker + +cmd_worker gi (args, []) = + do podcastid <- case lookup "castid" args of + Just x -> return (read x) + Nothing -> fail "setposthook: --castid required; see hpodder setposthook --help" + newPostHook <- case (lookup "posthook" args, lookup "delete" args) of + (Just _, Just _) -> fail "You may not pass both --delete and --posthook to setposthook" + (Nothing, Nothing) -> fail "You must pass exactly one of --delete and --posthook to setposthook" + (Just val, Nothing) -> return $ Just val + (Nothing, Just _) -> return $ Nothing + pc <- getPodcast (gdbh gi) podcastid + case pc of + [x] -> updatePodcast (gdbh gi) (x {postHook = newPostHook}) + _ -> fail $ "Invalid podcast ID given" + commit (gdbh gi) + +cmd_worker gi (_, _) = + fail $ "setposthook: unrecognized arguments; see hpodder setposthook --help" + + +helptext = "Usage: hpodder setposthook -c CASTID (-p 'CMD' | -d)\n\n\ + \You must specify one podcast ID with -c, and either specify the\n\ + \new posthook with -p, or provide -d to remove a previously-set posthook.\n\ + \The posthook should be an absolute pathname; it will be passed the\n\ + \file name of a newly downloaded episode as its one and only argument.\n" } Context: [Readying for hackage John Goerzen <[EMAIL PROTECTED]>**20070307004153] [TAG RELEASE_hpodder_0.99.1 John Goerzen <[EMAIL PROTECTED]>**20061208111652] Patch bundle hash: 70483b8db5b15e1e03f553599657f579a263b445