Represents the properties of subtitles.
This class acts as a container which allows you to get and set a variety of properties. Some of these properties are used in syncronization and timing calculations.
Inheritance: ICloneable
Beispiel #1
0
        public object Clone()
        {
            SubtitleProperties propertiesClone = this.properties.Clone() as SubtitleProperties;
            SubtitleCollection collectionClone = this.collection.Clone(propertiesClone);

            return(new Subtitles(collectionClone, propertiesClone));
        }
Beispiel #2
0
        /* Internal methods */

        internal void SetPropertiesForAll(SubtitleProperties properties)
        {
            foreach (Subtitle subtitle in subtitles)
            {
                subtitle.Properties = properties;
            }
        }
	internal string Build (SubtitleCollection collection, SubtitleProperties subtitleProperties, FileProperties fileProperties) {
		this.subtitleProperties = subtitleProperties;
		StringBuilder output = new StringBuilder();
		if (format.HasHeaders)
			output.Append(format.HeadersToString(subtitleProperties, fileProperties));

		if (format.HasBodyBegin)
			output.Append(format.BodyBeginOut);

		string subtitleExpression = GetSubtitleExpression(format, subtitleProperties, fileProperties);
		Regex fieldExpression = new Regex(@"<<(?<Field>\w+)(,(?<Width>\d+))?>>");
		MatchEvaluator matchEvaluator = new MatchEvaluator(this.FieldEvaluator);

		foreach (Subtitle currentSubtitle in collection) {
			subtitle = currentSubtitle;
			string outputSubtitle = fieldExpression.Replace(subtitleExpression, matchEvaluator);
			output.Append(outputSubtitle);
			output.Append("\n");
			subtitleNumber++;
			previousSubtitle = subtitle;
		}

		if (format.HasBodyEnd)
			output.Append(format.BodyEndOut);

		subtitle = null;
		previousSubtitle = null;
		subtitleNumber = 1;

		ConvertNewlines(output, fileProperties);
		return output.ToString();
	}
Beispiel #4
0
        /// <summary>Creates a subtitle based on the subtitle at the specified index and adds it to the
        /// collection, inserting it right before that index.</summary>
        /// <remarks>The newly created subtitle's times will be based on the specified subtitle. Its duration
        /// will be <see cref="SubtitleConstants.MaxSingleLineSubtitleDuration" />. Both the start and end times
        /// times will be wrapped to zero if they are negative.</remarks>
        /// <param name="index">The zero-based index before which the subtitle should be inserted.</param>
        /// <param name="subtitleProperties">The SubtitleProperties of the subtitles.</param>
        /// <param name="timeBetweenSubtitles">The gap to keep before the existing subtitle, in milliseconds.</param>
        /// <returns>True if the subtitle could be added, false otherwise.</returns>
        public bool AddNewBefore(int index, SubtitleProperties subtitleProperties, int timeBetweenSubtitles)
        {
            Subtitle existing = Get(index);

            if (existing == null)
            {
                return(false);
            }

            TimeSpan subtitleEnd = existing.Times.Start - TimeSpan.FromMilliseconds(timeBetweenSubtitles);

            if (subtitleEnd < TimeSpan.Zero)
            {
                subtitleEnd = TimeSpan.FromSeconds(0);
            }

            TimeSpan subtitleStart = subtitleEnd - TimeSpan.FromSeconds(SubtitleConstants.AverageSubtitleDuration);

            if (subtitleStart < TimeSpan.Zero)
            {
                subtitleStart = TimeSpan.FromSeconds(0);
            }

            Subtitle subtitle = new Subtitle(subtitleProperties, subtitleStart, subtitleEnd);

            Add(subtitle, index);
            return(true);
        }
	/* Public methods */

	public SubtitleCollection Clone (SubtitleProperties propertiesClone) {
		SubtitleCollection collectionClone = new SubtitleCollection();
		foreach (Subtitle subtitle in this.subtitles) {
			Subtitle subtitleClone = subtitle.Clone(propertiesClone);
			collectionClone.Add(subtitleClone);
		}
		return collectionClone;
	}
