Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Music Video Box (WPF)

0.00/5 (No votes)
10 Aug 2009 1  
This article explains the creation of a Music Video Box using Windows Presentation Foundation 3D Geometry and Media classes to play music albums as chosen by the user.

Introduction

This article explains the creation of a Music Video Box using the Windows Presentation Foundation 3D Geometry and Media classes to play music albums as chosen by the user.

Introduction

This Music Video Box is designed in a way that it stores music tracks of three different albums and the user can select an album and the track he wants to play. While the list of albums appears on the left side panel, the tracks for each album are represented as pictures on the sides of a 3D cube that rotates for easier selection of the track the user prefers.

Initially, the screen looks like this:

The epicenter of this application is the 3D cube that displays pictures of the tracks of the current album, and it rotates in clockwise direction.

Upon selection of an album (e.g.: Hindu Devotional), the cube takes a different look with pictures representing the tracks in the album, as below:

Upon clicking the picture, another window opens up that plays the corresponding video for you, as below:

WPF – 3D Geometry and Material

The sides of the cubes are created separately using the MeshGeometry3D class that builds a 3D shape. It allows us to specify the position, normal, and texture coordinate information.

<MeshGeometry3D x:Key="CubeSide01" 
      TriangleIndices="0,1,2 3,4,5"
      Normals="-1,0,0 -1,0,0 -1,0,0 -1,0,0 -1,0,0 -1,0,0 "
      TextureCoordinates="0,1 0,0 1,0 1,0 1,1 0,1 "
      Positions="-0.5,0.5,-0.5 -0.5,-0.5,-0.5 -0.5,-0.5,0.5 -0.5,
                 -0.5,0.5 -0.5,0.5,0.5 -0.5,0.5,-0.5 " />

The sides of the cube compose of a Material, DiffuseMaterial in this case, that allows the application of a 2-D brush, like a SolidColorBrush or TileBrush, for a diffusely-lit 3-D model. For the album selected in the list, this Material is applied on the sides dynamically, ImageBrush for the albums (Devotional and Taare Zameen Par) that contain the video tracks, and LinearGradientBrush for no selection or an album (Pop/Rock) that has only one video.

<MaterialGroup x:Key="TaareMaterial1">
    <DiffuseMaterial>
          <DiffuseMaterial.Brush>
                <ImageBrush Stretch="Fill" 
                     ImageSource="images\Taare\Taare1.jpg" 
                     TileMode="None" ViewportUnits="Absolute" 
                     Viewport="0 0 1 1" AlignmentX="Left" 
                     AlignmentY="Top" Opacity="1.000000" />
          </DiffuseMaterial.Brush>
    </DiffuseMaterial>
</MaterialGroup>

Both the Geometry and Material specifics are coded as Application Resources in app.xaml.

XAML for 3D Graphics

<Viewport3D  MouseDown="myViewport_MouseDown" 
           ClipToBounds="True" Width="600" 
           Height="400" Name="myViewport" Focusable="True" >
      <Viewport3D.Camera>
           <PerspectiveCamera x:Name="myPerspectiveCamera"
              FarPlaneDistance="15" LookDirection="0,0,1" 
              UpDirection="0,1,0" NearPlaneDistance="1" 
              Position="0,0,-3" FieldOfView="50" />
      </Viewport3D.Camera>
      <ModelVisual3D x:Name="topModelVisual3D">
            <ModelVisual3D.Children>
               <ModelVisual3D>
                     <ModelVisual3D.Content>
                         ...............
                         ...............
      <ModelVisual3D x:Name="side1ModelVisual">
            <ModelVisual3D.Content>
                   <GeometryModel3D x:Name="side1GeometryModel3D" 
                       Geometry="{StaticResource CubeSide01}" 
                       Material="{StaticResource InitMaterial1}" 
                       BackMaterial="{StaticResource InsideMaterial}"/>
            </ModelVisual3D.Content>
      </ModelVisual3D>

HitTest

The HitTest is the action that is taken when the user clicks on a side of the 3D cube. This is implemented in the ChooseTrack method wherein the mouse position parameters are retrieved from the MouseButtonEventArgs and we test for a result in the ViewPort3D.

public void ChooseTrack(object sender, System.Windows.Input.MouseButtonEventArgs args)
{
    if (listboxAlbum.SelectedIndex <= 0)
        return;
    Point mouseposition = args.GetPosition(myViewport);
    PointHitTestParameters pointparams = new PointHitTestParameters(mouseposition);

   //test for a result in the Viewport3D
   VisualTreeHelper.HitTest(myViewport, null, HTResult, pointparams);
}

The HitTest method takes the ViewPort object as a parameter along with a callback method HTResult and the position parameters. It is in the callback method HTResult, we use the RayMeshGeometry3DHitTestResult object and calls ModelHit to get the GeometryModel3D object for the three-dimensional shape where the user hits the mouse.

