Archive
Digitization of the SAVILLE analogue Conference interpreting recording facility: Lecture/Floor recording and CCTV streaming
The original conference interpreting lab setup had no provision for digital video recording of the lecture/floor. A workaround used on of the booth VCRs for analogue recording, with video form an ELMO dome cameras and audio from a lectern microphone – an audio installation which ran in parallel to the main DSI conference interpreting facility (and covered only the lectern, not the conference table).
A home-brew add-on was based on a consumer handheld digital camera for video. Experiments with different add-on microphones for audio from the lectern and floor were less than successful.
The DIS system however provides an audio out of the lectern an/or floor audio, as well as the capability for the conference administrator to open or mute floor microphones and for the technical administrator to set the maximum number of open microphones, and control their gain.
For the digitization of this system, I used
- an already retired standard university student lab computer
- to which I added an old spare ATI All-in-Wonder video card
- to which I connected a TEVION home TV switch as a poor man’s (~5£) video splitter into which I fed
- the (hitherto unused) DIS audio out balanced stereo, using an RCA adapter, as well as
- the ELMO video, using a coax to RCA adapter (video signal was split into the ATI as well as back into the original SAVILLE Kramer AV switch).
While originally coming with its own digitization software, the ATI All-in-wonder also works well with Windows Media Encoder.
Two wme configuration files were created:
- capturetestaticomposite_pal-l_480x320works.wme(find this file on the computer connected to the central rack, then double-click it in order to start Windows Media Encoder, then click the Record button in the top menu – no custom GUI was deemed necessary for this non-student operated recording) for recording to files that can be played with Windows media player, whether on Windows or on Mac OS X.
- streamtest480x320_15fps_pal.wme (again, simply find this file on the central rack computer, then double-click it) for streaming CCTV live to the back office. An onsite admin office was one of the usual features of a teaching lab which was missing in this installation. CCTV allows to keep an eye on teaching activities in the conference interpreting lab, proactively spot support needs ands absorb feature requirements which instructors tend to have problems articulating (or even seeing the need for articulating). A (lower quality archived stream is created on the side and can be picked up, post-processed and archived at TBA).
Digitization of the SAVILLE analogue Conference interpreting recording facility: Booths. Technical instructions
Prerequisites:
The original SAVILLE setup to add (floor and booth) video and enable recording in the DIS 6000 conference interpreting facility. The cabling, switching and interfacing can all be used unchanged, and the VHS recorders should indeed be used as backup. OTOH, once you feel confident about digital recording, you can fade out the VHS recorders (or replace them by yet another output device).
Digital video capture card – the cheapest I could find was this and it tested to work (including lip synching),
Miscellaneous AV splitters and cables.
Windows Media Encoder 9 and the Windows Media Encoder SDK, both available from Microsoft and installed by campus ICT support.
Windows Media Encoder Configuration Files trprecord_a.wme and trprecord_av.wme in \\stushare_server\StuShare\Humanities, Arts and Languages\Language_Services\configuration
AutoIt3, a scripting language used on campus for computer deployment. The compiled executable I provide has no prerequisites on our MS-Windows installation. If you want to make changes in the au3 script, you will need the free AutoIt3 language and development environment.
The script relies on impersonation to access the network shares. If the user/password this impersonation is based on changes, you can still work with the recordings on the local PC. To restore the network archiving/sharing functionality, you have to run trpPwdEncrypt.exe (a slight adaptation from the AutoIT3 help file example) and follow the included instructions:
Then recompile the script trprecord.au3 (both files are stored on the instructors-only share) and put the resulting trprecord.exe on the student-accessible share.
Troubleshooting:
- Check the AV cables and connectors.
- Check the screenshots and their filenames which the software produces for logging in the local temp directory (note that this directory gets purged on restart).
- If you make changes in the environment, do not fail to also change the corresponding configuration strings at the top of trprecord.au3, then recompile.
Digitization of the SAVILLE analogue Conference interpreting recording facility: Booths: End-user
The instructor sets the booth AV sources as usual (using the CRESTRON remote control).
The student in the booth starts the trprecord.exe from the student-accessible share (if the application is already running, an attempt to start another instance brings the current instance to the foreground).
In the GUI (which should not be hidden by blocking the student screen with AV signal; one more reason to stop the wasteful sharing of one screen between AV and VGA signal):
- choose whether to record “Audio” or “Video”(the disabled (grayed out) non-live recording modes are not yet implemented. they would be a completely separate extension of the SAVILLE system.).
- press “Start”, wait for the message indicating recording has begun
- pressing “Start” enables the “Stop” button; press “Stop” when finished
- once the “Play” button has been activated, the student can listen to the last recording in the default player for WMA or WMV files (normally Windows Media Player).
- both student and instructors can listen to other (past and/or peer) recordings by “open[ing the network share] folder”. The instructor (having full control permissions on the network share folder) controls the release of network share videos. Students can only read from this network share folder. The filename, e.g. trprecord_2009_08_04_18_24_47_MORLIB–PCC6392_plagwitt.wma, indicates this:
-
Prefix
Date recording started
Time recording started
on which computer
for which logged-in user
Audio or video
trprecord_
2009_08_04_
18_24_47_
MORLIB–PCC6392_
plagwitt
.wma/v
- Currently, the computer in the booths of the interpreting suite have the following names (note that the computer names are not aligned with the booth numbers; update this when the computers get upgraded):
-
Booth
Computer
mgb-41
morb43-6374
mgb-42
morb44-6344
mgb-43
morb45-6363
mgb-44
morb46-6353
mgb-45
morb42-6368
mgb-46
morb47-6359
- When listening to the recording in Windows Media Player, use the “Balance” slider which you can enable by clicking Menu:File / View / Enhancements / Graphics Equalizer. Wiggle the slider
- Press F1-key for (this) Help. Pay attention to program feedback messages in red.
View trprecord_demo_walkthrough.AVI (your problems with videos are addressed here; no screencast this time, as 2 simultaneous video encoding sessions would overtax the recording computer and could not demonstrate the interaction with the new secondary video screen) which demonstrates ease of use of the program itself and recording files it
How to build a digital recorder with GUI for free with Windows-Media-Encoder
- Merely a bit of systems integration. Context: An interpreting study program centered around a conference-interpreting lab that, in 2009, was still analog (tape-based) and could not be upgraded to digital, but each interpreter booth had unintegrated Windows PCs – an opportunity.
- Uses AutoIT and Windows-COM programming, as exemplified in Windows-media-encoder-SDK, against Windows-Media-Encoder.
- make sure that you have
- have all AutoIt packages referenced with #includes below;
- have the windows-media-encoder installed – the windows-media-encoder-SDK should not be needed , except for programming examples;
- make sure you adapt “PUTYOUROWN” to your own environment
- provide your own (equipment-specific) WME files for the Windows-Media-Encoder configuration.
- (While there exists an AutoIt brush for Alex Gorbatchev’s SyntaxHighlighter, WordPress.com does not seem to include it, hence the poor highlighting below:)
#Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_Outfile=g:\myfiles\bureaucracy\proposals\interpreting\digitization\local_hacks\recording.au3\trprecord.exe #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Sample: How to build a digital recorder with GUI for free with Windows-Media-Encoder for an analog interpreting lab that cannot be digitized ; prerequisites: ; make sure you have all autoit packages referenced with #includes below ; make sure you have the windows-media-encoder enstalled - the windows-media-encoder-sdk should not be needed , except for programming examples ; make sure you adapt "PUTYOUROWN" to your own environment ; provide your own WME files ; sorry for the magic strings! ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; $GW_HWNDNEXT $FORMAT_MESSAGE_FROM_SYSTEM $GW_CHILD T:\old\trp_l\lang\autoit\Include\Constants.au3(200): Global Const $GW_CHILD = 5 ; $GW_HWNDNEXT $FORMAT_MESSAGE_FROM_SYSTEM $GW_CHILD T:\old\trp_l\lang\autoit\Include\Constants.au3(200): Global Const $GW_CHILD = 5 ; $EM_LINEFROMCHAR etc EditConstants.au3 #include <Constants.au3> #include <GUIConstants.au3> #include <WindowsConstants.au3> ; for gui's #include <ButtonConstants.au3> #include <EditConstants.au3> #include <GUIConstantsEx.au3> #include <ProgressConstants.au3> #include <StaticConstants.au3> #include <WindowsConstants.au3> #include <GUIConstantsEx.au3> #include <_CSVLib_V1.3.au3> ; #include <Array.au3> ; #include <Array2D.au3> $WS_CLIPSIBLINGS, $WS_OVERLAPPEDWINDOW, WS_VISIBLE: used before declaration, must be outdated #include <date.au3> #include <debug.au3> #include <File.au3> #include <GuiComboBox.au3> #include <GuiListBox.au3> #include <GuiListView.au3> #include <GuiTab.au3> #include <Hash.au3> #include <Screencapture.au3> #include <trpCombo.au3> ; not anymore inline #include <trpListClick.au3> #include <trpOCRTextCapture.au3> #include <utils_array.au3> #include <utils_csv.au3> #include <utils_file.au3> #include <utils_Hash.au3> #include <utils_window.au3> #include <ftp.au3> ; for stream #include <Misc.au3> ; singleton ;#include <PopupChecker.au3> ; #include <trpAuralog.au3> Opt("MustDeclareVars", 0) ; i cannot find where i set thinks to 1, but aat a certain development point autoit would not run w/o complaining about vars not being declaured, including in include files Opt("TrayIconDebug", 1) Opt("WinWaitDelay", 250) ; Alters how long a script should briefly pause after a successful window-related operation; default is250ms Opt("WinTitleMatchMode", 1) ;1=start, 2=subStr, 3=exact, 4=advanced, -1 to -4=Nocase ; removed may 2008 Opt("RunErrorsFatal", 0) Global $thissingletonid = "trprecord" Global $thiswindowtitle = "TRPRecord" Global $debugtype = "debugconsolescreen"; "debugconsole" ; or run -> screenshots and debug out; consider "release" --> log ; _DebugSetup("debug") _ScreenCapture_SetBMPFormat(0) ; smallest, with default = 24bit, each 1280*1024 (seems to do only primary) is 3.5mb ; dolater: add cmdline: the program looks for params /admin and /video and loads the gui with buttons disabled and with video checked - there are prior solutions ; donot: options/ini: do you have to allow not to use default audio/video device? set the default device in the wme and edit it in there instead of the ini ; donot: logging - just store debug screenshots with names in the local temp, will get erased on restart ; beyond logging into a file for admin (debugging) (1 per student -> cannot be monitored by teacher), ; log for teacher onto a network folder which the instructor can monitor important errors like encoding start failed ; (not filecopy to instructors network folder, that is redundant, since log files are in the same folder) ; yes filecopy to student x: drive -> instructorr can tell students to clean up their x drives ; this functionality to write messages to filenames i devleoped already for auralog screenshots Global $g_eventerror = 0 ; to be checked to know if com error occurs. Must be reset after handling. global $oMyError Global $szDrive, $szDir, $szFName, $szExt Global $arrAutoitExe = _PathSplit(@AutoItExe, $szDrive, $szDir, $szFName, $szExt); Returns an array with 5 elements where 0 = original path, 1 = drive, 2 = directory, 3 = filename, 4 = extension Global $scriptfilewithexe = $arrAutoitExe[3] & $arrAutoitExe[4] ; autoit3.exe if <>@compiled Global $windowtitletrpRecord = "TRPRecord:Set Options, press Start to begin" Global $nowstring = StringRegExpReplace(_NowCalc(), "[\s\/\:]", "_") ; fill this here only for logfile, but later again when record button is pressed Global $networknamefile = "" Global $networkpathfile = "" ; can instead differentiate audio/video in backupRecording, using $ext Global $ext = "" Global $pathfilelog = FileNameEscape("rec" & "_" & $nowstring & "_" & @ComputerName & "_" & @UserName & "_" & ".log", @TempDir) ; wmeditor.exe is not in the path Global $wmeditorpath = "C:\Program Files\Windows Media Components\Encoder\wmeditor.exe" ; dolater: put in central ini Global $wmencexe = "wemenc.exe" Global $wmcmdvbspath = "C:\WMSDK\WMEncSDK9\samples\vb\wmcmd\Wmcmd.vbs" Global $webinterfacestring = "https://thomasplagwitz.com/2009/08/04/digitization-of-the-saville-analogue-conference-interpreting-recording-facility-booths-end-user/" ; "http://plagwitz1.spaces.live.com/blog/cns!4FA3329905D7E1CE!961.entry" Global $recordingstopstring = "stopRecordingAndPlay.exe" Global $ret = 0 Global $set = 0 ; just use TEMPdir=c:\temp ; just use @ComputerName =MORLIB--PCC6392 ; just use @USERNAME instead of $username =plagwitt ; just use @TempDir - $tempdir = "c:\temp"; todo: what if @TempDir dioes not point to c:\temp, but network Global $uncpathwritestudent = "PUTYOUROWN" ; "\\venus\homes\My Documents\My Music" ; todo: handle spaces ; not this, since can't probably be mapped under student account already "\\lgu.ac.uk\lgu$\multimedia student\mmedia\mmedia1\language_services\recordings" Global $usernameinstructor = "PUTYOUROWN"; "plagwitt" ; dolater: todo: move into network ini Global $passwordinstructor = "PUTYOUROWN" ; encrypted "7B5912DCA17955CECED6668C78303A0B" ; todo: 7A5D13D9A10555BCCED462FC7830, dolater:move into network ini Global $passworddecrypt = "record"; todo:ini: leave blank if you do not know how to encrypt your pwd with autoit; level was 1 Global $wmcmdpath = "C:\WMSDK\WMEncSDK9\samples\vb\wmcmd\Wmcmd.vbs" Global $uncpathsharewriteinstructoronly = "PUTYOUROWN" ; "\\lgu.ac.uk\lgu$\londonmet departments" ; old network backup destination for student recordings, replaced by k-drive; ; this worked for thp0136 (with filecopy to $driveletterkreplacementforstudentwrite returned from addinstructornetworkshares?) ; cannot replicate this anymore Global $dirsharewriteinstructoronly = "Humanities arts and languages (HAL)\Language_services\recordings" ; old network backup destination for student recordings, replaced by k-drive; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; done: @LogonDomain is lgu, which suffices - do students and instructors use the same domain? done: test with thp0136, has the same domain Global $domain = "lgu.ac.uk" Global $serverwriteinstructor = "PUTYOUROWN" ; "\\stushare_server" ; we need to disconnect form the entire server computer to be able to reconneec with different permissions Global $sharewriteinstructor = "PUTYOUROWN" ; "StuShare" Global $uncpathsharewriteinstructor = $serverwriteinstructor & "\" & $sharewriteinstructor ; when we reconnect wiht instrucoter permission, this share should receive a driveletter ; done: replace $driveletterkreplacementforstudentwrite & "\" & $dirsharestudentreadconfig by $driveletterkreplacementforstudentwrite & "\" & $dirsharestudentreadconfig Global $serverstudentreadconfig = "PUTYOUROWN" ; "\\lgu.ac.uk" ; we need to disconnect form the entire server computer to be able to reconneec with different permissions Global $sharestudentreadconfig = "PUTYOUROWN" ; "lgu$\multimedia student\mmedia" ; \\lgu.ac.uk\lgu$\multimedia student\mmedia Global $uncpathsharestudentreadconfig = $serverstudentreadconfig & "\" & $sharestudentreadconfig ; Global $dirsharestudentreadconfig = "PUTYOUROWN" ; "mmedia1\language_services\configuration" ; now on o:, was on k: "Humanities, Arts and Languages\Language_Services\configuration" ; done: have to put this on K:-uncpath, wmenc runs under student, student cannot read from j ; "\\lgu.ac.uk\lgu$\multimedia student\mmedia\mmedia1\language_services\configuration" ; wmenc.exe running under studentuser needs to be able to read config files; ; done: replace $driveletterkreplacementforstudentwrite & "\" & $dirsharestudentreadmedia by $driveletterkreplacementforstudentwrite & "\" & $dirsharestudentreadmedia Global $uncpathstudentreadmedia = "PUTYOUROWN" ; "\\stushare_server\StuShare\Humanities, Arts and Languages\Language_Services\media" ; studentuser can read Global $dirsharestudentreadmedia = "PUTYOUROWN"; "Humanities, Arts and Languages\Language_Services\media" Global $dirsharewriteinstructor = "PUTYOUROWN"; "Humanities, Arts and Languages\Language_Services\recordings" Global $uncpathwritemedia = $uncpathsharewriteinstructor & "\" & $dirsharewriteinstructor ; useful? we currently do not use unc but the driveletter ; done: replace $driveletterwriteinstructor by $driveletterkreplacementforstudentwrite Global $driveletterkreplacementforstudentwrite = ""; will be assigned in setupdrives() Global $driveletterkreplacementforstudentwritenetuse = "K:"; todo: hack for net use Global $driveletterreadconfig = ""; will be assigned in setupdrives() ; todo: build wme out of $driveletterreadconfig and trprecord ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; all the following .wme-files should be in the same network dir $driveletterkreplacementforstudentwrite & "\" & $dirsharestudentreadconfig - not neccessary anymore Global $wmefilename = "" ; ; will set by the differentiated following Global $wmefilenamerecordaudiolive = "recordaudiolive.wme" ; 64kbps,44khz,stereo,cbr (a default file archive profile)saving to c:\temp\recordaudio.wma - overwrite? Global $wmefilenamerecordvideolive = "recordvideolive.wme" Global $wmefilenamerecordaudiofile = "recordaudiofile.wme" Global $wmefilenamerecordvideofile = "recordvideofile.wme" ; indexing is required for all recordstop()ed files that are not (like audiofile, videofile) postprocessed ; if for indexing you reencode (to same as input) using wmenc.xe with .wme, you need to differentiate between audio, video as source Global $wmefilenamerecordaudioindexing = "recordaudioindexing.wme" Global $wmefilenamerecordvideoindexing = "recordvideoindexing.wme" ; streamudio() sample Global $fullpath, $name, $drv Global $Label_1 Global $Label_2 Global $input_1 Global $button2 Global $button1 Global $guiMsg Global $progbar Global $prioruser Global $wmencoderPID = 0 ; new approach from here using encoder-object.start/stop ; config files for audio-video and audio onlyrecording: edit in windows media encoder/ properties to make changes; assumes exists and have write permissions to "c:\temp" ;todo: either: refer to the drive letter or to the unc path? former should be more stable, but latter is in practice Global $strWMEFileVideoName = "trprecord_av.wme" Global $strWMEFileVideo ; can only be done after setupdrives = $driveletterreadconfig & "\" & $dirsharestudentreadconfig & "\" & $strWMEFileVideoName ; $driveletterkreplacementforstudentwrite & "\" & $dirsharestudentreadconfig & "\" & $strWMEFileVideoName ; "K:\Humanities, Arts and Languages\Language_Services\configuration\trprecord_av.wme" Global $strWMEFileAudioName = "trprecord_a.wme" Global $strWMEFileAudio ; can only be done after setupdrives = $driveletterreadconfig & "\" & $dirsharestudentreadconfig & "\" & $strWMEFileAudioName ; $driveletterkreplacementforstudentwrite & "\" & $dirsharestudentreadconfig & "\" & $strWMEFileAudioName ; "K:\Humanities, Arts and Languages\Language_Services\configuration\trprecord_a.wme" Global $objEncoder, $objIWMEncFile, $g_objEncoder, $g_ObjEvent, $g_objIWMEncFile ; done: rather than hardcoding read the tempfilename from the encoder-object.localfilename, which sets it according to load(wmefile) Global $tempfilename = "" Global $wmeoutputbasefilename = "trprecord" ; e.g. trprecord within c:\temp\trprecord.wma Global $wmeoutputbasefilename = "c:\temp" main() ;test() Func test() EndFunc ;==>test Func main() ; MsgBox(0, "test", "test") ; allow only one instance of the program to run If _Singleton($thissingletonid, 1) == 0 Then myDebugOut(@ScriptLineNumber, "An occurence of trprecord is already running") ; following test seems a bit superfluous, but just to make sure: If WinExists($thiswindowtitle) Then ; does work, when case-sensitivity is observed WinActivate($thiswindowtitle) ; remind the user of the running instance by showing it EndIf ; test Exit myDebugOut(@ScriptLineNumber, "singleton @error=" & @error) ; ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : Exit = ' & Exit & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console EndIf ; Msgbox(0,"OK","the first occurence of trprecord is running") killpriorInstance() ; before building a new gui ; was: test:non-interactive setupdrives() ; create an encoder-object here for the entire duration of the program $objEncoder = ObjCreate("WMEncEng.WMEncoder") ; this does not show up in the tasklist $oMyError = ObjEvent("AutoIt.Error", "MyErrFunc") ; must be called only once (and the objcreate happens only once, with the gui-creation) ; release: $g_ObjEvent=ObjEvent("AutoIt.Error","nothing"); Equal to VBscript's On Error Resume Next If Not IsObj($objEncoder) Then $set = GUICtrlSetData($guiMsg, "Cannot create encoder, try restarting computer." & @CRLF & "If app still fails, reinstall windwos media encoder with sdk.") myDebugOut(@ScriptLineNumber, "Cannot create encoder") Else ; $objEncoder.Start ; EndIf ; works MsgBox(0, "WMEncEng.WMEncoder", $ret) ; wmeobjects($objEncoder,$strWMEFileAudio) guioptions() ; obsolete removeInstructorNetworkShares() trpCleanup() EndFunc ;==>main Func setupdrives() addStudentReadconfigNetworkshares() ; wme cannot reside on k:, but o: can also be read by student, but wmencoder needs a path deleteStudentShare() ; before we reconnect with different permissions, we need to close all connections with current permissions (unless we were given the ip of the server) ; obsolete disconnectserverwriteinstructor() ; how can this be done? hardly drivemapdel is enough? net use? are local admin credentials necessary? ; determine: do this here? $driveletterkreplacementforstudentwrite = addInstructorNetworkshares() ; returns a driveletter $strWMEFileAudio = $driveletterreadconfig & "\" & $dirsharestudentreadconfig & "\" & $strWMEFileAudioName ; $driveletterkreplacementforstudentwrite & "\" & $dirsharestudentreadconfig & "\" & $strWMEFileAudioName ; "K:\Humanities, Arts and Languages\Language_Services\configuration\trprecord_a.wme" $strWMEFileVideo = $driveletterreadconfig & "\" & $dirsharestudentreadconfig & "\" & $strWMEFileVideoName ; $driveletterkreplacementforstudentwrite & "\" & $dirsharestudentreadconfig & "\" & $strWMEFileVideoName ; "K:\Humanities, Arts and Languages\Language_Services\configuration\trprecord_av.wme" EndFunc ;==>setupdrives Func recordstart(ByRef $g_objEncoder, $g_strWMEFile = "") ; this works in principle, with an existing wme-session file, ; done: unlike the gui-wmencoder, the object will overwrite an existing output filename, without need for interaction, even if it is open in wmplayer ; $OEvent=ObjEvent("AutoIt.Error","nothing"); Equal to VBscript's On Error Resume Next ;If a WME file is provided, load the encoding configuration from this WME file. If $g_strWMEFile <> "" Then If Not (FileExists($g_strWMEFile)) Then $set = GUICtrlSetData($guiMsg, "Cannot find config file " & $g_strWMEFile & ", will stop.") myDebugOut(@ScriptLineNumber, "Cannot find wme config file" ) Else ; recordstart($objEncoder, $g_strWMEFile) ; test only, rather stop interactively by passing byref $objEncoder to recordstop ; Sleep(5000) ; recordstop($objEncoder) ; EndIf If IsObj($g_objEncoder) Then $set = GUICtrlSetData($guiMsg, "Now preparing recording...") ; $oMyError = ObjEvent("AutoIt.Error", "MyErrFunc") ; done: crashes when called repeatedly = when recordstart is called repeatedly -> moved to after objcreate(encoder) ; Load enocder session from a WME file myDebugOut(@ScriptLineNumber, "attempting to load encoder profile $g_strWMEFile=" & $g_strWMEFile) $g_objEncoder.Load($g_strWMEFile) ; ( g_objFileSystem.GetAbsolutePathName( g_strWMEFile ) ) ; todo: on error returns 0x8007000E Memory cannot be allocated. - how can i sue this for debuging with ObjEvent ; if you try over-load [what? the output filename?], error: "the requested action with this object has failed."" $set = GUICtrlSetData($guiMsg, "One moment, please...") Sleep(2000) ; the mgb-36 computers are so slow, especially at startup (mcafee?) that we seem to need to go slower than 1000 ; todo: can you shave sth off? rather give the user feedback when recording started ; donot: fiddle with WMEncoder.PrepareToEncode , SynchronizeOperation = false $tempfilename = $g_objEncoder.File.LocalFileName ; not anymore: The requested action with this object has failed.: $g_objEncoder.start $set = GUICtrlSetData($guiMsg, "Now recording to localfilename:" & $tempfilename) myDebugOut(@ScriptLineNumber, "recording to localfilename:" & $tempfilename) Else $set = GUICtrlSetData($guiMsg, "Cannot find encoder, try restarting the application.") myDebugOut(@ScriptLineNumber, "error:encoder not isobject:" & $set) EndIf EndIf Else $set = GUICtrlSetData($guiMsg, "No configuration file specified, will stop. Try restarting the application.") myDebugOut(@ScriptLineNumber, "No wme configuration file specified" ) EndIf EndFunc ;==>recordstart Func recordstop(ByRef $g_objEncoder) ; done: interactively stop (without presetting an encoding duration) $g_objEncoder.stop ; This method does not return a value. ; tested: works myDebugOut(@ScriptLineNumber, "is the encoder stopped? how to tell.. ") ; todo: the network file cannot be played, but the tempfile can, what gives? ; is this cause=d by a mere encoder.stop? does not make sense, should be caused by copy ; is there another method short of destroy encoder to flush the file? ; todo: is it not also possible to rename the tempfile, or will another encoder.start otherwise add to it? but encoder.stop is more than encoder.pause ; donot: destroy the object - only destroy the object when gui/window/app is closed ; this cannot work with byref $g_objEncoder = 0 ; todo: i would need to know when the objEncoder is finished = safe to start work on its outputfile ; test: can i override the filename -> no ; Retrieve an IWMEncFile object and override the name of the archive file specified in the predefined configuration. ; $objIWMEncFile = ObjCreate("WMEncEng.WMEncoder.File") ; fails to create an object $objIWMEncFile = ObjCreate($objEncoder.File) ; müssen wir doch mit dem existierenden object arbeiten ; fails to create an object $objIWMEncFile = ObjCreate("WMEncEng.WMEncoder.File") ; müssen wir doch nicht mit dem existierenden object arbeiten ; $g_objIWMEncFile = $g_objEncoder.File ; this creates an object ; $ret = IsObj($g_objIWMEncFile) ; MsgBox(0,"WMEncEng.WMEncoder.File",$ret) ; File = Encoder.File; ; File.LocalFileName = "C:\\file_name.wmv"; ; $g_objIWMEncFile.LocalFileName = "C:\\tmp\\file_name.wmv"; error: Variable must be of type "Object" even though but ObjCreate did not error ; $objEncoder.File = $objIWMEncFile ;test:andersrum ; $g_objEncoder.start ; Sleep(15000) ; $g_objEncoder.stop EndFunc ;==>recordstop Func backupRecording() ; try to read ; todo: create source file path $ret = FileExists($tempfilename) If $ret Then If (StringRight($tempfilename, 4) = ".wma") Then; audio $ext = ".wma" ; handle a wma file ElseIf (StringRight($tempfilename, 4) = ".wmv") Then $ext = ".wmv";handle a wmv file Else ;error $set = GUICtrlSetData($guiMsg, "Not a legal temp file, cannot determine if audio or video.") myDebugOut(@ScriptLineNumber, "$set=" & $set) EndIf ; donot: leave it to the student to make manual backup copies in personal network home ; make instructor permanent copy of audio file ; done: create target file name from computername & username & datetime & ext ; done: create target file path $networknamefile = "trprecord" & "_" & $nowstring & "_" & @ComputerName & "_" & @UserName & $ext myDebugOut(@ScriptLineNumber, "$networknamefile is: " & $networknamefile) $networkpathfile = FileNameEscape($networknamefile, $driveletterkreplacementforstudentwrite & "\" & $dirsharewriteinstructor); YYYY/MM/DD HH:MM:SS myDebugOut(@ScriptLineNumber, "$networkpathfile is: " & $networkpathfile) ; todo: impersonate ; todo: copy $ret = FileCopy($tempfilename, $networkpathfile, 9) ; FileCopy ( "source", "dest" [, flag] ) ; todo: handle exceptions If ($ret == 0) Then myDebugOut(@ScriptLineNumber, "failed to filecopy: " & $networkpathfile) ; todo: this does not $ret 0, but the networkfile is not full size and does not have the complete audio even when it plays in wmp - is the recorded file closed? $set = GUICtrlSetData($guiMsg, "Failed to save to network, make sure you save your recording : " & $tempfilename) myDebugOut(@ScriptLineNumber, "$set=" & $set) Else $set = GUICtrlSetData($guiMsg, "Saved to network: " & $networknamefile) myDebugOut(@ScriptLineNumber, "$set=" & $set) EndIf Else ; todo: what to try if not fileexists $set = GUICtrlSetData($guiMsg, "tmp recording " & $tempfilename & ": does not exist, cannot save to network.") myDebugOut(@ScriptLineNumber, "$set=" & $set) EndIf ; todo: return 0 if error, 1 if success Return $ret EndFunc ;==>backupRecording Func killpriorInstance() $wmencoderPID = ProcessExists("wmencoder.exe") If $wmencoderPID <> 0 Then $prioruser = _ProcessGetOwner($wmencoderPID) If $prioruser <> @UserName Then ; is owner of wmencoder = currentuser than taskkill ; myDebugOut(@ScriptLineNumber, "prior $wmencoderPID ="& $wmencoderPID & ", $prioruser = " & $prioruser & ", @Username =" & @Username) $ret = MsgBox(1, "Error", "Looks like " & $prioruser & " should stop their trprecord on this computer first. Try again afterwards, I will exit now.") Exit Else ; if priorinstance belongs to @username, just kill it If WinExists($windowtitletrpRecord, "") Then WinKill($windowtitletrpRecord) ; always returns1 ; todo: killing the prior script instance is not enough - the instance may have spawned a wmencoder from the cmdline (since we do not use encoder objects here which would presumably be killed with the creating script) ; we need to kill any (todo: w/o warning to user?) wmencoder.exe process ; determine: which privileges are needed to execute taskkill? tested: a non-admin can use taskkill to kill their own tasks ; test: an admin or system account (teacher-> synchroneyes) should also be able to taskkill other admin and student task $ret = RunWait('taskkill /F /fi "imagename eq wmencoder*" /im *') ; return 0 seems good, sometimes? ; determine: do we need to kill other spawned processes like wmeditor (indexing)? or rather give them time to finish, and the calling script to copy the resulting audiofile EndIf Else ; no wmencoder process, nothing to kill EndIf EndFunc ;==>killpriorInstance Func guioptions() Opt("GUICoordMode", 1) ; 1 = absolute coordinates (default) still relative to the dialog box. 0 = relative position to the start of the last control (upper left corner). ; GUICreate ( "title" [, width [, height [, left [, top [, style [, exStyle [, parent]]]]]]] ) GUICreate($windowtitletrpRecord, 800, 180) GUISetHelp(@ProgramFilesDir & "\Internet Explorer\iexplore.exe http://plagwitz1.spaces.live.com"); todo: add the page to the actual blog entry Dim $msg ; which the user sends through the gui - essentially that he is done updating the controls ; Create the controls ; SET controls by using variables already read into from ini ; groups represent the sections of the ini ; A group control is the thin line you see around controls (usually only Radio button) that visually groups them together. ; If you want to have multiple groups without the visible line then you must use GUIStartGroup() to group your Radio buttons. ; horizontal ; GUICtrlCreateGroup ( "text", left, top [, width [, height [, style [, exStyle]]]] ) Dim $actiontyperecordingvideolivestatus = 0 Dim $actiontyperecordingaudioliveStatus = 1 Dim $actiontyperecordingaudiofileStatus = 0 Dim $actiontyperecordingvideofileStatus = 0 Dim $group_action = GUICtrlCreateGroup("Action", 10, 5, 780, 160); creategroup seems just a canvas in the gui GUIStartGroup() Dim $actiontyperecordingaudioliveCtrl = GUICtrlCreateRadio("Audio Live", 20, 20, 80, 15) Dim $actiontyperecordingvideoliveCtrl = GUICtrlCreateRadio("Video Live", 20, 50, 80, 15) Dim $actiontyperecordingaudiofileCtrl = GUICtrlCreateRadio("Audio with File,Path:", 20, 80, 110, 15) Dim $actiontyperecordingvideofileCtrl = GUICtrlCreateRadio("Audio w/ Video File,Path:", 20, 110, 140, 15) GUICtrlSetState($actiontyperecordingvideoliveCtrl, $actiontyperecordingvideolivestatus) GUICtrlSetState($actiontyperecordingaudioliveCtrl, $actiontyperecordingaudioliveStatus) GUICtrlSetState($actiontyperecordingaudiofileCtrl, $actiontyperecordingaudiofileStatus) GUICtrlSetState($actiontyperecordingvideofileCtrl, $actiontyperecordingvideofileStatus) ; todo: enable this if $actiontyperecordingaudiofile chosen Dim $inputAudiofilepath = $driveletterkreplacementforstudentwrite & "\" & $dirsharestudentreadconfig ; dim $audiofilelabelctrl = GUICtrlcreateLabel( "File with Audio" , 300, 180, 280,15) Dim $inputAudiofilepathCtrl = GUICtrlCreateInput($inputAudiofilepath, 160, 80, 580, 15) Dim $inputvideofilepath = $driveletterkreplacementforstudentwrite & "\" & $dirsharestudentreadconfig ; dim $audiovideolabelctrl = GUICtrlcreateLabel( "Video File with Audio" , 300, 210, 280,15) Dim $inputvideofilepathCtrl = GUICtrlCreateInput($inputAudiofilepath, 160, 110, 580, 15) Dim $button_start = GUICtrlCreateButton("&Start", 130, 20, 50, 50) Dim $button_stop = GUICtrlCreateButton("Sto&p", 190, 20, 50, 50) Dim $button_play = GUICtrlCreateButton("Play", 250, 20, 50, 50) ; todo: fails: Dim $button_play = GUICtrlCreateButton("Play" & @CRLF & " &Last", 250, 20, 50, 50, $BS_MULTILINE) Dim $button_open = GUICtrlCreateButton("&Open" & @CRLF & "Folder", 310, 20, 50, 50, $BS_MULTILINE) ; todo:fails ; Dim $statuslabelcontrol GUICtrlcreateLabel( "For trpRecording starting, Choose Action and press Start" , 300, 180, 280,15) ;global $guiMsg = GUICtrlCreateLabel("Look here for important messages. Press F1 for help.", 360, 20, 450, 50) ; use with GUICtrlSetData ($guimsg, "my message") GUICtrlSetColor($guiMsg, 0xff0000) ; Red GUICtrlSetState($button_start, $GUI_FOCUS + $GUI_DEFBUTTON) GUICtrlSetState($button_stop, $GUI_DISABLE) GUICtrlSetState($button_play, $GUI_DISABLE) GUICtrlSetState($actiontyperecordingaudiofileCtrl, $GUI_DISABLE) GUICtrlSetState($actiontyperecordingvideofileCtrl, $GUI_DISABLE) GUICtrlSetState($inputAudiofilepathCtrl, $GUI_DISABLE) GUICtrlSetState($inputvideofilepathCtrl, $GUI_DISABLE) GUISetState() While 1 $msg = GUIGetMsg() Select Case $msg = $GUI_EVENT_CLOSE ; todo: here also? ; donot: destroy the encoder object - only destroy the object when gui/window/app is closed $g_objEncoder = 0 trpCleanup(); could do ExitLoop, but probably better to exit ; donot: cannot happen, $actiontyperecordingaudiofileCtrl disabled, action not implemented Case $msg = $actiontyperecordingaudiofileCtrl ; todo: how to check for radio button $actiontyperecordingaudiofile selected? $set = GUICtrlSetData($guiMsg, "") myDebugOut(@ScriptLineNumber, "$set=" & $set) ; todo: enable $inputAudiofilepathCtrl GUICtrlSetState($inputAudiofilepathCtrl, $GUI_ENABLE) ; todo: disable $inputAudiofilepathCtrl GUICtrlSetState($inputvideofilepathCtrl, $GUI_DISABLE) $actiontyperecordingvideofileStatus = 0 $actiontyperecordingvideolivestatus = 0 $actiontyperecordingaudioliveStatus = 0 $actiontyperecordingaudiofileStatus = 1 ; donot: cannot happen, $actiontyperecordingvideofileCtrl disabled, action not implemented Case $msg = $actiontyperecordingvideofileCtrl ; todo: how to check for radio button $actiontyperecordingaudiofile selected? $set = GUICtrlSetData($guiMsg, "") myDebugOut(@ScriptLineNumber, "$set=" & $set) GUICtrlSetState($inputvideofilepathCtrl, $GUI_ENABLE) ; todo: disable $inputAudiofilepathCtrl GUICtrlSetState($inputAudiofilepathCtrl, $GUI_DISABLE) $actiontyperecordingvideofileStatus = 1 $actiontyperecordingvideolivestatus = 0 $actiontyperecordingaudioliveStatus = 0 $actiontyperecordingaudiofileStatus = 0 Case $msg = $actiontyperecordingvideoliveCtrl ; todo: how to check for radio button $actiontyperecordingvideofile selected? $set = GUICtrlSetData($guiMsg, "") myDebugOut(@ScriptLineNumber, "clerared gui:" & $set) ; todo: disable $inputvideofilepathCtrl GUICtrlSetState($inputvideofilepathCtrl, $GUI_DISABLE) ; todo: disable $inputAudiofilepathCtrl GUICtrlSetState($inputAudiofilepathCtrl, $GUI_DISABLE) $actiontyperecordingvideofileStatus = 0 $actiontyperecordingvideolivestatus = 1 $actiontyperecordingaudioliveStatus = 0 $actiontyperecordingaudiofileStatus = 0 Case $msg = $actiontyperecordingaudioliveCtrl ; todo: how to check for radio button $actiontyperecordingaudiofile selected? $set = GUICtrlSetData($guiMsg, "") myDebugOut(@ScriptLineNumber, "$set=" & $set) ; todo: disable $inputAudiofilepathCtrl ; was sollte das? ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : todo: = ' & todo: & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console GUICtrlSetState($inputAudiofilepathCtrl, $GUI_DISABLE) ; todo: disable $inputAudiofilepathCtrl GUICtrlSetState($inputAudiofilepathCtrl, $GUI_DISABLE) $actiontyperecordingvideolivestatus = 0 $actiontyperecordingaudioliveStatus = 1 $actiontyperecordingaudiofileStatus = 0 Case $msg = $button_start GUICtrlSetState($button_start, $GUI_DISABLE) GUICtrlSetState($button_stop, $GUI_ENABLE) $set = GUICtrlSetData($guiMsg, "Please wait...") myDebugOut(@ScriptLineNumber, "asking to wait=" & $set) If $actiontyperecordingaudiofileStatus Then ; dolater: not implemented If Not FileExists($inputAudiofilepath) Then MsgBox(0, "Error", "Enter a valid file name!") Else MsgBox(0, "Error", "Not implemented yet!") ; todo: set param, like this recordingstart($actiontyperecording = "audiofile", $inputAudiofilepath) EndIf ElseIf $actiontyperecordingvideolivestatus Then ; todo: set param, like this recordingstart($actiontyperecording = "videolive") ; $ret = recordingstart("videolive") ; old approac $ret = recordingstart("videolive") ; new approach with encoder-object ; done: capture datetime for file-postprocessing $nowstring = StringRegExpReplace(_NowCalc(), "[\s\/\:]", "_") ; done: does now get written, since no illegal chars get passed anymore paassed filenameescape myDebugOut(@ScriptLineNumber, $nowstring & ": trying to encode with $strWMEFileVideo=" & $strWMEFileVideo) myDebugOut(@ScriptLineNumber, "calling recordstart to encode with strWMEFileVideo=" & $strWMEFileVideo) $ret = recordstart($objEncoder, $strWMEFileVideo) ElseIf $actiontyperecordingaudioliveStatus Then ; $ret = recordingstart("audiolive") ; old approach $ret = recordingstart("audiolive") ;new approach encoder-object ; done: capture datetime for file-postprocessing $nowstring = StringRegExpReplace(_NowCalc(), "[\s\/\:]", "_") myDebugOut(@ScriptLineNumber, "calling recordstart to encode with $strWMEFileAudio=" & $strWMEFileAudio) $ret = recordstart($objEncoder, $strWMEFileAudio) ElseIf $actiontyperecordingvideofileStatus Then ; dolater: not implemented If Not FileExists($inputvideofilepath) Then MsgBox(0, "Error", "Enter a valid file name!") Else ; todo: set param, like this recordingstart($actiontyperecording = "videofile") MsgBox(0, "Error", "Not implemented yet!") EndIf EndIf Case $msg = $button_stop GUICtrlSetState($button_stop, $GUI_DISABLE) $set = GUICtrlSetData($guiMsg, "Please wait...") ; GUICtrlSetData($guiMsg, "Now recording to localfilename:" & $tempfilename) myDebugOut(@ScriptLineNumber, "$set=" & $set) ; not together, make a separate play button; $ret = recordingstopandplay() ; donot: (rather use encoder-object) differentiate whether indedexing or postprocessing required and whether to index audio or video ; new approach using encoder-object $ret = recordstop($objEncoder) ; todo: backup file to network, using impersonation Sleep(3000) ; half-done: the backuprecording is not complete when you do not give the enco der time to finish its saving after stop ; todo: is sleep(2000) enough time for large video files? maybe, filecopy comes later, i do not thinkg the encoder flushes all from memory when stopped $ret = backupRecording() GUICtrlSetState($button_start, $GUI_ENABLE) ; enable record again, the object-encoder has been stopped ; done: enable "play last"button GUICtrlSetState($button_play, $GUI_ENABLE) If Not ($ret == 0) Then $set = GUICtrlSetData($guiMsg, "Finished. Play your recording now or open folder to work with it.") myDebugOut(@ScriptLineNumber, "$set=" & $set) Else $set = GUICtrlSetData($guiMsg, "There was a problem saving your file to the network. You should save the local copy manually from " & @TempDir); todo myDebugOut(@ScriptLineNumber, "$set=" & $set) EndIf Case $msg = $button_play ; todo: this does not seem to do anything, not even guictrlsetdata $set = GUICtrlSetData($guiMsg, "Please wait...") myDebugOut(@ScriptLineNumber, "$set=" & $set) ; GUICtrlSetState($button_play, $GUI_DISABLE); donot: you do not know when the player has been close ; not together, make a separate play button; $ret = recordingstopandplay() ; donot: (rather use encoder-object) differentiate whether indexing or postprocessing required and whether to index audio or video ; new approach using encoder-object ; todo: change to proper variable names $networkpath & $currentfilename If FileExists($tempfilename) Then ; todo: i want to open thefile not with the default player which might be vlc, but with wmplayer myDebugOut(@ScriptLineNumber, "$tempfilename exists") ; this is reached $set = GUICtrlSetData($guiMsg, "Playing last recording from local temp recording.") myDebugOut(@ScriptLineNumber, "$set=" & $set) $ret = ShellExecute($tempfilename, "", @TempDir, "open") ; i do not think guimsg will be meaningful ElseIf FileExists($networkpathfile) Then ; fails ElseIf FileExists($driveletterkreplacementforstudentwrite & "\" & $dirsharewriteinstructor & "\" & $networknamefile) Then ;fails $ret = Run($driveletterkreplacementforstudentwrite & "\" & $dirsharewriteinstructor & "\" & $networknamefile, @TempDir, @SW_HIDE, 8) ; i do not think guimsg will be meaningful myDebugOut(@ScriptLineNumber, "$networkpathfile exists") $ret = ShellExecute($networkpathfile, "", @TempDir, "open") ; $set = GUICtrlSetData($guiMsg, "ATTENTION: no local copy") ; todo: & @CRLF & ", instead playing saved file from network.") myDebugOut(@ScriptLineNumber, "$set=" & $set) Else $set = GUICtrlSetData($guiMsg, "ERROR: last recording not found: " & @CRLF & $networknamefile & " or " & $tempfilename) myDebugOut(@ScriptLineNumber, "$set=" & $set) EndIf Case $msg = $button_open $set = GUICtrlSetData($guiMsg, "Please wait...") myDebugOut(@ScriptLineNumber, "$set=" & $set) ; GUICtrlSetState($button_stop, $GUI_DISABLE) ; donot: cannot check whether explore window has been closed, need not, if run open folder reissued, old on will be activatd ; not together, make a separate play button; $ret = recordingstopandplay() ; donot: (rathe use encoder-object) differentiate whether indedexing or postprocessing required and whether to index audio or video ; new approach using encoder-object ; todo: what is the proper variable names $ret = ShellExecute($driveletterkreplacementforstudentwrite & "\" & $dirsharewriteinstructor, "", @TempDir, "open") ; i do not think guimsg will be meaningful ; todo: enable "play last"button GUICtrlSetState($button_start, $GUI_ENABLE) GUICtrlSetState($button_play, $GUI_ENABLE) $set = GUICtrlSetData($guiMsg, "Done...") myDebugOut(@ScriptLineNumber, "$set=" & $set) Case Else ; ExitLoop rubbish, this will lead to an exit EndSelect WEnd ; todo: here? ; donot: destroy the encoder object - only destroy the object when gui/window/app is closed $g_objEncoder = 0 GUIDelete() EndFunc ;==>guioptions Func recordingstart($actiontyperecording = "audiolive", $inputAudiofilepath = "") Dim $arrinputAudiofilepath If $actiontyperecording = "audiolive" Then $wmefilename = $wmefilenamerecordaudiolive ElseIf $actiontyperecording = "videolive" Then $wmefilename = $wmefilenamerecordvideolive ; todo: this uses the default video source for live input - what ever shows there through the crestron, interpreting student or interpreter ElseIf $actiontyperecording = "audiofile" Then ; dolater: file - you cannot omit or override ion the cmdline filesnames in a wme ; - so either work with the cmdline input/output and not with wme ; or (if you need the wme for params that the cmdline cannot have, like timestretch), work with renaming files before inputting/after outputting to wme $wmefilename = $wmefilenamerecordaudiofile ;recordaudiofile.wme ; dolater: me needs to point to the defaultfile source.ext ; dolater: for file, the duration needs to be read from the file and the $wmefilename duration overwritten on the cmdline - is this possible? ; wmcmd.vbs says [-duration] <seconds> Amount of time in seconds to encode. Use when sourcing from devices.- ok with files? ; dolater: rip the audio (also get the duration - needs to be done first) with wemenc:!! ; dolater: how will you also play the file to the student? run(), opening with the default player ; dolater: is it not a restriction that wme can not do multi-channel ; donot: copy the file to a local temp location to avoid concurrency issues and with a generic name equal the the name p filesource hardcoded in $wmefilenamerecord = "recordaudiofile.wme" $ret = FileCopy2LocalTemp($arrinputAudiofilepath) If $ret = 0 Or @error Then ; dolater: making local copy failed EndIf ; we do not need to know whether audio or video, wmencoder can use both as audio source $inputAudiofilepathnameext = ; get file extension ;$ret = FileCopy($inputAudiofilepath, @tempdir & "\"& $inputAudiofilepathname ) ; would need to check whether copy is same as original ; dolater: audiofile (&videofile, audio only): ; wme out of the box does not allow combine audio channels (of pre-existing file and live recording) ; so you need to open the file (with the defaultapp) ; wmenc:captureaudiomonowav.wme: record the live student input, ; save the recording as MONO +WAV ; -> left.wav ; wmenc:rippaudiomonowav.wme rips from the pre-existing file the audio as MONO +WAV (you could use a video directly, but only if it is an WMV->AVI with mono audio) ; -> right.wav ; WavAviMux.exe can combine 2? mono (->monotize) wav(-> unpack! up to 2gb) channels (including from avi, w/o video, w/o 2gb limit) ; -> stereowav.avi: To wrap a stereo file with no video- >: wavavimux -o stereowav.avi -iwav 2 left.wav right.wav -mask 3 ; wmeenc:stereowav2wma.wme can compress avi:audio -> mp3 or wma: stereowav.avi -> [regular filename].wma ElseIf $actiontyperecording = "videofile" Then $wmefilename = $wmefilenamerecordaudiofile ;recordvideofile.wme ; dolater: wme needs to point to the defaultfile source.ext ; dolater: for file, the duration needs to be read from the file and the $wmefilename duration overwritten on the cmdline - is this possible? ; wmcmd.vbs says [-duration] <seconds> Amount of time in seconds to encode. Use when sourcing from devices.- ok with files? ; optional: videofile, with video - $actiontyperecordingavideofileStatus ; videofile optional can also do: ; wmenc:rippvideoavi.wme rips from the pre-existing file the audio as MONO +WAV (you could use a video directly, but only if it is an WMV->AVI with mono audio) ; WavAviMux.exe can combine 2? mono (->monotize) wav(-> unpack! up to 2gb) channels (including from avi, w/o video, w/o 2gb limit) ; To wrap a stereo file with video- >: wavavimux -iavi [input AVI file name] -o videostereowav.avi -iwav 2 left.wav right.wav -mask 3 ; the following indexing postprocessing actions are not needed, if we use encoderobject.stop instead of taskkill ; the following actions are internal (to recordingstopandplay) and not visible in the GUI ElseIf $actiontyperecording = "audioindex" Then ; there is not control for indexing in the gui, it is chose indirectly through button stop $wmefilename = $wmefilenamerecordaudioindexing ElseIf $actiontyperecording = "videoindex" Then ; there is not control for indexing in the gui, it is chose indirectly through button stop $wmefilename = $wmefilenamerecordaudioindexing EndIf ; IDENTIFY THE WMENC PROCESS ;this should check for a wmencoder process initated by admin - a remote controlled version of this script - and exit if there is one ; this should also check for another wemencoder process by current user - maybe user clicked twice, return message to "first stop prior recording session", then If ProcessExists($wmencexe) Then ; who is the owner of the prior wmenc.exe? "user name"of "image name" $strUser = _ProcessGetOwner($wmencexe); todo:requires wmi , does wmi require admin rights? If @error Then ; we cannot determine the user to the process -> play it safe $ret = MsgBox(0, "Error", "First stop current recording session, or talk to admin.") trpCleanup() EndIf ; error If $strUser = @UserName Then ; the process belongs to the current user -> guide her $ret = MsgBox(0, "Error", "First stop your current recording session, by running " & $recordingstopstring) ; browse to web-interface for $recordingstopstring ShellExecute($webinterfacestring) trpCleanup() Else ; todo: is this automatically the admin? what about logging in as different user? $ret = MsgBox(0, "Error", "Smile, you are already being recorded.") Exit ; nor sute i can trpCleanup() here EndIf Else ; no other wmenc process -> proceed normally EndIf ; processexists ; donot: provide an indicator that recording is running ; $ret = ; done: have 2 buttons start/stop and start gets greyed if pressed or, - indicator style only, no gui - , with stop, if admin started from the cmdline ; the trprecord.exe needs to remains running after start on client - whethe started from client or server ; another instance checks not only for wmeenc but also for filename.exe and stops a prior filename.exe also ; should this be autoit ; - then $recordingstopstring needs not only stop wmenc.exe, but also record.exe ; then indicator should contain a link to stop recording, which ends record.exe after launching $recordingstopstring ; or a visible wmcmd.vbs window is enough? ; that however could be stopped by user (could it if launched remotely by admin? but then not visible? psexec not, synchroneyes yes? ) manually also, not tragic while we have no remote control, but once we do, bad EndFunc ;==>recordingstart Func recordingstopandplay() ; todo: destroy gui ; todo: what is a good way to pass the filename to the $recordingstopstring ; mostrecent wma in tempdir? ; there might be more than one unindexed wma (if computer logged off? does this not clean the tempdir?) ; overwrite path to create time-specific (that does not overwrite) local file ; done: do not create file on network (can be down) or local (would probably be lost on restart - copy to network at end) ; find local file ; run ; donot: check homedir ; donot:copy local file to homedir addInstructorNetworkshares() ; identify a prior GUI and stop it (not myself) If ProcessExists($scriptfilewithexe) Then ; it is Not me ; todo EndIf ; IDENTIFY THE WMENC PROCESS ;this should check for a wmencoder process initiated by admin/instructor-user/synchroneyes-user - a remote controlled version of this script - and exit if there is one ; this should also check for another wmencoder process by current user - maybe user clicked twice, return message to "first stop prior recording session", then If ProcessExists($wmencexe) Then ; who is the owner of the prior wmenc.exe? "user name"of "image name" $strUser = _ProcessGetOwner($wmencexe); todo:requires wmi , does wmi require admin rights? If @error Then $ret = MsgBox(0, "Error", "First stop current recording session, or talk to admin.") Exit ; nor sure i can trpCleanup() here EndIf ; error If $strUser = @UserName Then $ret = MsgBox(0, "Error", "First stop your current recording session, by running " & $recordingstopstring) ; browse to web-interface for $recordingstopstring ShellExecute($webinterfacestring) Exit Else ; todo: is this automatically the admin? what about logging in as different user? $ret = MsgBox(0, "Error", "Smile, you are being recorded (let's hope it's your admin).") Exit EndIf Else EndIf ; processexists ; IDENTIFY THE AUDIO FILE WE NEED TO WORK ON $myfiles = _FileListToArray(@TempDir, "rec_*.wma", 1) ; _FileListToArray($sPath[, $sFilter = "*"[, $iFlag = 0]]) ; @Error: 1 = Path not found or invalid ; $iFlag=1 Return files only ; sort the array, excluding the element=0=elemenetcounter, ascending ; todo: how does this arraysort identify the audiofil to work on? only if the audiofilename contains a datetimecreationstring, but then the sort should be descending, to put the largest=latest audiofile first ; todo: better upon fiel creration store the current (datetime) filename in a variable an refer to this variable throughout _ArraySort($myfiles, 1, 1) ; ArraySort(ByRef $avArray[, $iDescending = 0[, $iStart = 0[, $iEnd = 0[, $iSubItem = 0]]]]) ; array elements contain just the filenames, plus the counter, which will always be first element-counter (besides, we exclude the element-counter from sort) after sort (since filenames start with rec_) ; INDEXING (the audio file will (todo: really?) always be unindexed due to taskkill of wmenc to stop) ; donot: open the audio file in wmeditor to index, alt+_file /_save and index, alt+_file /e_xit and close : awkard, and can you issue keystrokes with a hidden window ; wmeditor can not be called form the cmdline, you cannot even run wmeditor with a file to open, so also open has to be done with keystrokes ; rather todo: wmenc can and has an AutoIndex Specifies and retrieves a value indicating whether the archive file will be indexed after the archiving process is completed. ; but it is overkill to reencode and save as the file just to index it ; WMEncoder Encoder; ; Encoder = new WMEncoder(); ; attempt ; oWMEncoder = objcreate("WMEncEng.WMEncoder") ; If @error then ; $ret = msgbox("failed to created object") ; else ; Encoder.Load ("C:\filename.wme") ; basics, same as record.wme, or even entire, but then change source to files and output to new filename, on ; set inputfile ; set outputfile ; bool bAutoIndex; ; // Configure the encoding session to archive encoded content. ; // For a complete example, see either the IWMEncFile object or the IWMEncFileArchiveStats object. ; // Specify the AutoIndex property. ; Encoder.AutoIndex = true; ; Encoder.Start ; endif ; @error objecreate? ; ODER SO, laut chm ; using WMEncoderLib; ; Create the WMEncBasicEdit object. ;todo: use this: WMEncBasicEdit BasicEdit = new WMEncBasicEdit(); ; Specify the input and output files. ;BasicEdit.MediaFile = "C:\\InputFile.wmv"; ; %2 ;BasicEdit.OutputFile = "C:\\OutputFile.wmv"; ; %3 ; Specify a configuration file. ;BasicEdit.ConfigFile = "C:\\ConfigFile.txt"; ; %1 ; Add indexing to the file. ;BasicEdit.Index = True;don't you need to start the encoding bei claling one of tis method after setting its properties? ; oder doch wieder run-wmcmd.vbs ; [-wme] <Windows Media Encoder session file> ; [-profile] <profile code> ; [-loadprofile] <profile file name> // what is the difference between -profile and -loadprofile? a64: Profile_AudioOnly_CDQuality_64K (64 Kbps) ; [-input] ; [-output] <file or directory name> ; cscript.exe c:\windows\wmcmd.vbs -input g:\videoinput.avs -output g:\videooutput.wmv -v_codec WVC1 -videoonly -v_mode 0 -v_preset better -v_bitrate 8000000 -v_keydist 3 -v_buffer 600000 -v_quality 100 -s_config own.weu ; Run ( "filename" [, "workingdir" [, flag[, standard_i/o_flag]]] ) $ret = Run("cscript.exe " & $wmcmdvbspath & " - wme " & $driveletterkreplacementforstudentwrite & "\" & $dirsharestudentreadconfig & "\" & $wmefilename & " -input " & @TempDir & "\" & $myfiles[1] & "-output " & @TempDir & "\" & "i" & $myfiles[1], @TempDir, @SW_HIDE, 8) If $ret = 0 Then myDebugOut(@ScriptLineNumber, "failed to run indexing vbs: " & $wmcmdvbspath & " - wme " & $driveletterkreplacementforstudentwrite & "\" & $dirsharestudentreadconfig & "\" & $wmefilename & " -input " & @TempDir & "\" & $myfiles[1] & "-output " & @TempDir & "\" & "i" & $myfiles[1]) Else ; no error : replace unindexed original audio file $ret = FileCopy(@TempDir & "\" & "i" & $myfiles[1], @TempDir & "\" & $myfiles[1]) EndIf ; @error indexing? ; todo:open output from local in wmplayer - either the indexed, or, if error, the unindexed version $ret = Run(@TempDir & "\" & $myfiles[1], @TempDir, @SW_HIDE) ; do this first, this will take some time and focus the attention of the user away from the script finishing If $ret = 0 Then myDebugOut(@ScriptLineNumber, "failed to open indexed audio file:" & @TempDir & "\" & "i" & $myfiles[1]) ; make student permanent copy of audio file $ret = FileCopy(@TempDir & "\" & $myfiles[1], $uncpathwritestudent & "\" & $myfiles[1], 9) ; FileCopy ( "source", "dest" [, flag] ) If $ret = 0 Then myDebugOut(@ScriptLineNumber, "failed to filecopy:" & $uncpathwritestudent & "\" & $myfiles[1]) ; make instructor permanent copy of audio file $ret = FileCopy(@TempDir & "\" & $myfiles[1], $driveletterkreplacementforstudentwrite & "\" & $dirsharewriteinstructor & "\" & $myfiles[1], 9) ; FileCopy ( "source", "dest" [, flag] ) If $ret = 0 Then myDebugOut(@ScriptLineNumber, "failed to filecopy:" & $driveletterkreplacementforstudentwrite & "\" & $dirsharewriteinstructor & "\" & $myfiles[1]) ; cleanup before next iteration $ret = DriveMapDel($driveletterkreplacementforstudentwrite) If $ret = 0 Then myDebugOut(@ScriptLineNumber, "failed to DriveMapDel for: " & $driveletterkreplacementforstudentwrite & ", @error=" & @error) Exit EndFunc ;==>recordingstopandplay Func streamVideo() Dim $WMENC_VIDEO = 2 Dim $WMENC_AUDIO = 1 Dim $WMENC_PROTOCOL_HTTP = 1 $object = ObjCreate("WMEncEng.WMEncoder") If @error Then MsgBox(0, "Error", "Couldn't create object! Exiting...") Else $SrcGrpColl = $object.SourceGroupCollection $SrcGrp = $SrcGrpColl.Add("SG_1") $SrcVid = $SrcGrp.AddSource($WMENC_VIDEO) $SrcAud = $SrcGrp.AddSource($WMENC_AUDIO) $SrcVid.SetInput("DEVICE://Default_Video_Device") $SrcAud.SetInput("DEVICE://Default_Audio_Device") $ProColl = $object.ProfileCollection $lLength = $ProColl.Count For $i = 0 To $lLength - 1 $Pro = $ProColl.Item($i) If $Pro.Name = "Windows Media Video 8 for Local Area Network (384 Kbps)" Then $SrcGrp.Profile = $Pro ExitLoop EndIf Next $Broadcast = $object.Broadcast $Broadcast.PortNumber($WMENC_PROTOCOL_HTTP) = 8010 $object.Start While 1 Sleep(100) WEnd $object.Stop EndIf EndFunc ;==>streamVideo Func streamAudio() ; Overview: This script opens a default.wme file and edits it to suit ; our needs. Then it runs the encoder application in hidden mode ; and begins both broadcasting a live stream ; and saving a copy to a network drive for archival purposes. ; When the user stops the broadcast ; the application is closed and the archived file is FTP'd to another server GUICreate("Audio Encoder", 410, 200) $Label_1 = GUICtrlCreateLabel("Type in a title for the broadcast and then click the button below", 30, 20, 300, 21, 0x00000020) $Label_2 = GUICtrlCreateLabel("", 30, 130, 300, 21, 0x00000020) $input_1 = GUICtrlCreateInput("", 30, 40, 350, 21) $button2 = GUICtrlCreateButton("Stop Broadcasting", 150, 80, 100, 30) GUICtrlSetState($button2, $GUI_HIDE) $button1 = GUICtrlCreateButton("Begin Broadcasting", 150, 80, 100, 30) $progbar = GUICtrlCreateProgress(30, 150, 350, 30, $PBS_SMOOTH) GUISetState() While 1 $msg = GUIGetMsg() Select Case $msg = $button1 ; begin broadcasting $data = GUICtrlRead($input_1) ; title for broadcast GUICtrlSetData($Label_1, $data) GUICtrlDelete($input_1) GUICtrlDelete($button1) GUICtrlSetState($button2, $GUI_SHOW) Initiate($data) Case $msg = $button2 GUICtrlSetData($Label_2, "Stopping Encoder") trpCleanup() Case $msg = $GUI_EVENT_CLOSE GUICtrlSetData($Label_2, "Stopping Encoder") trpCleanup() EndSelect WEnd EndFunc ;==>streamAudio Func Initiate($var) elog("=============================") GUICtrlSetData($Label_2, "Configuring System") GUICtrlSetData($progbar, 0) $newtitle = $var elog(day() & time() & " User input Title: " & Chr(34) & $newtitle & Chr(34)) ; open files for reading / re-writing ; todo: this opens wme-gui and automates it, not what i want $default = FileOpen("C:\encode\script\default.wme", 0) ; todo: remove strings $start = FileOpen("C:\encode\script\start.wme", 2); todo: remove strings If $default = -1 Then MsgBox(0, "Error", "Unable to open 'default.wme' file.") trpCleanup() EndIf If $start = -1 Then MsgBox(0, "Error", "Unable to open 'start.wme' file.") myCleanup() EndIf ; map network drive for temp storing the archive file ; If you specify "*" an unused drive letter will be automatically selected. $drv = DriveMapAdd("*", "\\Server\ShareName$") ; todo: remove string elog(day() & time() & " Attempting to map Network Drive - " & $drv) Sleep(2000) If $drv = "" Then ; todo: seems wrong check, DriveMapAdd Returns 0 if a new mapping could not be created and sets @error (see below). $drv = "C:\encode\archive" Select Case @error = 1 $comment = "1. Undefined / Other error" Case @error = 2 $comment = "2. Access to the remote share was denied" Case @error = 3 $comment = "3. The device is already assigned" Case @error = 4 $comment = "4. Invalid device name" Case @error = 5 $comment = "5. Invalid remote share" Case @error = 6 $comment = "6. Invalid password" EndSelect elog(day() & time() & " Could not map network drive. Error was: " & $comment) EndIf GUICtrlSetData($Label_2, "Creating system parameters") GUICtrlSetData($progbar, 25) ; format necessary info $oldtitle = "CHANGE_TITLE" $oldpath = "C:\CHANGE_PATH.wma" $name = StringLeft($newtitle, 10) ; $newtitle is what the user entered $name = StringReplace($name, " ", "") $name = StringReplace($name, "/", "") $name = StringReplace($name, ";", "") $name = StringReplace($name, ",", "") $name = StringReplace($name, "'", "") $name = StringReplace($name, ":", "") $name = StringReplace($name, "?", "") $name = StringReplace($name, "~", "") $name = StringReplace($name, "@", "") $name = StringReplace($name, "!", "") $name = StringReplace($name, "$", "") $name = StringReplace($name, "*", "") $name = StringReplace($name, "<", "") $name = StringReplace($name, ">", "") $name = day() & $name & ".wma" $fullpath = $drv & "\" & $name elog(day() & time() & " Archive file = " & $fullpath) ; create a custom start.wme file While 1 $line = FileReadLine($default) If @error = -1 Then ExitLoop; -1 means the end of the file If StringInStr($line, $oldtitle) Then $line = StringReplace($line, $oldtitle, $newtitle) ElseIf StringInStr($line, $oldpath) Then $line = StringReplace($line, $oldpath, $fullpath) EndIf FileWriteLine($start, $line) WEnd FileClose($default) FileClose($start) GUICtrlSetData($Label_2, "Starting Encoder Program") GUICtrlSetData($progbar, 50) ; run encoding program in hidden mode Run("C:\Program Files\Windows Media Components\Encoder\wmenc.exe c:\encode\script\start.wme", "", @SW_HIDE) WinActivate("Audio Encoder"); shift focus back to our app While 1 Sleep(500) If WinExists("start - Windows Media Encoder") Then Sleep(2000); give it a couple seconds before proceeding ExitLoop EndIf WEnd GUICtrlSetData($Label_2, "Initiating Encoder") GUICtrlSetData($progbar, 75) ; Send keys to begin broadcasting ControlSend("start - Windows Media Encoder", "", "Titan:CToolBar1", "^E", 0) elog(day() & time() & " Started Encoding") ; Do some error checking to ensure the archive file is being created $count = 0 While 1 If FileExists($fullpath) Then elog(day() & time() & " Archive file took " & $count & " sec to create") ExitLoop Else Sleep(1000) $count = $count + 1 If $count > 10 Then elog(day() & time() & " File not found within 10 seconds, killing process") WinKill("start - Windows Media Encoder") DriveMapDel($drv) $msg = MsgBox(0, "Error", "There has been an error, please " _ & "contact an administrator if this problem persists") Exit EndIf EndIf WEnd GUICtrlSetData($progbar, 100) GUICtrlSetData($Label_2, "Broadcasting Live") EndFunc ;==>Initiate Func myCleanup() ControlSend("start - Windows Media Encoder", "", "Titan:CToolBar1", "^S", 0) GUICtrlSetData($progbar, 0) GUICtrlSetData($Label_2, "Ending Session") ; give the encoder enough time to stop (move progress bar while waiting) $movebar = 0 While 1 GUICtrlSetData($progbar, $movebar) Sleep(1000) $movebar = $movebar + 10 If $movebar > 99 Then ExitLoop WEnd WinClose("start - Windows Media Encoder") ; wait for encoder program to close GUICtrlSetData($Label_2, "Closing Encoder Application") $movebar = 0 While 1 Sleep(500) If WinExists("start - Windows Media Encoder") Then GUICtrlSetData($progbar, $movebar) $movebar = $movebar + 10 If $movebar > 99 Then $movebar = 0 Else ExitLoop EndIf WEnd elog(day() & time() & " Begin FTP") ; FTP file to media server If FileExists($fullpath) Then GUICtrlSetData($progbar, 60) GUICtrlSetData($Label_2, "Sending Archive file to Media Server") $server = '192.168.1.1'; IP of server $username = 'UserName' $pass = "PassWord" $Open = _FTPOpen('MyFTP Control') $Conn = _FTPConnect($Open, $server, $username, $pass) $Ftpp = _FtpPutFile($Conn, $fullpath, $name) $Ftpc = _FTPClose($Open) elog(day() & time() & " Completed FTP of temp file") FileDelete($fullpath) elog(day() & time() & " Deleted temp file") GUICtrlSetData($Label_2, "Transfer Completed... Closing Application") GUICtrlSetData($progbar, 100) DriveMapDel($drv) Sleep(2000) Exit Else MsgBox(0, "Done", "Archived File not found.") elog(day() & time() & " Temp file did not exist") DriveMapDel($drv) Exit EndIf elog(day() & time() & " Closing Application Successfully") EndFunc ;==>myCleanup Func elog($txt) $ix = FileOpen("C:\encode\script\errorlog.txt", 1) FileWriteLine($ix, $txt) If $ix = -1 Then MsgBox(0, "Error", "Unable to open 'error.txt' file.") Exit EndIf FileClose($ix) EndFunc ;==>elog Func day() $iday = @YEAR & @MON & @MDAY Return $iday EndFunc ;==>day Func time() $iTime = @HOUR & @MIN & @SEC Return $iTime EndFunc ;==>time ; Function Name: _ProcessGetOwner() ; Description: Get the owner of an open process ; Parameter(s): $vProcess - PID of a process. ; $strComputer - Name of target computer ; Requirement(s): AutoIt Beta v3.2.+ ; cimwin32.dll (included with Windows) ; Return Value(s): On Success - Returns owners username of process ; 0 - Successful, returns username ; ; On Failure: Returns friendly errormessage and sets @Error to: ; 2 - Access denied ; 3 - Insufficient privilege ; 8 - Unknown failure ; 21 - Path not found ; Author(s): Andreas Fälldin ;=============================================================================== Func _ProcessGetOwner($vProcess, $strComputer = "") Local $i_PID = ProcessExists($vProcess) If Not $i_PID Then SetError(1) Return -1 EndIf Local $wbemFlagReturnImmediately = 0x10 Local $wbemFlagForwardOnly = 0x20 Local $colItems = "" Local $strUser = "" ; The local computer name in the object path can be replaced with '.' ; The computer name can also be omitted from the object path, in which case the local computer is assumed. If $strComputer = "" Then $strComputer = "localhost" $objWMIService = ObjGet("winmgmts:{impersonationLevel=impersonate}!\\" & $strComputer & "\root\CIMV2") $colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_Process WHERE ProcessID = " & $i_PID, "WQL", _ $wbemFlagReturnImmediately + $wbemFlagForwardOnly) If IsObj($colItems) Then For $objItem In $colItems $rc = $objItem.GetOwner($strUser) Switch $rc Case 0 SetError(0) Return $strUser Case 2 SetError(2) Return "ACCESS DENIED" Case 3 SetError(3) Return "INSUFFICIENT PRIVILEGE" Case 8 SetError(8) Return "UNKNOWN FAILURE" Case 9 SetError(9) Return "PATH NOT FOUND" Case 21 SetError(21) Return "INVALID PARAMETER" Case Else SetError(1) Return -1 EndSwitch Next EndIf EndFunc ;==>_ProcessGetOwner ; automates adding contextinfo to the debug msg (screenshot, scriptlinenumber) ; parameters: $ScriptLineNumber needs to be set to @ScriptLineNumber ; better with $tempdir ; requires screencapture.au3, debug.au3 with _debugsetup ; todo: would be nicer if $ScriptLineNumber need not be set explicitly, but default value would work (test), but then the parameter sequence needs to be switched ; i think $ScriptLineNumber = @ScriptLineNumber does not work ; updated ver below not documented above Func myDebugOut($ScriptLineNumber = @ScriptLineNumber, $msg = "Error") ; requires global setting of $debugtype = "debug" Local $debugstring Local $debugfilename Local $tabhandle Local $tabmaxnumber Local $tempdir ; must be global local $pathfilelog $tempdir = @TempDir If $tempdir == "" Then $tempdir = "c:\temp" $debugstring = $ScriptLineNumber & "~" & _Now() & "~" & $msg ; changed : to ~to have delimiters -> tab -> excel -> filter If $debugtype = "debug" Then Local $activewindowtitle = WinGetTitle("") ; todo: test: is using this necessary to give focus back to the window after oking msgbox? MsgBox(0, "debug", $debugstring) WinActivate($activewindowtitle) ElseIf $debugtype = "debugconsole" Then ConsoleWrite($debugstring & Chr(13)) ElseIf $debugtype = "run" Then If $tempdir == "" Then $tempdir = "c:\temp" $debugfilename = FileNameEscape($debugstring, $tempdir) & ".jpg" ; ".bmp" ; can this do jpg also, and jsut by changing the extension? ; works _DebugOut("$debugfilename:" & $debugfilename) _ScreenCapture_Capture($debugfilename); [$sFileName = ""[, $iLeft = 0[, $iTop = 0[, $iRight = -1[, $iBottom = -1[, $fCursor = True]]]]]]) _DebugOut($debugstring) ElseIf $debugtype = "debugconsolescreen" Then ; do both ConsoleWrite($debugstring & Chr(13)) $debugfilename = FileNameEscape($debugstring, $tempdir) & ".jpg" ; ".bmp" ; can this do jpg also, and jsut by changing the extension? ; works _DebugOut("$debugfilename:" & $debugfilename) ; todo: filenameescape does not result in a legit filename, it seems: debug - problem is the \ ; works better now that backslash is escaped ConsoleWrite("$debugfilename:" & $debugfilename & Chr(13)) _ScreenCapture_Capture($debugfilename); [$sFileName = ""[, $iLeft = 0[, $iTop = 0[, $iRight = -1[, $iBottom = -1[, $fCursor = True]]]]]]) ElseIf $debugtype = "releasetextlog" Then ; todo ; todo: consider "release" --> log ; file open append file close If $pathfilelog == "" Then $pathfilelog = @TempDir & "\" & "autoitlogfile.log" $loghandle = FileOpen($pathfilelog, 1); Success: Returns a file "handle" for use with subsequent file functions. If $ret = 0 Or @error Then Exit ; Failure: Returns - 1 If error occurs. $ret = FileWriteLine($loghandle, $debugstring & Chr(13)) If $ret = 0 Or @error Then Exit ; Failure: Returns - 1 If error occurs. $ret = FileClose($loghandle) ElseIf $debugtype = "releasewordpad" Then ; todo Else ; do nothing or error ; can one paste behind the scenes screenshots into wordpad? eaiser for the betatester to send SetError(1) EndIf EndFunc ;==>myDebugOut Func FileNameEscape($filename, $tempdir) ; return a filename which has no special chars - todo: should be unescapable ; StringReplace ( "string", "searchstring" or start, "replacestring" [, count [, casesense]] ) ; added for mydebugout() $filename = StringReplace($filename, ":", "_"); cannot have : in filename $filename = StringReplace($filename, ">", "larger_than"); cannot have > in filename $filename = StringReplace($filename, "<", "smaller_than"); cannot have > in filename ; end added for mydebugout() $filename = StringReplace($filename, " ", "_"); have no spaces in filenames ? $filename = StringReplace($filename, "/", "&"); "Picture/Word_Association" ; todo: & is not save on the commandline - does + work better $filename = StringReplace($filename, "/", "+"); "Picture/Word_Association" $filename = StringReplace($filename, "&", "+"); occurs in some titles $filename = StringReplace($filename, Chr(92), "_") ; tabs - todo: what about other space characters $filename = StringReplace($filename, Chr(9), "_") ; tabs - todo: what about other space characters ; todo: fails again, without warning, file save dialogue remains open: ; Language=1[British_English]_Family=2[Intermediate]_Contenttype=1[Activity]_ActivityOrUnitOrCulture=1[Dialogue]_Exercise=10['Still_hungry?'_Intermediate_1elements]_error171 ; replace questionmark, exclamation mark, quotationmark $filename = StringReplace($filename, "?", "questionmark") $filename = StringReplace($filename, "!", "exclamationmark") $filename = StringReplace($filename, "'", "quotationmark") ; todo: should say single or sth else unique $filename = StringReplace($filename, Chr(34), "doublequotationmark") ; 34 Quotation mark (" in HTML) $filename = StringReplace($filename, "__", "_") ; todo: can stringreplace handle multicharacter? $filename = StringReplace($filename, "__", "_") ; $filename = StringReplace($filename, "__", "_") ; $filename = StringReplace($filename, "__", "_") ; $filename = $tempdir & "\" & $filename ; end filename routine Return $filename EndFunc ;==>FileNameEscape Func FileCopy2LocalTemp($filepath) ; ex: Dim $arrfilepath, $filepathname, $arrfilepathname, $filepathnameext $blnValid = True If Not FileExists($filepath) Then If Not DriveMapAdd("", $filepath) Then ; todo: try also unc paths $blnValid = False EndIf EndIf If $blnValid Then $arrfilepath = _StringSplit($filepath, "\") If @error Then SetError(1) myDebugOut(@ScriptLineNumber, "error stringsplit filepath") EndIf $filepathname = $arrfilepath(UBound($arrfilepath) - 1); get !!filename ; ould be used to give the file a new basename, which would have to be passed as 2nd param $basename ;$arrfilepathname = _StringSplit($filepathname,".") ;if @error then ; myDebugOut(@ScriptLineNumber, "error stringsplit filepathname") ; seterror(1) ;endif ;$filepathnameext = $arrfilepathname(UBound($arrfilepathname) -1); get ext $ret = FileCopy($filepath, @TempDir & "\" & $filepathname) Else SetError(1) EndIf EndFunc ;==>FileCopy2LocalTemp Func taskkillsamples() Local $ret3, $ret4, $filename, $windowtitlePDFCreate myDebugOut(@ScriptLineNumber, "trying to use taskkill to bypass window:" & $windowtitlePDFCreate & " for: " & $filename) $ret3 = RunWait('taskkill /F /fi "imagename eq acro*" /im *') ; return 0 seems good, sometimes? ; single quotes error from the commandline , doublequotes do not, they close the process(including multiple process using wildcard) myDebugOut(@ScriptLineNumber, "runwait returned " & $ret3) ; ERROR: The process "'acro*.exe'" not found. Sleep(5000) ; trying to find a mazimum taskkill that won't shutdown the system ; return 0 seems good, sometimes? requires script-exe name start with auralog ; do close tutortools, /fi "imagename ne tutortools*" $ret4 = RunWait('taskkill /F /fi "username ne SYSTEM" /fi "username ne LOCAL SERVICE" /fi "username ne NETWORK SERVICE" /fi "imagename ne autoit*" /fi "imagename ne notepad*" /fi "imagename ne scite*" /fi "imagename ne ' & $scriptfilewithexe & '*" /im *') ; return 0 seems good, sometimes? myDebugOut(@ScriptLineNumber, "checkercounter > 5, Exterminate all user tasks, returns :" & $ret4) EndFunc ;==>taskkillsamples ; todo: test this with student permissions Func addStudentReadconfigNetworkshares() ; wmencoder cannot handle wme load as uncpath ;SETTINGS $driveletterreadconfig = DriveMapAdd("*", $uncpathsharestudentreadconfig, 0) ; connect as logged in user - works only for students myDebugOut(@ScriptLineNumber, "$driveletterreadconfig is: " & $driveletterreadconfig & ", $uncpathsharestudentreadconfig is " & $uncpathsharestudentreadconfig & ", @error=" & @error) If @error > 0 Then demandloginasstudent() EndIf If (($driveletterreadconfig == "") Or $driveletterreadconfig == 0) Then ; todo:hack $driveletterreadconfig = "O:" EndIf ; if StringLen($driveletterreadconfig) > 0 then ; no error mapping: If there was an error using "*" then a blank string "" will be returned. ; todo: you have added the drives, but for whom? do you no need to impersonate as this user when you filecopy? ; endif ; another interesting idea is this (but how to pass the original username as parameter? could save to and read from ini) ; If Not IsAdmin() Then RunAs($user, $domain, $pass, 0, @ScriptFullPath), Exit EndIf Return $driveletterreadconfig EndFunc ;==>addStudentReadconfigNetworkshares Func deleteStudentShare() ; net use or drivemapdel ; To disconnect from the \\Financial\Public directory, type: net use f: \\financial\public /delete , /y = do not ask the user to type Y or N ; To run DOS commands, try RunWait(@ComSpec & " /c " & "commandName") ; don't forget " " before "/c" ; check first whether the drive / share is connected If Not (FileExists($uncpathsharewriteinstructor) Or FileExists($driveletterkreplacementforstudentwritenetuse)) Then; todo: works with dirs? todo: not uses - now what? safe to connect with sever permissions myDebugOut(@ScriptLineNumber, $driveletterkreplacementforstudentwrite & " nor " & $uncpathsharewriteinstructor & "exist, cannot disconnect") Else ; exists - todo: what exactly? share, driveletter, which permissions $ret = DriveMapDel($driveletterkreplacementforstudentwritenetuse) ; todo: stupid hack, essentially hardcoded k: myDebugOut(@ScriptLineNumber, "disconnect for $driveletterkreplacementforstudentwritenetuse=" & $driveletterkreplacementforstudentwritenetuse & ", $ret=" & $ret & ", @error=" & @error) EndIf EndFunc ;==>deleteStudentShare Func addStudentShare() If Not (FileExists($driveletterkreplacementforstudentwritenetuse)) Then $ret = RunWait(@ComSpec & " /c net use " & $driveletterkreplacementforstudentwritenetuse, "", @SW_HIDE) ; default permissions Sleep(1000) EndIf EndFunc ;==>addStudentShare ; todo: when is removeInstructorNetworkShares called? Func removeInstructorNetworkShares() ; this does not work ; cleanup before next iteration $ret = DriveMapDel($driveletterkreplacementforstudentwrite) If $ret = 0 Then myDebugOut(@ScriptLineNumber, "failed to DriveMapDel for: " & $driveletterkreplacementforstudentwrite & ", @error=" & @error) EndFunc ;==>removeInstructorNetworkShares Func addInstructorNetworksharesNetuse() ; even if we write to K; which the student has a mapping to, it is crucial (and more important than a confusing driveletter) that we map as instructor, or else no write permission of script to folder ; this hardcodes k: ; the command completed successfully: net use k: \\stushare_server\StuShare "friday12" /user:lgu.ac.uk\plagwitt ;SETTINGS If FileExists($driveletterkreplacementforstudentwritenetuse) Then ; if it was not connected and the disconnect fails, xit the program with msg close all files and programms from k: ; net use k: /delete /y $ret = RunWait(@ComSpec & " /c net use " & $driveletterkreplacementforstudentwritenetuse & " /delete /y", "", @SW_HIDE) Sleep(1000) If $ret = 0 Then demanddisconnectkfirst() EndIf EndIf If StringLen($passworddecrypt) > 0 Then ; allows the user in the ini to leave the pwd blank to not have to encrypt the password (which amy be too difficult for the user) $run = RunWait(@ComSpec & " /c net use " & $driveletterkreplacementforstudentwritenetuse & " " & $uncpathsharewriteinstructor & " """ & _StringEncrypt(0, $passwordinstructor, $passworddecrypt) & """ " & " /user:" & @LogonDomain & "\" & $usernameinstructor, "", @SW_HIDE) myDebugOut(@ScriptLineNumber, "connect $ret=" & $ret) Else $run = RunWait(@ComSpec & " /c net use " & $driveletterkreplacementforstudentwritenetuse & " " & $uncpathsharewriteinstructor & " """ & $passwordinstructor & """ " & " / user:" & @LogonDomain & " \" & $usernameinstructor, "", @SW_HIDE) myDebugOut(@ScriptLineNumber, "connect $ret=" & $ret) EndIf EndFunc ;==>addInstructorNetworksharesNetuse Func addInstructorNetworkshares() ; even if we write to K; which the student has a mapping to, it is crucial (and more important than a confusing driveletter) that we map as instructor, or else no write permission of script to folder ;SETTINGS If StringLen($passworddecrypt) > 0 Then ; allows the user in the ini to leave the pwd blank to not have to encrypt the password (which amy be too difficult for the user) $driveletterkreplacementforstudentwrite = DriveMapAdd("*", $uncpathsharewriteinstructor, 0, @LogonDomain & "\" & $usernameinstructor, _StringEncrypt(0, $passwordinstructor, $passworddecrypt)) Else $driveletterkreplacementforstudentwrite = DriveMapAdd("*", $uncpathsharewriteinstructor, 0, @LogonDomain & "\" & $usernameinstructor, $passwordinstructor) EndIf myDebugOut(@ScriptLineNumber, "$driveletterkreplacementforstudentwrite is: " & $driveletterkreplacementforstudentwrite & ", $uncpathsharewriteinstructor is " & $uncpathsharewriteinstructor & ", $usernameinstructor, $passwordinstructor are " & $usernameinstructor & $passwordinstructor & ", @error=" & @error) If (($driveletterkreplacementforstudentwrite == "") Or $driveletterkreplacementforstudentwrite == 0) Then ; todo:hack $driveletterkreplacementforstudentwrite = "K:" EndIf ; if StringLen($driveletterkreplacementforstudentwrite) > 0 then ; no error mapping: If there was an error using "*" then a blank string "" will be returned. ; todo: you have added the drives, but for whom? do you no need to impersonate as this user when you filecopy? ; endif ; another interesting idea is this (but how to pass the original username as parameter? could save to and read from ini) ; If Not IsAdmin() Then RunAs($user, $domain, $pass, 0, @ScriptFullPath), Exit EndIf Return $driveletterkreplacementforstudentwrite EndFunc ;==>addInstructorNetworkshares Func demanddisconnectkfirst() myDebugOut(@ScriptLineNumber, "disconnect $ret=" & $ret) $ret = MsgBox(1, "Error!", "Close all files and programms running from K: first, then restart trprecord. Will exit now...") myCleanup() EndFunc ;==>demanddisconnectkfirst Func demandloginasstudent() myDebugOut(@ScriptLineNumber, "disconnect $ret=" & $ret) $ret = MsgBox(1, "Error!", "You are logged in as: " & @UserName & ". Make sure you are logged in as student with access to \\lgu.ac.uk\lgu$\multimedia student\mmedia, then restart trprecord. Will exit now...") myCleanup() EndFunc ;==>demandloginasstudent Func trpCleanup() removeInstructorNetworkShares() addStudentShare() Exit EndFunc ;==>trpCleanup Func MyErrFunc() $myMessage = "err.description_" & $oMyError.description & "." & "err.windescription_" & $oMyError.windescription & "." & "err.number_" & Hex($oMyError.number,8) & "." & "err.lastdllerror_" & $oMyError.lastdllerror & "." & "err.scriptline_" & $oMyError.scriptline & "." & "err.source_" & $oMyError.source & "." & "err.helpfile_" & $oMyError.helpfile & "." & "err.helpcontext_" & $oMyError.helpcontext myDebugOut(@ScriptLineNumber, "Com Error: " & $myMessage) MsgBox(0, "trpRecord WME SDK COM Error", "Alt+Print Screen, then paste this into an email to ictservicedesk@londonmet.ac.uk! I will exit after you press OK." & @CRLF & $myMessage) Local $err = $oMyError.number If $err = 0 Then $err = -1 Exit ; added trp $g_eventerror = $err ; to check for after this function returns - spar ich mir EndFunc ;==>MyErrFunc ; done: why does on exit a cmd window flash? is there a comspec without sw_hide somewhere? b/o forgottem "", @SW_HIDE wiht runwait(@comspec ; todo: drivemapadd * does not give k: even if i drivemapdel k: - nor surprise, you allow any drivleietter iwth * , it would be bette to reconnect as k:, but this would require additional checking