Beispiel #6
0
	/// <summary>Initializes a new instance of the <see cref="Subtitle" /> class, given the
	/// global subtitles' properties and the subtitle's text and style.</summary>
	/// <param name="properties">The subtitles' properties.</param>
	/// <param name="text">The subtitle's text.</param>
	/// <param name="style">The subtitle's style.</param>
	public Subtitle (SubtitleProperties properties, SubtitleText text, Style style) {
		this.properties = properties;
		this.text = text;
		this.style = style;

		times = new Times(this);
		frames = new Frames(this);
	}
	internal override string HeadersToString(SubtitleProperties subtitleProperties, FileProperties fileProperties) {
		Headers headers = subtitleProperties.Headers;
		return "# <HEAD>\n" +
			"# FRAME RATE=" + headers.FrameRate + "\n" +
			"# CREATOR=" + headers.Author + "\n" +
			"# VIDEO SOURCE=" + headers.VideoSource + "\n" +
			"# DATE=" + headers.Date + "\n" +
			"# </HEAD>\n#\n";
	}
Beispiel #8
0
        /* Private methods */

        private void SetFieldsForDeepClone(SubtitleProperties properties, Times times, Frames frames, SubtitleText text, SubtitleText translation, Style style)
        {
            this.properties  = properties;
            this.times       = times;
            this.frames      = frames;
            this.text        = text;
            this.translation = translation;
            this.style       = style;
        }
Beispiel #9
0
        /// <summary>Initializes a new instance of the <see cref="Subtitle" /> class, given the
        /// global subtitles' properties and the subtitle's text and style.</summary>
        /// <param name="properties">The subtitles' properties.</param>
        /// <param name="text">The subtitle's text.</param>
        /// <param name="style">The subtitle's style.</param>
        public Subtitle(SubtitleProperties properties, SubtitleText text, Style style)
        {
            this.properties = properties;
            this.text       = text;
            this.style      = style;

            times  = new Times(this);
            frames = new Frames(this);
        }
	internal override string HeadersToString (SubtitleProperties subtitleProperties, FileProperties fileProperties) {
		Headers headers = subtitleProperties.Headers;
		return "[ti: " + headers.Title + "]\n" +
			"[au:" + headers.MovieAuthor + "]\n" +
			"[ar:" + headers.Artist + "]\n" +
			"[al:" + headers.Album + "]\n" +
			"[by:" + headers.Author + "]\n" +
			"[ve:" + headers.Version + "]\n" +
			"[re:" + headers.Program + "]\n";
	}
	internal override string HeadersToString (SubtitleProperties subtitleProperties, FileProperties fileProperties) {
		Headers headers = subtitleProperties.Headers;
		return "[TITLE]\n" + headers.Title + "\n" +
			"[AUTHOR]\n" + headers.Author + "\n" +
			"[SOURCE]\n" + headers.VideoSource + "\n" +
			"[PRG]\n" + headers.Program + "\n" +
			"[FILEPATH]\n" + headers.SubtitlesSource + "\n" +
			"[DELAY]\n" + headers.Delay + "\n" +
			"[CD TRACK]\n" + headers.CDTrack + "\n";
	}
	internal override string HeadersToString (SubtitleProperties subtitleProperties, FileProperties fileProperties) {
		Headers headers = subtitleProperties.Headers;
		string format = (fileProperties.TimingMode == TimingMode.Times ? "TIME" : subtitleProperties.CurrentFrameRate.ToString());
		return "TITLE=" + headers.Title + "\n" +
			"FILE=" + headers.FileProperties + "\n" +
			"AUTHOR=" + headers.Author + "\n" +
			"TYPE=" + headers.MediaType + "\n" +
			"FORMAT=" + format + "\n" +
			"NOTE=" + headers.Comment + "\n\n";
	}
Beispiel #13
0
        /* Public methods */

        public SubtitleCollection Clone(SubtitleProperties propertiesClone)
        {
            SubtitleCollection collectionClone = new SubtitleCollection();

            foreach (Subtitle subtitle in this.subtitles)
            {
                Subtitle subtitleClone = subtitle.Clone(propertiesClone);
                collectionClone.Add(subtitleClone);
            }
            return(collectionClone);
        }
