■ NAUDIO 라이브러리를 사용해 음악 재생하기

------------------------------------------------------------------------------------------------------------------------


TestSolution.zip


[TestProject 프로젝트]

 

MainWindow.xaml

 

 

<Window x:Class="TestProject.MainWindow"

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    xmlns:library="clr-namespace:TestLibrary;assembly=TestLibrary"

    Width="800"

    Height="600"

    Title="NAUDIO 라이브러리를 사용해 음악 재생하기">

    <Grid Background="{DynamicResource WindowBackgroundBrush}">

        <Grid.RowDefinitions>

            <RowDefinition Height="Auto" />

            <RowDefinition Height="100" />

            <RowDefinition Height="*"    />

            <RowDefinition Height="100" />

            <RowDefinition Height="40"   />

        </Grid.RowDefinitions>

        <Grid.ColumnDefinitions>

            <ColumnDefinition Width="30*" />

            <ColumnDefinition Width="60*" />

        </Grid.ColumnDefinitions>

        <Menu Grid.Row="0" Grid.ColumnSpan="2">

            <MenuItem Header="파일">

                <MenuItem Name="openFileMenuItem"

                    Header="파일 열기" />

                <Separator />

                <MenuItem Name="closeMenuItem"

                    Header="종료" />

            </MenuItem>

            <MenuItem Header="테마">

                <MenuItem Name="defaultThemeMenuItem"

                    Header="디폴트 (테마 없음)"

                    IsCheckable="True" />

                <MenuItem Name="expressionDarkThemeMenuItem"

                    Header="다크 테마"

                    IsCheckable="True" />

                <MenuItem Name="expressionLightThemeMenuItem"

                    Header="라이트 테마"

                    IsCheckable="True" />

            </MenuItem>

        </Menu>

        <library:DigitalClock x:Name="digitalClock" Grid.Row="1" Grid.ColumnSpan="2"

            Margin="5"

            HorizontalAlignment="Center"

            ShowHours="False"

            ShowSubSeconds="True" />

        <library:AlbumArtDisplay x:Name="albumArtDisplay" Grid.Column="0" Grid.Row="2"

            Margin="5" />

        <Grid Grid.Row="2" Grid.Column="1">

            <Grid.ColumnDefinitions>

                <ColumnDefinition Width="*" />

                <ColumnDefinition Width="*" />

            </Grid.ColumnDefinitions>

            <library:SpectrumAnalyzer x:Name="spectrumAnalyzer"

                Margin="5"

                BarCount="16" />

            <library:Equalizer x:Name="equalizer" Grid.Column="1"

                BandCount="7" />

        </Grid>

        <Grid Grid.Row="3" Grid.ColumnSpan="2">

            <Grid.ColumnDefinitions>

                <ColumnDefinition Width="*"   />

                <ColumnDefinition Width="100" />

            </Grid.ColumnDefinitions>

            <library:WaveformTimeline x:Name="waveformTimeline"

                Margin="5"

                BorderThickness="1" />

            <StackPanel Grid.Column="1"

                Orientation="Vertical"

                VerticalAlignment="Center">

                <library:TimeEditor Name="repeatStartTimeEdit"

                    Margin="5"

                    IsReadOnly="True" />

                <library:TimeEditor Name="repeatStopTimeEdit"

                    Margin="5"

                    IsReadOnly="True" />

            </StackPanel>

        </Grid>

        <Grid Grid.Row="4" Grid.ColumnSpan="2"

            Margin="5">

            <Grid.ColumnDefinitions>

                <ColumnDefinition Width="*"    />

                <ColumnDefinition Width="Auto" />

            </Grid.ColumnDefinitions>

            <TextBox Name="filePathTextBox" Grid.Column="0"

                Margin="5"

                HorizontalAlignment="Stretch"

                VerticalAlignment="Center"

                IsReadOnly="True" />

            <StackPanel Grid.Column="1"

                HorizontalAlignment="Right"

                Orientation="Horizontal">

                <Button Name="browseButton"

                    Margin="2 2 10 2"

                    HorizontalAlignment="Center"

                    VerticalAlignment="Center"

                    Height="24"

                    Width="50"

                    Content="선곡" />

                <Button Name="playButton"

                    Margin="2"

                    Width="50"

                    VerticalAlignment="Center"

                    Height="24"

                    IsEnabled="False"

                    Content="재생" />

                <Button Name="pauseButton"

                    Margin="2"

                    VerticalAlignment="Center"

                    Width="50"

                    Height="24"

                    IsEnabled="False"

                    Content="중지" />

                <Button Name="stopButton"

                    Margin="2"

                    VerticalAlignment="Center"

                    Width="50"

                    Height="24"

                    IsEnabled="False"

                    Content="중단" />

            </StackPanel>

        </Grid>

    </Grid>

