|
SageTV v7 Customizations This forums is for discussing and sharing user-created modifications for the SageTV version 7 application created by using the SageTV Studio or through the use of external plugins. Use this forum to discuss plugins for SageTV version 7 and newer. |
|
Thread Tools | Search this Thread | Display Modes |
#701
|
|||
|
|||
Quote:
1) Simplifies this script by reducing the amount of "stuff" it's trying to do 2) Allows SJQ to better manage resources by properly distributing your comskip tasks This isn't necessary, of course, but if you want to see how it's done take a look at my media_file_scanner.groovy script (in my scripts repository). Lines 65-75 in that script show how to add tasks to the SJQ task queue from Groovy (don't forget to include the import statements as well). Quote:
__________________
Twitter: @ddb_db Server: Intel i5-4570 Quad Core, 16GB RAM, 1 x 128GB OS SSD (Win7 Pro x64 SP1), 1 x 2TB media drive Capture: 2 x Colossus STB Controller: 1 x USB-UIRT Software:Java 1.7.0_71; SageTV 7.1.9 Clients: 1 x HD300, 2 x HD200, 1 x SageClient, 1 x PlaceShifter Plugins: Too many to list now... |
#702
|
|||
|
|||
Groovy example: Email
Here's a quick script for sending email from Groovy.
Notes:
More examples of how to send email via Groovy are here. In particular, the last page of that article uses the Groovy AntBuilder object to run the ant task for sending email. This is by far the easiest/most convenient way to send email from Groovy, but since under the hood the ant task uses the JavaMail API, you're also free to directly use the JavaMail API for sending email from Groovy (and the article linked to above shows an example of doing that). Code:
private class EmailSettings { static def host = 'smtp.gmail.com' static def user = 'user@gmail.com' static def pwd = 'password' static def port = 465 static def subj = 'Email Subject' static def from = user // To send via Gmail, from addr must equal user addr static def to = 'john@doe.com' } def ant = new AntBuilder() ant.mail(mailhost: EmailSettings.host, mailport: "${EmailSettings.port}", subject: EmailSettings.subj, user: EmailSettings.user, password: EmailSettings.pwd, ssl: "true") { from(address: EmailSettings.from) to(address: EmailSettings.to) message('My message body') } Happy scripting!
__________________
Twitter: @ddb_db Server: Intel i5-4570 Quad Core, 16GB RAM, 1 x 128GB OS SSD (Win7 Pro x64 SP1), 1 x 2TB media drive Capture: 2 x Colossus STB Controller: 1 x USB-UIRT Software:Java 1.7.0_71; SageTV 7.1.9 Clients: 1 x HD300, 2 x HD200, 1 x SageClient, 1 x PlaceShifter Plugins: Too many to list now... |
#703
|
||||
|
||||
I've built a script to do the commerical cutting using videoredo (which uses windows COM interface for automagic output) and though it works fine from sagegroovy it's failing from within sagetv. I'm guessing it's a permissions issue? I have set the COM+ service to an admin id for startup user with no success. Here's the script:
Code:
// def SJQ4_METADATA = ["SJQ4_ID":"4598125", "SJQ4_TYPE":"MediaFile"] // remove the above line before using the scirpt in SJQv4. import org.apache.commons.io.FilenameUtils import org.apache.commons.io.FileUtils private class Settings { static public final boolean TEST_MODE = false } def mf = MediaFileAPI.GetMediaFileForID(SJQ4_METADATA["SJQ4_ID"].toInteger()) if(mf == null) { //make sure it's a valid file id println "Invalid media file id! [${SJQ4_METADATA['SJQ4_ID']}]" return 1 } def title = ShowAPI.GetShowTitle(mf) def Prefix = FilenameUtils.getBaseName(MediaFileAPI.GetFileForSegment(mf, 0).getAbsolutePath()) def Origfile = new File(Prefix + ".ts") def Outputfile = new File(Prefix + ".mkv") def Origdir = ((MediaFileAPI.GetParentDirectory(mf).toString()) + "\\") def base = FilenameUtils.getBaseName(Origfile.getName()) def OrigExt = ("." + FilenameUtils.getExtension(Origfile.getName())) def CutExt = ".ts" def CutDir = "\\\\Sage-pc\\Mirror_Set\\Process_TV\\com_free\\" def FullInputFile = Origdir + Origfile def FullCutFile = CutDir + Origfile println FullCutFile // Cutting file using VideoRedo def i = 1 def file = new File(FullCutFile) while(file.exists()) file = new File(CutDir, "$base-${i++}$CutExt") println "New file is: $file" FullCutFile = file println "Cutting files that look like '${FullInputFile}' to '${FullCutFile}'." def command = ('cscript.exe //nologo "C:\\Program Files (x86)\\VideoReDoTVSuite4\\vp.vbs " "' + FullInputFile + '" "' + FullCutFile + '" "/p:H.264 Transport Stream" /q /e') println "full cut command will be '$command'" if(!Settings.TEST_MODE) { // Are we running test mode, if not do this def proc = command.execute() def initialSize = 4096 def outStream = new ByteArrayOutputStream(initialSize) def errStream = new ByteArrayOutputStream(initialSize) proc.consumeProcessOutput(outStream, errStream) proc.waitFor() println 'out:\n' + outStream println 'err:\n' + errStream } else { // if we are in test mode do this println "Would run '$command' if test mode were disabled!" } //relink ExternalID to new file if(!Settings.TEST_MODE) { // Are we running test mode, if not do this def src = (FullCutFile.toString()) println "fullpathfile is=$src" def sid = ShowAPI.GetShowExternalID(mf) println "ExternalID is ${sid}" if(!Utility.IsFilePath(src)) { println "${src} does not exist!" return 1 } if(MediaFileAPI.GetMediaFileForFilePath(new File(src)) != null) { println "${src} is already a registered SageTV media file!" return 1 } def show = ShowAPI.GetShowForExternalID(sid) if(show == null) { println "ShowEID ${sid} is invalid!" return 1 } def mfadd = MediaFileAPI.AddMediaFile(new File(src), null) if(mfadd == null) { println "Failed to add media file!" return 1 } if(!MediaFileAPI.SetMediaFileShow(mfadd, show)) { println "Failed to link show metadata to media file!" return 1 } MediaFileAPI.MoveTVFileOutOfLibrary(mfadd) println "Imported '${src}' and linked it to ShowEID '${sid}'!" } else { // if we are in test mode do this println "Would have relinked the showID '${sid}' to the new file '${src}' if test mode were disabled!" } def wildBase = (Origdir + base +".*") if(!Settings.TEST_MODE) { // Are we running test mode, if not do this FileUtils.deleteFile(wildBase) } else { // if we are in test mode do this println "Would delete '$wildBase' if test mode were disabled!" } Any suggestions? |
#704
|
|||
|
|||
If using the Sage plugin version of the task client, is the Sage service running as a user with sufficient permission to access the COM service?
If using the Windows service version of the task client, is that service running as a user with sufficient permissions? The error means nothing to me, but if you think it's a permissions issue then I'd start by checking the permissions of the task client process.
__________________
Twitter: @ddb_db Server: Intel i5-4570 Quad Core, 16GB RAM, 1 x 128GB OS SSD (Win7 Pro x64 SP1), 1 x 2TB media drive Capture: 2 x Colossus STB Controller: 1 x USB-UIRT Software:Java 1.7.0_71; SageTV 7.1.9 Clients: 1 x HD300, 2 x HD200, 1 x SageClient, 1 x PlaceShifter Plugins: Too many to list now... |
#705
|
||||
|
||||
Quote:
Thx again. |
#706
|
||||
|
||||
Two questions:
1) I'm having issues with cut/paste & copy/paste within sagegroovy. Sometimes it works, sometimes it insists on pasting a prior cut/copy. Seems if I use the windows global cut/paste it overrides a internal one... i.e. if I use CTRL+C/CTRL+V that works more often than internal menu option... but not always. Just an update as it may be me but may be related to the 64bit? 2) I'm trying to link the metadata with the new file. First step, as I understand it is to get the externalID, so I'm using: Code:
def SJQ4_METADATA = ["SJQ4_ID":"4598527", "SJQ4_TYPE":"MediaFile"] def sid = ShowAPI.GetShowExternalID("SJQ4_ID") println "ExternalID is ${sid}" |
#707
|
||||
|
||||
Nevermind, I got it.... one of those copy/paste issues as I was building....
Code works as: Code:
def SJQ4_METADATA = ["SJQ4_ID":"4598527", "SJQ4_TYPE":"MediaFile"] def mf = MediaFileAPI.GetMediaFileForID(SJQ4_METADATA["SJQ4_ID"].toInteger()) def sid = ShowAPI.GetShowExternalID(mf) println "ExternalID is ${sid}" |
#708
|
||||
|
||||
I'm lost... stuck with the delete phase of things. I know it's a problem with the argument type being passed to the deleteFile but have no idea what to do about it.... Any suggestions?
I'm trying to do a (I thought) simple equiv. to "del filename.*" using the groovy script process and can't figure out a way past the following error. Code:
\\Sage-pc\Mirror_Set\Recorded TV\7Newsat5-4519451-0 Exception thrown groovy.lang.MissingMethodException: No signature of method: static org.apache.commons.io.FileUtils.deleteFile() is applicable for argument types: (java.lang.String) values: [\\Sage-pc\Mirror_Set\Recorded TV\7Newsat5-4519451-0.ts] at cut$_run_closure1.doCall(cut.groovy:36) at cut.run(cut.groovy:32) Code:
def SJQ4_METADATA = ["SJQ4_ID":"4606425", "SJQ4_TYPE":"MediaFile"] // remove the above line before using the scirpt in SJQv4. import org.apache.commons.io.FilenameUtils import org.apache.commons.io.FileUtils private class Settings { static public final boolean TEST_MODE = true } def mf = MediaFileAPI.GetMediaFileForID(SJQ4_METADATA["SJQ4_ID"].toInteger()) if(mf == null) { //make sure it's a valid file id println "Invalid media file id! [${SJQ4_METADATA['SJQ4_ID']}]" return 1 } def title = ShowAPI.GetShowTitle(mf) def Prefix = FilenameUtils.getBaseName(MediaFileAPI.GetFileForSegment(mf, 0).getAbsolutePath()) def Origfile = new File(Prefix + ".ts") def VideoReDoFile = new File(Prefix + ".VPrj") def Outputfile = new File(Prefix + ".mkv") def Origdir = (MediaFileAPI.GetParentDirectory(mf)) def base = FilenameUtils.getBaseName(Origfile.getName()) def OrigExt = ("." + FilenameUtils.getExtension(Origfile.getName())) def CutExt = ".ts" def CutDir = "\\\\Sage-pc\\Mirror_Set\\Process_TV\\com_free\\" def wildBase = new File(Origdir, base)// + ".*") println wildBase Utility.DirectoryListing(Origdir).each { if(FilenameUtils.wildcardMatchOnSystem(it.getName(), "${Prefix}.*")) { def fileName = new File(Origdir, base + (it.getName().substring(it.getName().indexOf('.')))) try { FileUtils.deleteFile(fileName) } catch(IOException e) { e.printStackTrace() } } } |
#709
|
|||
|
|||
It's telling you the FileUtils.deleteFile() call is invalid and offers no suggestions. So you head to the javadocs for FileUtils:
http://commons.apache.org/io/apidocs...FileUtils.html You look for the deleteFile() method... ah, it doesn't exist. So you're calling a non-existent method. As it turns out, java.io.File objects have their own delete() method. So this should work: fileName.delete() That call returns true or false so you may want to check the return value and handle failures accordingly.
__________________
Twitter: @ddb_db Server: Intel i5-4570 Quad Core, 16GB RAM, 1 x 128GB OS SSD (Win7 Pro x64 SP1), 1 x 2TB media drive Capture: 2 x Colossus STB Controller: 1 x USB-UIRT Software:Java 1.7.0_71; SageTV 7.1.9 Clients: 1 x HD300, 2 x HD200, 1 x SageClient, 1 x PlaceShifter Plugins: Too many to list now... |
#710
|
||||
|
||||
Quote:
As it turns out I started this extravaganza with fileName.delete() but kept putting the fileName in the () and getting all sorts of non specific messages. I'm very unclear on how to interpret "public boolean delete()" I keep trying to stick the object of the command in the brackets.... |
#711
|
|||
|
|||
Quote:
But most methods in most APIs will be instance methods, which means you have an object, say of type File, and you call methods against that object (i.e. filename.delete()). If you read up on the differences between static methods and instance methods you should be able to see the differences. Like I said, you'll become a Java programmer yet!
__________________
Twitter: @ddb_db Server: Intel i5-4570 Quad Core, 16GB RAM, 1 x 128GB OS SSD (Win7 Pro x64 SP1), 1 x 2TB media drive Capture: 2 x Colossus STB Controller: 1 x USB-UIRT Software:Java 1.7.0_71; SageTV 7.1.9 Clients: 1 x HD300, 2 x HD200, 1 x SageClient, 1 x PlaceShifter Plugins: Too many to list now... |
#712
|
||||
|
||||
Quote:
I'm looking at the example media_file_scanner script to break up the mega_script and have that working more-or-less but for error testing, etc it would be helpful if there is a test I could run to see if a given task for a given ID was running, completed successfully, in queue, etc. Is there such a routine that I can use at various points? I'm using the scanner to scan for a file placed after I've reviewed proposed cuts and if the file exists put the cut process in the queue, which is working, but if the scanner comes around again before executed it's dropping another task for the same thing in the queue which is buggering things up. So I'd like to check if that task for that mediafile is already done, in process, queue'd etc. Got a couple other uses for such a test lined up as well if it exists! |
#713
|
|||
|
|||
You cannot query SJQv4 (reliably) about the execution and subsequent result of previous tasks. This is because SJQv4 purges old tasks from the queue periodically.
However, there is a "Slugger approved" way of doing what you want, but the burden is on the user. So as not to get lost in the maze of info buried throughout this thread, I've written up a wiki doc explaining what you need to do. That should point you in the right direction.
__________________
Twitter: @ddb_db Server: Intel i5-4570 Quad Core, 16GB RAM, 1 x 128GB OS SSD (Win7 Pro x64 SP1), 1 x 2TB media drive Capture: 2 x Colossus STB Controller: 1 x USB-UIRT Software:Java 1.7.0_71; SageTV 7.1.9 Clients: 1 x HD300, 2 x HD200, 1 x SageClient, 1 x PlaceShifter Plugins: Too many to list now... |
#714
|
||||
|
||||
Quote:
|
#715
|
|||
|
|||
Quote:
The same type of strategy can be used as a (sketchy) form of IPC between OS process, SJQ tasks, etc. I say "sketchy" because metadata properties aren't really the best way to communicate between processes, but it's rather simple to implement and better than nothing. If reliability and fault tolerance are crucial then a more robust form of IPC should be used. However, for most use cases, metadata should be enough.
__________________
Twitter: @ddb_db Server: Intel i5-4570 Quad Core, 16GB RAM, 1 x 128GB OS SSD (Win7 Pro x64 SP1), 1 x 2TB media drive Capture: 2 x Colossus STB Controller: 1 x USB-UIRT Software:Java 1.7.0_71; SageTV 7.1.9 Clients: 1 x HD300, 2 x HD200, 1 x SageClient, 1 x PlaceShifter Plugins: Too many to list now... |
#716
|
||||
|
||||
I'm trying to use of MediaFileAIP.GetMediaFiles("T") to get the same list that is generated by the sage ui for 'current recordings' and what it's returning seems to be everything, including archive. I'd 'like' to be getting the list of 'current recordings' (from sage ui) Anybody have a clue what the sage ui is polling to get the 'current recordings' list?
|
#717
|
|||
|
|||
Quote:
A TV recording is archived if MediaFileAPI.IsTVFile() == true && MediaFileAPI.IsLibraryFile() == true You don't need to check IsTVFile() because you're already implicitly doing that check by passing the 'T' media mask to GetMediaFiles().
__________________
Twitter: @ddb_db Server: Intel i5-4570 Quad Core, 16GB RAM, 1 x 128GB OS SSD (Win7 Pro x64 SP1), 1 x 2TB media drive Capture: 2 x Colossus STB Controller: 1 x USB-UIRT Software:Java 1.7.0_71; SageTV 7.1.9 Clients: 1 x HD300, 2 x HD200, 1 x SageClient, 1 x PlaceShifter Plugins: Too many to list now... |
#718
|
||||
|
||||
Quote:
Maybe there's something set incorrectly with the media files, but somehow the sage ui is getting the listing correct. So I guess the real question is: what's being considered 'current recordings' by the sage ui? |
#719
|
|||
|
|||
GetMediaFiles('T') returns all tv files, always. If you only want "current" ones then you need to further filter the returned list yourself using the API calls above.
__________________
Twitter: @ddb_db Server: Intel i5-4570 Quad Core, 16GB RAM, 1 x 128GB OS SSD (Win7 Pro x64 SP1), 1 x 2TB media drive Capture: 2 x Colossus STB Controller: 1 x USB-UIRT Software:Java 1.7.0_71; SageTV 7.1.9 Clients: 1 x HD300, 2 x HD200, 1 x SageClient, 1 x PlaceShifter Plugins: Too many to list now... |
#720
|
||||
|
||||
Slugger,
I want to change the backup scripts so that if it is not run by a certain time of day it will not be run at all on that day. Right now I have the script set to do a backup at 4:00 AM and I want to make sure that if it's not run by 8:00 AM it's not run at all. Do you suggest I do this by making the agent only available between 4 AM and 8 AM, or do you suggest I check the time in the test script and return 2 if it's past 8 AM? Tom
__________________
Sage Server: 8th gen Intel based system w/32GB RAM running Ubuntu Linux, HDHomeRun Prime with cable card for recording. Runs headless. Accessed via RD when necessary. Four HD-300 Extenders. |
Currently Active Users Viewing This Thread: 4 (0 members and 4 guests) | |
|
|
Similar Threads | ||||
Thread | Thread Starter | Forum | Replies | Last Post |
Plugin: MizookLCD (Alternate SageTV LCDSmartie Plugin) | cslatt | SageTV Customizations | 48 | 06-11-2012 10:44 AM |
SJQv4: Technology Preview | Slugger | SageTV v7 Customizations | 39 | 12-17-2010 01:17 PM |
SageTV Plugin Developers: Any way to see stats for your plugin? | mkanet | SageTV Software | 4 | 12-12-2010 10:33 PM |
MediaPlayer Plugin/STV Import: Winamp Media Player Plugin | deria | SageTV Customizations | 447 | 12-11-2010 07:38 PM |
SJQv4: Design Discussion | Slugger | SageTV v7 Customizations | 26 | 10-18-2010 08:22 AM |