Beispiel #14
0
        /// <summary>Creates a subtitle and adds it to the collection, inserting it at the specified index
        /// and with the specified start time.</summary>
        /// <remarks>The newly created subtitle's duration will be
        /// <see cref="SubtitleConstants.MaxSingleLineSubtitleDuration" />.</remarks>
        /// <param name="index">The zero-based index at which the subtitle should be inserted.</param>
        /// <param name="subtitleProperties">The SubtitleProperties of the subtitles.</param>
        /// <param name="start">The time at which the new subtitle will start</para>
        /// <returns>True if the subtitle could be added, false otherwise.</returns>
        public bool AddNewAt(int index, SubtitleProperties subtitleProperties, TimeSpan start)
        {
            if ((index < 0) || (index > Count))
            {
                return(false);
            }

            TimeSpan subtitleStart = start;
            TimeSpan subtitleEnd   = subtitleStart + TimeSpan.FromSeconds(SubtitleConstants.AverageSubtitleDuration);
            Subtitle subtitle      = new Subtitle(subtitleProperties, subtitleStart, subtitleEnd);

            Add(subtitle, index);
            return(true);
        }
Beispiel #15
0
        /* Public methods */

        /// <summary></summary>
        /// <remarks>SubtitleProperties is not cloned and should be set afterwards.</remarks>
        public Subtitle Clone(SubtitleProperties propertiesClone)
        {
            Subtitle subtitleClone = new Subtitle();

            Times        timesClone       = this.times.Clone(subtitleClone);
            Frames       framesClone      = this.frames.Clone(subtitleClone);
            SubtitleText textClone        = this.text.Clone() as SubtitleText;
            SubtitleText translationClone = (this.translation != null ? this.translation.Clone() as SubtitleText : null);
            Style        styleClone       = this.style.Clone() as Style;

            subtitleClone.SetFieldsForDeepClone(propertiesClone, timesClone, framesClone, textClone, translationClone, styleClone);

            return(subtitleClone);
        }