</Window>

 

 

MainWindow.xaml.cs

 

 

using Microsoft.Win32;

using System;

using System.ComponentModel;

using System.IO;

using System.Windows;

using System.Windows.Controls;

using System.Windows.Media.Imaging;

using System.Windows.Data;

 

using TestLibrary;

 

namespace TestProject

{

    /// <summary>

    /// 메인 윈도우

    /// </summary>

    public partial class MainWindow : Window

    {

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region 생성자 - MainWindow()

 

        /// <summary>

        /// 생성자

        /// </summary>

        public MainWindow()

        {

            InitializeComponent();

 

            NAudioEngine naudioEngine = NAudioEngine.Instance;

 

            UIHelper.Bind(naudioEngine, "CanStop"       , this.stopButton         , Button.IsEnabledProperty                    );

            UIHelper.Bind(naudioEngine, "CanPlay"       , this.playButton         , Button.IsEnabledProperty                    );

            UIHelper.Bind(naudioEngine, "CanPause"      , this.pauseButton        , Button.IsEnabledProperty                    );

            UIHelper.Bind(naudioEngine, "SelectionBegin", this.repeatStartTimeEdit, TimeEditor.ValueProperty, BindingMode.TwoWay);

            UIHelper.Bind(naudioEngine, "SelectionEnd"  , this.repeatStopTimeEdit , TimeEditor.ValueProperty, BindingMode.TwoWay);     

 

            this.spectrumAnalyzer.RegisterSpectrumPlayer(naudioEngine);

 

            this.waveformTimeline.RegisterSoundPlayer(naudioEngine);

 

            LoadExpressionDarkTheme();

 

            naudioEngine.PropertyChanged              += naudioEngine_PropertyChanged;

            this.openFileMenuItem.Click               += openFileMenuItem_Click;

            this.closeMenuItem.Click                  += closeMenuItem_Click;

            this.defaultThemeMenuItem.Checked         += defaultThemeMenuItem_Checked;

            this.expressionDarkThemeMenuItem.Checked  += expressionDarkThemeMenuItem_Checked;

            this.expressionLightThemeMenuItem.Checked += expressionLightThemeMenuItem_Checked;

            this.browseButton.Click                   += browseButton_Click;

            this.playButton.Click                     += playButton_Click;

            this.pauseButton.Click                    += pauseButton_Click;

            this.stopButton.Click                     += stopButton_Click;

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method

        ////////////////////////////////////////////////////////////////////////////////////////// Protected

 

        #region 닫을 경우 처리하기 - OnClosing(e)

 

        /// <summary>

        /// 닫을 경우 처리하기

        /// </summary>

        /// <param name="e">이벤트 인자</param>

        protected override void OnClosing(CancelEventArgs e)

        {

            NAudioEngine.Instance.Dispose();

        }

 

        #endregion

 

        ////////////////////////////////////////////////////////////////////////////////////////// Private

        //////////////////////////////////////////////////////////////////////////////// Event

 

        #region NAUDIO 엔진 속성 변경시 처리하기 - naudioEngine_PropertyChanged(sender, e)

 

        /// <summary>

        /// NAUDIO 엔진 속성 변경시 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        private void naudioEngine_PropertyChanged(object sender, PropertyChangedEventArgs e)

        {

            NAudioEngine naudioEngine = NAudioEngine.Instance;

 

            switch(e.PropertyName)

            {

                case "FileTag" :

 

                    if(naudioEngine.FileTag != null)

                    {

                        TagLib.Tag tag = naudioEngine.FileTag.Tag;

 

                        if(tag.Pictures.Length > 0)

                        {

                            using(MemoryStream memoryStream = new MemoryStream(tag.Pictures[0].Data.Data))

                            {

                                try

                                {

                                    BitmapImage bitmapImage = new BitmapImage();

 

                                    bitmapImage.BeginInit();

 

                                    bitmapImage.CacheOption  = BitmapCacheOption.OnLoad;

                                    bitmapImage.StreamSource = memoryStream;

 

                                    bitmapImage.EndInit();

 

                                    this.albumArtDisplay.AlbumArtImage = bitmapImage;

                                }

                                catch(NotSupportedException)

                                {

                                    this.albumArtDisplay.AlbumArtImage = null;

                                }

 

                                memoryStream.Close();

                            }

                        }

                        else

                        {

                            this.albumArtDisplay.AlbumArtImage = null;

                        }

                    }

                    else

                    {

                        this.albumArtDisplay.AlbumArtImage = null;

                    }

 

                    break;

 

                case "ChannelPosition" :

 

                    this.digitalClock.Time = TimeSpan.FromSeconds(naudioEngine.ChannelPosition);

 

                    break;   

 

                default:

 

                    break;

            }

        }

 

        #endregion

 

        #region 파일 열기 메뉴 항목 클릭시 처리하기 - openFileMenuItem_Click(sender, e)

 

        /// <summary>

        /// 파일 열기 메뉴 항목 클릭시 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        private void openFileMenuItem_Click(object sender, RoutedEventArgs e)

        {

            OpenFile();

        }

 

        #endregion

        #region 닫기 메뉴 항목 클릭시 처리하기 - closeMenuItem_Click(sender, e)

 

        /// <summary>

        /// 닫기 메뉴 항목 클릭시 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        private void closeMenuItem_Click(object sender, RoutedEventArgs e)

        {

            Close();

        }

 

        #endregion

        #region 디폴트 테마 메뉴 항목 클릭시 처리하기 - defaultThemeMenuItem_Checked(sender, e)

 

        /// <summary>

        /// 디폴트 테마 메뉴 항목 클릭시 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        private void defaultThemeMenuItem_Checked(object sender, RoutedEventArgs e)

        {

            LoadDefaultTheme();

        }

 

        #endregion

        #region 익스프레션 다크 테마 메뉴 항목 클릭시 처리하기 - expressionDarkThemeMenuItem_Checked(sender, e)

 

        /// <summary>

        /// 익스프레션 다크 테마 메뉴 항목 클릭시 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        private void expressionDarkThemeMenuItem_Checked(object sender, RoutedEventArgs e)

        {

            LoadExpressionDarkTheme();

        }

 

        #endregion

        #region 익스프레션 라이트 테마 메뉴 항목 클릭시 처리하기 - expressionLightThemeMenuItem_Checked(sender, e)

 

        /// <summary>

        /// 익스프레션 라이트 테마 메뉴 항목 클릭시 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        private void expressionLightThemeMenuItem_Checked(object sender, RoutedEventArgs e)

        {

            LoadExpressionLightTheme();

        }

 

        #endregion

 

        #region 선곡 버튼 클릭시 처리하기 - browseButton_Click(sender, e)

 

        /// <summary>

        /// 선곡 버튼 클릭시 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        private void browseButton_Click(object sender, RoutedEventArgs e)

        {

            OpenFile();

        }

 

        #endregion

        #region 재생 버튼 클릭시 처리하기 - playButton_Click(sender, e)

 

        /// <summary>

        /// 재생 버튼 클릭시 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        private void playButton_Click(object sender, RoutedEventArgs e)

        {

            if(NAudioEngine.Instance.CanPlay)

            {

                NAudioEngine.Instance.Play();

            }

        }

 

        #endregion

        #region 중지 버튼 클릭시 처리하기 - pauseButton_Click(sender, e)

 

        /// <summary>

        /// 중지 버튼 클릭시 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        private void pauseButton_Click(object sender, RoutedEventArgs e)

        {

            if(NAudioEngine.Instance.CanPause)

            {

                NAudioEngine.Instance.Pause();

            }

        }

 

        #endregion

        #region 중단 버튼 클릭시 처리하기 - stopButton_Click(sender, e)

 

        /// <summary>

        /// 중단 버튼 클릭시 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        private void stopButton_Click(object sender, RoutedEventArgs e)

        {

            if(NAudioEngine.Instance.CanStop)

            {

                NAudioEngine.Instance.Stop();

            }

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////// Event

 

        #region 파일 열기 - OpenFile()

 

        /// <summary>

        /// 파일 열기

        /// </summary>

        private void OpenFile()

        {

            OpenFileDialog openFileDialog = new OpenFileDialog();

 

            openFileDialog.Filter = "MP3 파일|*.mp3";

 

            if(openFileDialog.ShowDialog() == true)

            {

                NAudioEngine.Instance.OpenFile(openFileDialog.FileName);

 

                this.filePathTextBox.Text = openFileDialog.FileName;

            }

        }

 

        #endregion

        #region 디폴트 테마 로드하기 - LoadDefaultTheme()

 

        /// <summary>

        /// 디폴트 테마 로드하기

        /// </summary>

        private void LoadDefaultTheme()

        {

            this.defaultThemeMenuItem.IsChecked         = true;

            this.defaultThemeMenuItem.IsEnabled         = false;

            this.expressionDarkThemeMenuItem.IsChecked  = false;

            this.expressionDarkThemeMenuItem.IsEnabled  = true;

            this.expressionLightThemeMenuItem.IsChecked = false;

            this.expressionLightThemeMenuItem.IsEnabled = true;

 

            Resources.MergedDictionaries.Clear();

        }

 

        #endregion

        #region 익스프레션 다크 테마 로드하기 - LoadExpressionDarkTheme()

 

        /// <summary>

        /// 익스프레션 다크 테마 로드하기

        /// </summary>

        private void LoadExpressionDarkTheme()

        {

            this.defaultThemeMenuItem.IsChecked         = false;

            this.defaultThemeMenuItem.IsEnabled         = true;

            this.expressionDarkThemeMenuItem.IsChecked  = true;

            this.expressionDarkThemeMenuItem.IsEnabled  = false;

            this.expressionLightThemeMenuItem.IsChecked = false;

            this.expressionLightThemeMenuItem.IsEnabled = true;

 

            Resources.MergedDictionaries.Clear();

 

            ResourceDictionary resourceDictionary = Application.LoadComponent(new Uri("ExpressionDark.xaml", UriKind.Relative))

                as ResourceDictionary;

 

            Resources.MergedDictionaries.Add(resourceDictionary);

        }

 

        #endregion

        #region 익스프레션 라이트 테마 로드하기 - LoadExpressionLightTheme()

 

        /// <summary>

        /// 익스프레션 라이트 테마 로드하기

        /// </summary>

        private void LoadExpressionLightTheme()

        {

            this.defaultThemeMenuItem.IsChecked         = false;

            this.defaultThemeMenuItem.IsEnabled         = true;

            this.expressionDarkThemeMenuItem.IsChecked  = false;

            this.expressionDarkThemeMenuItem.IsEnabled  = true;

            this.expressionLightThemeMenuItem.IsChecked = true;

            this.expressionLightThemeMenuItem.IsEnabled = false;

 

            Resources.MergedDictionaries.Clear();

 

            ResourceDictionary themeResources = Application.LoadComponent(new Uri("ExpressionLight.xaml", UriKind.Relative))

                as ResourceDictionary;

 

            Resources.MergedDictionaries.Add(themeResources);

        }

 

        #endregion

    }

}

 

------------------------------------------------------------------------------------------------------------------------

※ 컴파일시 TestProject 프로젝트의 플랫폼 대상을 x86으로 설정해야 한다.

Posted by 사용자 icodebroker
TAG

댓글을 달아 주세요