Artykuł

lut 22 2012
0

Odtwarzanie plików MP3 w C#

Z biegiem lat, mam nieodparte wrażenie, że doba staje się coraz bardziej krótsza. Brakuje mi czasu na wiele różnych rzeczy. Obojętnie czy jest to pisanie kodu, czytanie książek, czy też nauka. Problem ten dotyczy również bloga, dlatego też spróbuję rozwiązać go w pewien sposób, wprowadzając nowy rodzaj tekstów oznaczonych tagiem Szybkie porady. Głównym zadaniem wpisów oznaczonych takim znacznikiem, będzie rozwiązanie pewnych, jasno określonych problemów. Teksty tego typu mogą pojawić się właściwie w każdej kategorii i będą w sposób zwięzły rozwiązywać określony problem (mogą to być również Wasze problemy, o które spytacie np. drogą mailową.

Wpisy tej kategorii cechować się będą z pewnością odrobinę mniejszą objętością. Nie ma się co oszukiwać, że średnia ilość tekstu, która przypada na jeden wpis, jest na Alt Control Delete raczej duża - w kontraście choćby do średniej na innych blogach.

Zmniejszając objetość określonych wpisów, postaram się za to poszerzyć zakres tematów i jednocześnie nie obniżyć jakości samego bloga. Mam nadzieję, że nowy cykl wpisów przypadnie Wam do gustu;) Uprzedzając pytanie - wpisy normalnej objętości dalej będą się pojawiać.

To tyle tytułem wstępu, czas przejść do meritum, czyli w dniu dziejszym będą to zagadnienia związane z odtwarzaniem plików MP3 w C#. Przedstawię i pokrótce opiszę dwa sposoby realizacji tego celu.

Rozwiązanie

Kwestia odtwarzania pliku MP3, pojawiła się u mnie w moim ostatnim projekcie, który robiłem dla znajomego. Rozwiązań tego problemu jest z pewnością kilka, jednak dwa z nich szczególnie przypadły mi do gustu.

Umieściłem je razem w jednej klasie App:

using System;
using System.Text;
// Dla WMP, wymaga referencji COM Windows Media Player
// C:\Windows\system32\wmp.dll
using WMPLib;
// Dla winmm
using System.Runtime.InteropServices;

namespace Mp3Test
{
    class App
    {
        private readonly string MP3_PATH = "D:\\Piosenka.mp3";
        
        [DllImport("winmm.dll")]
        private static extern long mciSendString(string sCommand, 
			StringBuilder sReturn, int nReturnLength, IntPtr oCallback);

        public void PlayMp3UsingWMP()
        {
            WindowsMediaPlayer oMediaPlayer = new WindowsMediaPlayer();
            oMediaPlayer.URL = MP3_PATH;
            oMediaPlayer.controls.play();
            // ...
            Console.ReadKey();
            oMediaPlayer.controls.stop();
        }

        public void PlayMp3UsingWinmm()
        {
            mciSendString("open \"" + MP3_PATH + 
				"\" type mpegvideo alias MediaFile", null, 0, IntPtr.Zero);
            mciSendString("play MediaFile", null, 0, IntPtr.Zero);
            // ...
            Console.ReadKey();
            mciSendString("close MediaFile", null, 0, IntPtr.Zero);
        }
    }
}

Omówienie listingu, zaczniemy od przestrzeni nazw. Oprócz tych standardowych, w linii 5 pojawia się WMPLib. Jest to referencja dla biblioteki COM Windows Media Player. Powinna ona znajdować się w każdym Windowsie (jest ona wymagana przez Windows Media Player). My wykorzystamy ją w metodzie PlayMp3UsingWMP.

W linii 7, podpinamy także bibliotekę potrzebną dla konstrukcji DllImport - będzie ona potrzebna w drugiej z metod. Najwyższy czas przejść do konkretów.

Odtwarzanie przy użyciu biblioteki Windows Media Player

Odtwarzanie przy użyciu biblioteki Windows Media Player realizujemy w metodzie PlayMp3UsingWMP zawartej w liniach 19-27.

Na początku, tworzymy obiekt klasy Windows Media Player (21). Następnie wskazujemy ścieżkę do piosenki (zdefiniowaliśmy sobie ją wcześniej w linii 13 jako pole klasy), by w końcu w linii 23 uruchomić odtwarzanie.

Kod ten, można umieścić również bez problemu w osobnym wątku.

Gdybyśmy tak teraz zostawili ten kod sam sobie, to w przypadku aplikacji konsolowej, prawdopodobnie by się ona natychmiast zakończyła i nic byśmy nie usłyszeli. Dlatego w linii 25 czekamy na naciśnięcie klawisza przez użytkownika, by w linii 26 zatrzymać odtwarzanie utworu.

Klasa Windows Media Player posiada oczywiście znacznie więcej możliwości, które możecie poznać choćby przy pomocy IntelliSense.

Odtwarzanie przy użyciu biblioteki Winmm

Drugie rozwiązanie polega na użyciu Windows Multimedia API, zawartego w pliku winmm.dll. W tym przypadku korzystamy z biblioteki Windowsa. Również w tym przypadku kod jest całkiem prosty, choć często zdarzają się pewne komplikacje, ale o tym za chwilę.

Najpierw musimy wykonać trochę dziwną konstrukcję, która pozwoli nam na wykorzystanie funkcji mciSendString wysyłającej komunikaty do naszego urządzenia audio (15-17). Bardzo ważny jest fakt, żeby funkcja ta nazywała się właśnie tak a nie inaczej (w innym przypadku nie zadziała).

Po zdefiniowaniu funkcji, możemy przystąpić do zbadania metody PlayMp3UsingWinmm zawartej w liniach 29-37.

Schemat działania w tym przypadku jest identyczny jak w poprzedniej metodzie. Otwieramy plik, uruchamiamy odtwarzanie, czekamy na klawisz i zatrzymujemy muzykę.

Każda operacja realizowana jest poprzez wysłanie odpowiedniej komendy do funkcji mciSendString. W gruncie rzeczy, w tej funkcji interesuje nas tylko pierwszy parametr - reszta pozostaje bez zmian za każdym razem.

W liniach 31-32 otwieramy plik i przypisujemy mu alias MediaFile. Dzięki temu, będziemy mogli się do niego odwoływać w kolejnych wywołaniach funkcji za pomocą aliasu, bez konieczności ponownego podawania ścieżki. Wszystko to bardziej przypomina programowanie strukturalne, aniżeli obiektowe.

W linii 33, uruchamiamy odtwarzanie za pomocą komendy play wykorzystując wcześniej zdefiniowany alias.

W linii 36, kończymy odtwarzanie.

Co wybrać?

Z dwóch rozwiązań, poleciłbym chyba jednak to pierwsze, bo:

  • Łatwiej się z niego korzysta
  • Ma wiele możliwości i opcji
  • Korzystamy z programowania obiektowego
  • Bez problemu radzi sobie z wątkami

Pewnym minusem jest za to, uzależnienie od Windows Media Playera.

Drugie rozwiązanie jest bardziej kłopotliwe:

  • Problemy pojawiają się w przypadku wykorzystania wątków
  • Trudniej debugować taki kod (o ile jest to w ogóle możliwe)
  • Brak IntelliSense

Nie ma w tym przypadku za to konieczności bratania się z Windows Media Playerem. Tutaj znajdziecie więcej informacji na temat funkcji mciSendString.

Podoba Ci się ten wpis? Powiedz o tym innym!

Send to Kindle

Komentarze

blog comments powered by Disqus