Beispiel #16
0
        /// <summary>Creates a subtitle based on the subtitle at the specified index and adds it to the
        /// collection, inserting it right after that index.</summary>
        /// <remarks>The newly created subtitle's times will be based on the specified subtitle.
        /// Its duration will be <see cref="SubtitleConstants.MaxSingleLineSubtitleDuration" />.</remarks>
        /// <param name="index">The zero-based index after which the subtitle should be inserted.</param>
        /// <param name="subtitleProperties">The SubtitleProperties of the subtitles.</param>
        /// <param name="timeBetweenSubtitles">The gap to keep after the existing subtitle, in milliseconds.</param>
        /// <returns>True if the subtitle could be added, false otherwise.</returns>
        public bool AddNewAfter(int index, SubtitleProperties subtitleProperties, int timeBetweenSubtitles)
        {
            Subtitle existing = Get(index);

            if (existing == null)
            {
                return(false);
            }

            TimeSpan subtitleStart = existing.Times.End + TimeSpan.FromMilliseconds(timeBetweenSubtitles);
            TimeSpan subtitleEnd   = subtitleStart + TimeSpan.FromSeconds(SubtitleConstants.AverageSubtitleDuration);
            Subtitle subtitle      = new Subtitle(subtitleProperties, subtitleStart, subtitleEnd);

            Add(subtitle, index + 1);
            return(true);
        }
	internal override string HeadersToString (SubtitleProperties subtitleProperties, FileProperties fileProperties) {
		Headers headers = subtitleProperties.Headers;
		return "[INFORMATION]\n" +
			"[TITLE]" + headers.Title + "\n" +
			"[AUTHOR]" + headers.Author + "\n" +
			"[SOURCE]" + headers.VideoSource + "\n" +
			"[PRG]" + headers.Program + "\n" +
			"[FILEPATH]" + headers.SubtitlesSource + "\n" +
			"[DELAY]" + headers.Delay + "\n" +
			"[CD TRACK]" + headers.CDTrack + "\n" +
			"[COMMENT]" + headers.Comment + "\n" +
			"[END INFORMATION]\n" +
			"[SUBTITLE]\n" +
			"[COLF]" + headers.FontColor + ",[STYLE]" + headers.FontStyle +
				",[SIZE]" + headers.FontSize + ",[FONT]" + headers.FontName + "\n";
	}
	internal override string HeadersToString (SubtitleProperties subtitleProperties, FileProperties fileProperties) {
		Headers headers = subtitleProperties.Headers;
		return "[Script Info]\n" +
			Header("Title:", headers.Title, "<untitled>") +
			Header("Original Script:", headers.OriginalScript, "<unknown>") +
			"Script Type: " + ScriptType + "\n" +
			Header("Original Translation:", headers.OriginalTranslation) +
			Header("Original Editing:", headers.OriginalEditing) +
			Header("Original Timing:", headers.OriginalTiming) +
			Header("Original Script Checking:", headers.OriginalScriptChecking) +
			Header("Script Updated By:", headers.ScriptUpdatedBy) +
			Header("Collisions:", headers.Collisions) +
			Header("PlayResX:", headers.PlayResX) +
			Header("PlayResY:", headers.PlayResY) +
			Header("PlayDepth:", headers.PlayDepth) +
			Header("Timer:", headers.Timer) + "\n" +
			StyleSection;
Beispiel #19
0
 /// <summary>Initializes a new instance of the <see cref="Subtitle" /> class, given the
 /// global subtitles' properties.</summary>
 /// <param name="properties">The subtitles' properties.</param>
 public Subtitle(SubtitleProperties properties)
     : this(properties, new SubtitleText(), new Style())
 {
 }
Beispiel #20
0
 /// <summary>Initializes a new instance of the <see cref="Subtitle" /> class, given the
 /// global subtitles' properties and its start and end frames.</summary>
 /// <param name="properties">The subtitles' properties.</param>
 /// <param name="startFrame">The subtitle's start frame.</param>
 /// <param name="endFrame">The subtitle's end frame.</param>
 public Subtitle(SubtitleProperties properties, int startFrame, int endFrame)
     : this(properties, new SubtitleText(), new Style())
 {
     frames.Start = startFrame;
     frames.End   = endFrame;
 }
Beispiel #21
0
 /// <summary>Initializes a new instance of the <see cref="Subtitle" /> class, given the
 /// global subtitles' properties and its start and end times.</summary>
 /// <param name="properties">The subtitles' properties.</param>
 /// <param name="startTime">The subtitle's start time.</param>
 /// <param name="endTime">The subtitle's end time.</param>
 public Subtitle(SubtitleProperties properties, TimeSpan startTime, TimeSpan endTime)
     : this(properties, new SubtitleText(), new Style())
 {
     times.Start = startTime;
     times.End   = endTime;
 }
Beispiel #22
0
	/// <summary>Initializes a new instance of the <see cref="Subtitle" /> class, given the
	/// global subtitles' properties.</summary>
	/// <param name="properties">The subtitles' properties.</param>
	public Subtitle (SubtitleProperties properties)
			: this(properties, new SubtitleText(), new Style()){
	}
	/* Internal methods */

	internal void SetPropertiesForAll (SubtitleProperties properties) {
		foreach (Subtitle subtitle in subtitles)
			subtitle.Properties = properties;
	}
	/// <summary>Creates a subtitle based on the subtitle at the specified index and adds it to the
	/// collection, inserting it right after that index.</summary>
	/// <remarks>The newly created subtitle's times will be based on the specified subtitle.
	/// Its duration will be <see cref="SubtitleConstants.MaxSingleLineSubtitleDuration" />.</remarks>
	/// <param name="index">The zero-based index after which the subtitle should be inserted.</param>
	/// <param name="subtitleProperties">The SubtitleProperties of the subtitles.</param>
	/// <param name="timeBetweenSubtitles">The gap to keep after the existing subtitle, in milliseconds.</param>
	/// <returns>True if the subtitle could be added, false otherwise.</returns>
	public bool AddNewAfter (int index, SubtitleProperties subtitleProperties, int timeBetweenSubtitles) {
		Subtitle existing = Get(index);
		if (existing == null)
			return false;

		TimeSpan subtitleStart = existing.Times.End + TimeSpan.FromMilliseconds(timeBetweenSubtitles);
		TimeSpan subtitleEnd = subtitleStart + TimeSpan.FromSeconds(SubtitleConstants.AverageSubtitleDuration);
		Subtitle subtitle = new Subtitle(subtitleProperties, subtitleStart, subtitleEnd);
		Add(subtitle, index + 1);
		return true;
	}
Beispiel #25
0
 internal virtual string HeadersToString (SubtitleProperties subtitleProperties, FileProperties fileProperties) {
     return String.Empty;
 }
	/// <summary>Creates a subtitle based on the subtitle at the specified index and adds it to the
	/// collection, inserting it right before that index.</summary>
	/// <remarks>The newly created subtitle's times will be based on the specified subtitle. Its end
	/// time will be the start time of the existing subtitle minus <see cref="SubtitleConstants.MinTimeBetweenSubtitles" />.
	/// Its duration will be <see cref="SubtitleConstants.MaxSingleLineSubtitleDuration" />. Both times will be wrapped to
	/// zero if they are less than zero.</remarks>
	/// <param name="index">The zero-based index before which the subtitle should be inserted.</param>
	/// <param name="subtitleProperties">The SubtitleProperties of the subtitles.</param>
	/// <returns>True if the subtitle could be added, false otherwise.</returns>
	public bool AddNewBefore (int index, SubtitleProperties subtitleProperties) {
		return AddNewBefore(index, subtitleProperties, (int)(SubtitleConstants.MinTimeBetweenSubtitles*1000));
	}
Beispiel #27
0
	/* Private methods */

	private void SetFieldsForDeepClone (SubtitleProperties properties, Times times, Frames frames, SubtitleText text, SubtitleText translation, Style style) {
		this.properties = properties;
		this.times = times;
		this.frames = frames;
		this.text = text;
		this.translation = translation;
		this.style = style;
	}
Beispiel #28
0
	/// <summary>Initializes a new instance of the <see cref="Subtitle" /> class, given the
	/// global subtitles' properties and its start and end times.</summary>
	/// <param name="properties">The subtitles' properties.</param>
	/// <param name="startTime">The subtitle's start time.</param>
	/// <param name="endTime">The subtitle's end time.</param>
	public Subtitle (SubtitleProperties properties, TimeSpan startTime, TimeSpan endTime)
			: this(properties, new SubtitleText(), new Style()) {

		times.Start = startTime;
		times.End = endTime;
	}
	/// <summary>Creates a subtitle based on the subtitle at the specified index and adds it to the
	/// collection, inserting it right before that index.</summary>
	/// <remarks>The newly created subtitle's times will be based on the specified subtitle. Its duration
	/// will be <see cref="SubtitleConstants.MaxSingleLineSubtitleDuration" />. Both the start and end times
	/// times will be wrapped to zero if they are negative.</remarks>
	/// <param name="index">The zero-based index before which the subtitle should be inserted.</param>
	/// <param name="subtitleProperties">The SubtitleProperties of the subtitles.</param>
	/// <param name="timeBetweenSubtitles">The gap to keep before the existing subtitle, in milliseconds.</param>
	/// <returns>True if the subtitle could be added, false otherwise.</returns>
	public bool AddNewBefore (int index, SubtitleProperties subtitleProperties, int timeBetweenSubtitles) {
		Subtitle existing = Get(index);
		if (existing == null)
			return false;

		TimeSpan subtitleEnd = existing.Times.Start - TimeSpan.FromMilliseconds(timeBetweenSubtitles);
		if (subtitleEnd < TimeSpan.Zero)
			subtitleEnd = TimeSpan.FromSeconds(0);

		TimeSpan subtitleStart = subtitleEnd - TimeSpan.FromSeconds(SubtitleConstants.AverageSubtitleDuration);
		if (subtitleStart < TimeSpan.Zero)
			subtitleStart = TimeSpan.FromSeconds(0);

		Subtitle subtitle = new Subtitle(subtitleProperties, subtitleStart, subtitleEnd);
		Add(subtitle, index);
		return true;
	}
Beispiel #30
0
	/* Public methods */

	/// <summary></summary>
	/// <remarks>SubtitleProperties is not cloned and should be set afterwards.</remarks>
	public Subtitle Clone (SubtitleProperties propertiesClone) {
		Subtitle subtitleClone = new Subtitle();

		Times timesClone = this.times.Clone(subtitleClone);
		Frames framesClone = this.frames.Clone(subtitleClone);
		SubtitleText textClone = this.text.Clone() as SubtitleText;
		SubtitleText translationClone = (this.translation != null ? this.translation.Clone() as SubtitleText : null);
		Style styleClone = this.style.Clone() as Style;
		subtitleClone.SetFieldsForDeepClone(propertiesClone, timesClone, framesClone, textClone, translationClone, styleClone);

		return subtitleClone;
	}
	/// <summary>Creates a subtitle and adds it to the collection, inserting it at the specified index
	/// and with the specified start time.</summary>
	/// <remarks>The newly created subtitle's duration will be
	/// <see cref="SubtitleConstants.MaxSingleLineSubtitleDuration" />.</remarks>
	/// <param name="index">The zero-based index at which the subtitle should be inserted.</param>
	/// <param name="subtitleProperties">The SubtitleProperties of the subtitles.</param>
	/// <param name="start">The time at which the new subtitle will start</para>
	/// <returns>True if the subtitle could be added, false otherwise.</returns>
	public bool AddNewAt (int index, SubtitleProperties subtitleProperties, TimeSpan start) {
		if ((index < 0) || (index > Count))
			return false;

		TimeSpan subtitleStart = start;
		TimeSpan subtitleEnd = subtitleStart + TimeSpan.FromSeconds(SubtitleConstants.AverageSubtitleDuration);
		Subtitle subtitle = new Subtitle(subtitleProperties, subtitleStart, subtitleEnd);
		Add(subtitle, index);
		return true;
	}
Beispiel #32
0
        /* Internal members */

        /// <summary>Initializes a new instance of the <see cref="Subtitles" /> class.</summary>
        /// <param name="collection">A collection of subtitles.</param>
        /// <param name="properties">The subtitles' properties.</param>
        internal protected Subtitles(SubtitleCollection collection, SubtitleProperties properties)
        {
            this.collection = collection;
            this.properties = properties;
        }
Beispiel #33
0
 /// <summary>Creates a subtitle based on the subtitle at the specified index and adds it to the
 /// collection, inserting it right after that index.</summary>
 /// <remarks>The newly created subtitle's times will be based on the specified subtitle. Its start
 /// time will be the end time of the existing subtitle plus <see cref="SubtitleConstants.MinTimeBetweenSubtitles" />.
 /// Its duration will be <see cref="SubtitleConstants.MaxSingleLineSubtitleDuration" />.</remarks>
 /// <param name="index">The zero-based index after which the subtitle should be inserted.</param>
 /// <param name="subtitleProperties">The SubtitleProperties of the subtitles.</param>
 /// <returns>True if the subtitle could be added, false otherwise.</returns>
 public bool AddNewAfter(int index, SubtitleProperties subtitleProperties)
 {
     return(AddNewAfter(index, subtitleProperties, (int)(SubtitleConstants.MinTimeBetweenSubtitles * 1000)));
 }
Beispiel #34
0
	/// <summary>Initializes a new instance of the <see cref="Subtitle" /> class, given the
	/// global subtitles' properties and its start and end frames.</summary>
	/// <param name="properties">The subtitles' properties.</param>
	/// <param name="startFrame">The subtitle's start frame.</param>
	/// <param name="endFrame">The subtitle's end frame.</param>
	public Subtitle (SubtitleProperties properties, int startFrame, int endFrame)
			: this(properties, new SubtitleText(), new Style()) {

		frames.Start = startFrame;
		frames.End = endFrame;
	}
Beispiel #35
0
	internal virtual string GetDynamicSubtitleOut (SubtitleProperties properties) {
		return null;
	}
	internal override string GetDynamicSubtitleOut (SubtitleProperties properties) {
		bool isFrameRatePAL = IsFrameRatePAL(properties.CurrentFrameRate);
		char sep = GetTimingSeparator(isFrameRatePAL);
		string suf = GetFrameRateSuffix(isFrameRatePAL);
		return "<<SubtitleNumber>> <<StartHours>>" + sep + "<<StartMinutes>>" + sep + "<<StartSeconds>>" + sep + "<<StartMillisecondsAsFrames" + suf + ">> <<EndHours>>" + sep + "<<EndMinutes>>" + sep + "<<EndSeconds>>" + sep + "<<EndMillisecondsAsFrames" + suf + ">> <<Text>>";
	}
Beispiel #37
0
	/* Internal members */

	/// <summary>Initializes a new instance of the <see cref="Subtitles" /> class.</summary>
	/// <param name="collection">A collection of subtitles.</param>
	/// <param name="properties">The subtitles' properties.</param>
	internal protected Subtitles (SubtitleCollection collection, SubtitleProperties properties) {
		this.collection = collection;
		this.properties = properties;
	}
Beispiel #38
0
	private string GetSubtitleExpression (SubtitleFormat format, SubtitleProperties subtitleProperties, FileProperties fileProperties) {
		if (format.Mode == SubtitleMode.Both) {
			if (fileProperties.TimingMode == TimingMode.Times)
				return format.SubtitleOutTimesMode;
			else
				return format.SubtitleOutFramesMode;
		}
		else {
			if (format.SubtitleOut != null)
				return format.SubtitleOut;
			else
				return format.GetDynamicSubtitleOut(subtitleProperties);
		}
	}