This is part 3 in the series and it is a work in progress – its barely started in fact…
I have published it now for the sake of quickly sharing some example C# code and will update it over the next few days (maybe weeks).
For now, you can find below the required C# code that will create a simple ProPresenter 7 document with two slides like this:
TODO:
- Demo how to use protoc to generate C# code from the .proto files
- Demo making a new C# project, adding reference to Google.Protobuf and then adding all the generated C# code files
- Demo writing simple code to create a document
- DO a bit of a dive into structure of document and the RTF format used for text elements.
- Point out that you can generate other languages (eg Python, Java)
Here is a dump of some manually written code that creates a new simple ProPresenter 7 document. The underlying “plumbing” code that enables this to work is auto-generated by the protoc compiler.
// You need to add these namespaces...
using Rv.Data;
using Google.Protobuf;
// Code to read an existing presentation and create a new one from scratch
Rv.Data.Presentation newPresentation, existingPresentation;
using (var input = File.OpenRead(@"C:\Users\media\Documents\ProPresenter\Libraries\Default\Alive.pro")) // Path to existing presentation
{
existingPresentation = Rv.Data.Presentation.Parser.ParseFrom(input);
} // Put in break point here to inspect existing presetation and learn the structure
// ***** Create new presentation *****
newPresentation = new Rv.Data.Presentation
{
Uuid = new UUID { String = Guid.NewGuid().ToString() },
Name = "HelloWorld",
ApplicationInfo = new ApplicationInfo
{
Application = ApplicationInfo.Types.Application.Propresenter,
Platform = ApplicationInfo.Types.Platform.Windows
}
};
// Create a new cue (with a single action of type presentation_slide)
Cue newCue = new Cue
{
Uuid = new UUID { String = Guid.NewGuid().ToString() },
IsEnabled = true,
Actions = { new Rv.Data.Action
{
Uuid = new UUID { String = Guid.NewGuid().ToString() },
IsEnabled = true,
Label = new Rv.Data.Action.Types.Label
{
Text = "Hello Slide1",
Color = new Rv.Data.Color
{
Red = 0.8f,
Green = 0.1f,
Blue = 0.4f,
Alpha = 1
}
},
Slide = new Rv.Data.Action.Types.SlideType
{
Presentation = new PresentationSlide
{
BaseSlide = new Slide
{
Uuid = new UUID
{
String = Guid.NewGuid().ToString()
},
BackgroundColor = new Rv.Data.Color
{
Red = 0.05f,
Blue =0.2f,
Green = 0.6f,
Alpha = 0.4f
},
DrawsBackgroundColor = true,
Size = new Graphics.Types.Size
{
Width = 1920,
Height = 1080
},
Elements = {
new Slide.Types.Element {
Element_ = new Graphics.Types.Element
{
Uuid = new UUID
{
String = Guid.NewGuid().ToString()
},
Fill = new Graphics.Types.Fill
{
Color = new Rv.Data.Color{Alpha =0} // Transparent fill for element
},
Name = "Hello Element",
Bounds = new Graphics.Types.Rect {
Origin = new Graphics.Types.Point {X =0, Y=0},
Size = new Graphics.Types.Size {Width = 1920, Height = 1080}
},
Opacity = 1,
Text = new Graphics.Types.Text
{
VerticalAlignment = Graphics.Types.Text.Types.VerticalAlignment.Middle,
RtfData = ByteString.CopyFrom("{\\rtf0\\ansi\\ansicpg1252" +
"{\\fonttbl\\f0\\fnil Arial;}" +
"{\\colortbl\\red255\\green255\\blue255;}" +
"{\\*\\expandedcolortbl\\csgenericrgb\\c100000\\c100000\\c100000\\c100000;\\csgenericrgb\\c100000\\c100000\\c100000\\c100000;}" +
"{\\*\\listtable}{\\*\\listoverridetable}" +
"\\uc1\\paperw12240\\margl0\\margr0\\margt0\\margb0" +
"\\pard\\qc\\slmult0\\slleading0\\f0\\b0\\ul0\\strike0\\fs400\\cf0\\strokewidth0\\strokec1\\nosupersub Hello World"+
"\\par\\pard\\qc\\slmult0\\slleading0\\f0\\i\\b0\\ul0\\strike0\\fs200\\cf0\\strokewidth0\\strokec1\\nosupersub (Slide with green background)}",
Encoding.ASCII),
},
Path = new Graphics.Types.Path
{
Shape = new Graphics.Types.Path.Types.Shape
{
Type = Graphics.Types.Path.Types.Shape.Types.Type.Rectangle
}
},
}
}
}
}
}
},
Type = Rv.Data.Action.Types.ActionType.PresentationSlide
}
}
};
// Add new cue (slide)
newPresentation.Cues.Add(newCue);
Cue newCue2 = new Cue
{
Uuid = new UUID
{
String = Guid.NewGuid().ToString()
},
IsEnabled = true,
Actions = { new Rv.Data.Action
{
Uuid = new UUID
{
String = Guid.NewGuid().ToString()
},
Label = new Rv.Data.Action.Types.Label
{
Text = "Hello Slide2",
Color = new Rv.Data.Color
{
Red = 0.46f,
Green = 0.0f,
Blue = 0.8f,
Alpha = 1}
},
Slide = new Rv.Data.Action.Types.SlideType
{
Presentation = new PresentationSlide
{
BaseSlide = new Slide
{
Uuid = new UUID
{
String = Guid.NewGuid().ToString()
},
BackgroundColor = new Rv.Data.Color
{
Red = 1,
Green = 1,
Blue = 1,
Alpha = 1
},
Size = new Graphics.Types.Size
{
Width = 1920,
Height = 1080
}
}
}
},
Type = Rv.Data.Action.Types.ActionType.PresentationSlide,
}
}
};
// Add new cue (slide)
newPresentation.Cues.Add(newCue2);
// Add a new group with above two slides
newPresentation.CueGroups.Add(new Presentation.Types.CueGroup
{
CueIdentifiers = { newCue.Uuid, newCue2.Uuid },
Group = new Group
{
Uuid = new UUID
{
String = Guid.NewGuid().ToString()
},
Name = "Hello Group",
Color = new Rv.Data.Color
{
Red = 0.0f,
Green = 0.467f,
Blue = 0.8f,
Alpha = 1
}
},
}
);
// Create a single arrangement with above group
newPresentation.Arrangements.Add(new Presentation.Types.Arrangement
{
Uuid = new UUID
{
String = Guid.NewGuid().ToString()
},
Name = "Hello Arrangement",
// Just add the one group to this arrangement
GroupIdentifiers = { newPresentation.CueGroups[0].Group.Uuid }
});
// Set selecte arrangement to the one and only arrangement
newPresentation.SelectedArrangement = newPresentation.Arrangements[0].Uuid;
// Save to file!
using (var fileStream = File.Create(@"C:\Users\media\Documents\ProPresenter\Libraries\Default\HelloWorld.pro"))
{
newPresentation.WriteTo(fileStream); // This is an override method provided in Google.Protobuf namespace (make sure to add a using Google.Protobuf;)
}
</div>
</div>
</div>
</div>