logo

Live Production Software Forums


Welcome Guest! To enable all features please Login or Register.

Notification

Icon
Error

Options
Go to last post Go to first unread
matkeane  
#1 Posted : Monday, February 15, 2021 7:58:34 PM(UTC)
matkeane

Rank: Advanced Member

Groups: Registered
Joined: 10/6/2020(UTC)
Posts: 98
France

Was thanked: 21 time(s) in 21 post(s)
This is my first attempt at scripting in vMix but, with the help of examples from the 'Scripting for Dummies' thread and this other post (https://forums.vmix.com/posts/t23962-Movie-Title--name), I've managed to build a functioning script which loops through a CSV DataSource and exports a PNG image of my lower-third with each row of data.

So far so good except that, in all the examples I've found so far, loops use a hard-coded limit. I don't see anything in the API results - is there a way for a script to retrieve the number of entries in a DataSource ?

Looking at the VBscript docs (https://docs.microsoft.com/en-us/dotnet/visual-basic/programming-guide/language-features/control-flow/loop-structures), it seems like it should be possible to use an API command in a While loop. But, since API commands return a status code (e.g. 200) rather than a boolean, I can't find a way to get that working.

There are no doubt some other optimisations - avoiding defining variables inside a loop ? Padding the file numbers to 2 or 3 digits ? - so I'm open to suggestions for improvements.

Thanks

Code:
' Export Titles as images.

Dim title_input_no as integer = 29
Dim datasource_row_count as integer = 33

Dim snapshot_file_basename as string = "synthe_"
Dim snapshot_file_extension as string = ".png"
Dim snapshot_filename as string

dim xml_data as new system.xml.xmldocument
dim title_text as string
Dim title_text_word_last as String 

Dim index as integer = 0

' Send Title to Preview.
'API.Function("PreviewInput",Input:=title_input_no)
'API.Function("DataSourceSelectRow",Value:="Excel/CSV,Sheet1,0")

' Loop through Data Source rows.
While index <= datasource_row_count
  API.Function("DataSourceSelectRow",Value:="Excel/CSV,Sheet1," & index)
  sleep(500)

  dim xml as string = API.XML()
  xml_data.loadxml(xml)
  title_text = (xml_data.SelectSingleNode("//inputs//input[" & title_input_no & "]//text[1]").InnerText)
  Dim words as String() = title_text.Split()
  title_text_word_last = words(words.getUpperBound(0))
  if title_text_word_last = "" then
    title_text_word_last = "title"
  End If

  snapshot_filename = snapshot_file_basename & index & "_" & title_text_word_last & snapshot_file_extension
  API.Function("SnapshotInput",Input:=title_input_no,Value:=snapshot_filename)  
  sleep(1000)
  index += 1
End While
doggy  
#2 Posted : Monday, February 15, 2021 9:24:27 PM(UTC)
doggy

Rank: Advanced Member

Groups: Registered
Joined: 12/27/2012(UTC)
Posts: 5,057
Belgium
Location: Belgium

Thanks: 283 times
Was thanked: 916 time(s) in 755 post(s)
AFAIK there is no vMix integrated option to retrieve a data source row count

but you can loop through it and count them by comparing data. If data is same as previous you reached end of list

In the case of a a CSV/text file one can do a line count of the file itself directly (google "vb.net count rows in csv file")

Similar can be done with a xml file
matkeane  
#3 Posted : Monday, February 15, 2021 10:44:18 PM(UTC)
matkeane

Rank: Advanced Member

Groups: Registered
Joined: 10/6/2020(UTC)
Posts: 98
France

Was thanked: 21 time(s) in 21 post(s)
Hi Doggy,

Thanks for those suggestions. I'm trying to keep things as simple as possible so that the script could be used by other people, and I think querying the CSV file directly might complicate things. I was hoping there would be the equivalent of array.length or list.size() I could grab.

I did wonder about comparing rows to detect the end (or comparing to the first row, in case looping is set to On). I have one client who likes to add all the names to the CSV sequentially so, if a speaker appears in more than one session, their name is repeated - so it's not impossible that there would be edge-cases where comparing rows would bail out before reaching the end of the CSV file, but I guess it would work 99% of the time.
doggy  
#4 Posted : Monday, February 15, 2021 11:21:12 PM(UTC)
doggy

Rank: Advanced Member

Groups: Registered
Joined: 12/27/2012(UTC)
Posts: 5,057
Belgium
Location: Belgium

Thanks: 283 times
Was thanked: 916 time(s) in 755 post(s)
Originally Posted by: matkeane Go to Quoted Post
I'm trying to keep things as simple as possible so that the script could be used by other people, and I think querying the CSV file directly might complicate things. I was hoping there would be the equivalent of array.length or list.size() I could grab.


so one line would complicate things ? <g>

Code:
Dim RowCount = File.ReadAllLines("D:\File.csv").Length
matkeane  
#5 Posted : Tuesday, February 16, 2021 12:28:04 AM(UTC)
matkeane

Rank: Advanced Member

Groups: Registered
Joined: 10/6/2020(UTC)
Posts: 98
France

Was thanked: 21 time(s) in 21 post(s)
Haha, no, that will simplify my script... but will involve explaining to other users which line in the script to modify and how to find the file path of the CSV file referenced by the lower-third!

Having said that, I think I saw some examples of opening a file dialog from a script, so that users can pick the file themselves... but that's a bit advanced for my needs at the moment.

Thank you for that code - I will add it to my script and it's probably less error-prone than comparing text rows.

... and, now I have allow for header rows after getting the row count from the file. And fix the 'while' loop using '<' instead of '<='. Updated version below :

Code:
' Export Titles as images.

Dim title_input_no as integer = 29
Dim datasource_header_rows as integer = 1
Dim datasource_file_path as string = "D:\absolute\path\to\my\datasource.csv"

Dim snapshot_file_basename as string = "synthe_"
Dim snapshot_file_extension as string = ".png"
Dim snapshot_filename as string

dim xml_data as new system.xml.xmldocument
dim title_text as string
Dim title_text_word_last as String 

Dim index as integer = 0
Dim datasource_row_count = File.ReadAllLines(datasource_file_path).Length
datasource_row_count -= datasource_header_rows
console.writeline("Found "& datasource_row_count &" rows in file: " & datasource_file_path)

' Send Title to Preview.
'API.Function("PreviewInput",Input:=title_input_no)
'API.Function("DataSourceSelectRow",Value:="Excel/CSV,Sheet1,0")

' Loop through Data Source rows.
While index < datasource_row_count
  API.Function("DataSourceSelectRow",Value:="Excel/CSV,Sheet1," & index)
  sleep(500)

  dim xml as string = API.XML()
  xml_data.loadxml(xml)
  title_text = (xml_data.SelectSingleNode("//inputs//input[" & title_input_no & "]//text[1]").InnerText)
  Dim words as String() = title_text.Split()
  title_text_word_last = words(words.getUpperBound(0))
  if title_text_word_last = "" then
    title_text_word_last = "title"
  End If

  snapshot_filename = snapshot_file_basename & index & "_" & title_text_word_last & snapshot_file_extension
  API.Function("SnapshotInput",Input:=title_input_no,Value:=snapshot_filename)  
  sleep(1000)
  index += 1
End While
Users browsing this topic
Forum Jump  
You cannot post new topics in this forum.
You cannot reply to topics in this forum.
You cannot delete your posts in this forum.
You cannot edit your posts in this forum.
You cannot create polls in this forum.
You cannot vote in polls in this forum.