public HitTestResultBehavior HTResult(System.Windows.Media.HitTestResult rawresult)
{
      RayHitTestResult rayResult = rawresult as RayHitTestResult;
      if (rayResult != null)
      {
          RayMeshGeometry3DHitTestResult rayMeshResult = 
                       rayResult as RayMeshGeometry3DHitTestResult;
          if (rayMeshResult != null)
          {
              GeometryModel3D hitgeo = rayMeshResult.ModelHit as GeometryModel3D;
              SetTrack(hitgeo);
              PlayTrack();
          }
      }

      return HitTestResultBehavior.Stop;
}

There are two helper methods, SetTrack to select the track and PlayTrack to open the MediaElement in a window to play the video. In the SetTrack method, a MusicPlayer instance is created, and the properties CurrentAlbum and CurrentTrackPath are set by calling the FindAlbum and FindTrack methods, respectively.

public void SetTrack(GeometryModel3D hitgeo)
{
  mplayer = new MusicPlayer();
  mplayer.currentAlbum = AvailTracks.FindAlbum(listboxAlbum.SelectedIndex - 1);
  // For pop/rock, only one video is placed. On clicking any picture
  // on any of the 6 sides, the same video plays.
  if (listboxAlbum.SelectedIndex == 2)
  {
    mplayer.currtrapath = AvailTracks.FindTrack(listboxAlbum.SelectedIndex - 1, 0);
    return;
  }
  if (hitgeo.Geometry==MeshGeometry3D)Application.Current.Resources["CubeSide01"])
  {
     mplayer.currtrapath =AvailTracks.FindTrack(listboxAlbum.SelectedIndex - 1, 0);
  }
  else if (hitgeo.Geometry==(MeshGeometry3D)Application.Current.Resources["CubeSide02"])
  {
    mplayer.currtrapath =AvailTracks.FindTrack(listboxAlbum.SelectedIndex - 1, 1);
  }
  else if (hitgeo.Geometry == (MeshGeometry3D)Application.Current.Resources["CubeSide03"])
  {
    mplayer.currtrapath = AvailTracks.FindTrack(listboxAlbum.SelectedIndex - 1, 2);
  }
  else if (hitgeo.Geometry == (MeshGeometry3D)Application.Current.Resources["CubeSide04"])
  {
    mplayer.currtrapath = AvailTracks.FindTrack(listboxAlbum.SelectedIndex - 1, 3);
  }
  else if (hitgeo.Geometry == (MeshGeometry3D)Application.Current.Resources["CubeSide05"])
  {
    mplayer.currtrapath = AvailTracks.FindTrack(listboxAlbum.SelectedIndex - 1, 4);
  }
  else if (hitgeo.Geometry == (MeshGeometry3D)Application.Current.Resources["CubeSide06"])
  {
    mplayer.currtrapath = AvailTracks.FindTrack(listboxAlbum.SelectedIndex - 1, 5);
  }
}

In the PlayTrack method, the MusicPlayer is shown as a dialog as coded below:

public void PlayTrack()
{
    mplayer.ShowDialog();
}

On selecting an album, the pictures of the sides of the cube changes, and the method SetMaterial is used for this purpose. For example, calling this method as below:

setSideMaterial("TaareMaterial");

would apply the corresponding material resource defined in App.xaml for each side of the cube.

public void setSideMaterial(string materialKey)
{
    side1GeometryModel3D.Material = 
      (MaterialGroup) Application.Current.Resources[materialKey+"1"];
    side2GeometryModel3D.Material = 
      (MaterialGroup) Application.Current.Resources[materialKey+"2"];
    side3GeometryModel3D.Material = 
      (MaterialGroup) Application.Current.Resources[materialKey+"3"];
    side4GeometryModel3D.Material = 
      (MaterialGroup) Application.Current.Resources[materialKey+"4"];
    side5GeometryModel3D.Material = 
      (MaterialGroup) Application.Current.Resources[materialKey+"5"];
    side6GeometryModel3D.Material = 
      (MaterialGroup) Application.Current.Resources[materialKey+"6"];
}

Music Video Box’s Album class

The music videos supplied along with this application are stored in a sub-folder inside the application folder. The names of the video files are retrieved and are stored in the instances of the AlbumCollection class. The AlbumCollection class is a generic class of type Album that contains two properties namely AlbumName and TrackPath, and an array of strings.

public static class AlbumList
{
    public static AlbumCollection CreateAlbums()
    {
        string[] Devotelist = System.IO.Directory.GetFiles(@"e:\bala\music " + 
                              @"video box\tracks\devotional", "*.wmv");
        string[] PopRocklist = System.IO.Directory.GetFiles(@"e:\bala\music " + 
                               @"video box\tracks\poprock", "*.wmv");
        string[] Taarelist = System.IO.Directory.GetFiles(
                             @"e:\bala\music video box\tracks\taaree", "*.wmv");
        AlbumCollection ac = new AlbumCollection();
        ac.Add(new Album("Devotional", Devotelist));
        ac.Add(new Album("Pop/Rock", PopRocklist));
        ac.Add(new Album("Taare Zameen Par", Taarelist));
        return ac;
    }

Conclusion

This Music Video Box with three albums is created using WPF’s 3D technologies.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here