Home > e-languages, multimedia-recording, service-is-programming, sourcecode > How to build a digital recorder with GUI for free with Windows-Media-Encoder

How to build a digital recorder with GUI for free with Windows-Media-Encoder

  1. 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.
  2. Uses AutoIT and Windows-COM programming, as exemplified in Windows-media-encoder-SDK, against Windows-Media-Encoder.
  3. make sure that you have
    1. have all AutoIt packages referenced with #includes below;
    2. have the windows-media-encoder installed – the windows-media-encoder-SDK should not be needed , except for programming examples;
    3. make sure you adapt “PUTYOUROWN” to your own environment
    4. provide your own (equipment-specific) WME files for the Windows-Media-Encoder configuration.
  4. (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 (&quot; 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
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: