Seb,
I assume that when you say "expose" that you mean offer audio play controls for those sub-clips.
Here is a suggested step-by-step for building a Silverlight app that plays an audio file between a start and an end point:
Step 1: Create a sample Silverlight application with Visual Studio (File / New Project / Silverlight Application
Step 2: In your newly create project, edit the MainPage.xaml, and place the following code inside the UserControl's Grid:
<StackPanel>
<MediaElement x:Name="x_MediaElement" AutoPlay="False" Stretch="Uniform" CacheMode="BitmapCache"
MediaOpened="OnMediaOpened" MarkerReached="OnMarkerReached" MediaEnded="OnMediaEnded" CurrentStateChanged="OnMediaCurrentStateChanged"
Source="http://www.shinedraw.com/wordpress/wp-content/uploads/AudioPlayer/littlewaltz.mp3" />
<StackPanel Orientation="Horizontal">
<Button x:Name="x_Play" Click="OnPlayClick" Content="Play" Height="20" Width="40" />
<Button x:Name="x_Pause" Click="OnPauseClick" Content="Pause" Height="20" Width="40" />
<Button x:Name="x_Stop" Click="OnStopClick" Content="Stop" Height="20" Width="40" />
<Slider x:Name="x_Timeline" HorizontalAlignment="Stretch" Width="200" Maximum="1" Value="0" ValueChanged="OnTimelineValueChanged"/>
<TextBlock x:Name="x_CurrentTime" Height="20" Width="75" TextAlignment="Right" HorizontalAlignment="Right" VerticalAlignment="Center" />
<TextBlock Text="/" Height="20" VerticalAlignment="Center" />
<TextBlock x:Name="x_TotalTime" Height="20" Width="75" VerticalAlignment="Center" />
<ToggleButton x:Name="x_Mute" Click="OnMuteClick" Content="Mute" Height="20" Width="40" IsChecked="false" />
<Slider x:Name="x_VolumeSlider" HorizontalAlignment="Stretch" Width="50" Maximum="1"
Value="{Binding ElementName=x_MediaElement, Mode=TwoWay, Path=Volume, UpdateSourceTrigger=Default}"/>
</StackPanel>
</StackPanel>
Step 3: Edit the MainPage.cs, and replace the MainPage class with the following code:
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
CompositionTarget.Rendering += OnCompositionTargetRendering;
}
private void SetStart(TimeSpan timeStart)
{
x_MediaElement.Position = timeStart;
}
private void SetEnd(TimeSpan timeEnd)
{
if (x_MediaElement.Markers == null || x_MediaElement.Markers.Count == 0)
x_MediaElement.Markers.Add(new TimelineMarker() { Time = timeEnd });
else
x_MediaElement.Markers[0].Time = timeEnd;
}
private bool _InTickEvent;
private void OnPlayClick(object sender, RoutedEventArgs e)
{
SetStart(new TimeSpan(0,0,10));
SetEnd(new TimeSpan(0,0,20));
x_MediaElement.Play();
}
private void OnPauseClick(object sender, RoutedEventArgs e)
{
x_MediaElement.Pause();
}
private void OnStopClick(object sender, RoutedEventArgs e)
{
x_MediaElement.Stop();
}
private void OnMuteClick(object sender, RoutedEventArgs e)
{
x_MediaElement.IsMuted = (bool)x_Mute.IsChecked;
}
private void OnMediaOpened(object sender, RoutedEventArgs e)
{
x_TotalTime.Text = TimeSpanToString(x_MediaElement.NaturalDuration.TimeSpan);
}
private void OnMarkerReached(object sender, TimelineMarkerRoutedEventArgs e)
{
x_MediaElement.Stop();
}
private void OnMediaEnded(object sender, RoutedEventArgs e)
{
x_MediaElement.Stop();
}
private void OnTimelineValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
if (_InTickEvent)
return; // throw new Exception("Can't call Seek() now, you'll get an infinite loop");
double percentComplete = x_Timeline.Value;
TimeSpan duration = x_MediaElement.NaturalDuration.TimeSpan;
int newPosition = (int)(duration.TotalSeconds * percentComplete);
x_MediaElement.Position = new TimeSpan(0, 0, newPosition);
}
private void OnCompositionTargetRendering(object sender, EventArgs e)
{
_InTickEvent = true;
TimeSpan duration = x_MediaElement.NaturalDuration.TimeSpan;
if (duration.TotalSeconds != 0)
{
double percentComplete = (x_MediaElement.Position.TotalSeconds / duration.TotalSeconds);
x_Timeline.Value = percentComplete;
string text = TimeSpanToString(x_MediaElement.Position);
if (x_CurrentTime.Text != text)
x_CurrentTime.Text = text;
}
_InTickEvent = false;
}
private string TimeSpanToString(TimeSpan time)
{
return string.Format("{0:00}:{1:00}", (time.Hours * 60) + time.Minutes, time.Seconds);
}
private void OnMediaCurrentStateChanged(object sender, RoutedEventArgs e)
{
switch (x_MediaElement.CurrentState)
{
case MediaElementState.Buffering:
break;
case MediaElementState.Opening:
break;
case MediaElementState.Paused:
break;
case MediaElementState.Playing:
break;
case MediaElementState.Stopped:
break;
}
}
}
Step 4: Build and Run!