2021年8月7日土曜日

C#でMusic Playerを作ろう 2

 前回はmciSendString関数を色々試したので、今回はそれを使って簡単なMusic Playerを作ります。ソースコードは530行だけなので簡単です。


 今回のソフトを作るときに一番苦労したのはUIのデザインです。

 最初は、曲を移動するための"Next"、"Prev"ボタンとか、リストから1曲削除するボタンとか、"Pause/Resume"機能とかも作ったのですが、結局、やめました。とにかく単純にしたかったから。

 ちなみに、音量操作をトラックバーではなく、ボタンにしたのは、見た目が理由です。トラックバーだと、再生位置用のトラックバーとかぶるんで。

 リストの保存とか、ファイルの拡張子の制限とか、ほかにも機能は色々追加できるんですが。まぁ、なくてもいいかなぁ、という感じです。

 結果、コンパイルしたら12KBでした。こういう軽いソフトが好きなんです。


 ソースコードはご自由にご利用ください。ただし、趣味のプログラムなので保証はありません。



using System;

using System.IO;

using System.Text;

using System.Drawing;

using System.Windows.Forms;

using System.Runtime.InteropServices;

using System.Collections.Generic;


/*--------------------------------------------------*/

class Program

{

[STAThread]


static void Main()

{

Application.Run( new MusicPlayer());

}

}


/*--------------------------------------------------*/

class MusicPlayer : Form

{

/*--------------------------------------------------*/

[DllImport( "Winmm.dll")]

extern static int mciSendString( string cmd, System.Text.StringBuilder retStr, uint ret, IntPtr hwnd);


/*--------------------------------------------------*/

private MenuStrip ms;

private ToolStripMenuItem[][] tsmi;


private Label lbl;

private ListBox lbx;

private List<string> lst;


private TextBox tbx;

private TrackBar tbr;


private Button[] btn;


private const string DeviceID = "mysound";


private int volume;


private Timer tmr;


/*--------------------------------------------------*/

public MusicPlayer()

{

/*--------------------------------------------------*/

this.ClientSize = new Size( 280, 360);

this.Text = "Music Player";


this.Load += new EventHandler( this.Form_Load);

this.Closed += new EventHandler( this.Form_Closed);


this.AllowDrop = true;

this.DragEnter += new DragEventHandler( this.Form_DragEnter);

this.DragDrop += new DragEventHandler( this.Form_DragDrop);


/*--------------------------------------------------*/

this.CreateMenu();


/*--------------------------------------------------*/

this.lbl = new Label();

this.lbl.SetBounds( 20, 30, 240, 30);

this.lbl.Anchor = AnchorStyles.Left | AnchorStyles.Top | AnchorStyles.Right;

this.lbl.TextAlign = ContentAlignment.MiddleLeft;

this.lbl.Text = "Play List";

this.Controls.Add( this.lbl);


/*--------------------------------------------------*/

this.lbx = new ListBox();

this.lbx.SetBounds( 20, 60, 240, 160);

this.lbx.Anchor = AnchorStyles.Left | AnchorStyles.Top | AnchorStyles.Right | AnchorStyles.Bottom;

this.lbx.HorizontalScrollbar = true;

this.Controls.Add( this.lbx);


/*--------------------------------------------------*/

this.tbx = new TextBox();

this.tbx.SetBounds( 20, 230, 240, 20);

this.tbx.Anchor = AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Bottom;

this.tbx.BorderStyle = BorderStyle.None;

this.tbx.ReadOnly = true;

this.Controls.Add( this.tbx);

this.tbr = new TrackBar();

this.tbr.SetBounds( 20, 250, 240, 50);

this.tbr.Anchor = AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Bottom;

this.tbr.MouseUp += new MouseEventHandler( this.tbr_MouseUp);

this.Controls.Add( this.tbr);


/*--------------------------------------------------*/

this.btn = new Button[4];


this.btn[0] = new Button();

this.btn[0].SetBounds( 20, 300, 60, 40);

this.btn[0].Anchor = AnchorStyles.Bottom;

this.btn[0].Text = ">";

this.btn[0].Click += new EventHandler( this.btn_Play_Click);

this.Controls.Add( this.btn[0]);


this.btn[1] = new Button();

this.btn[1].SetBounds( 80, 300, 60, 40);

this.btn[1].Anchor = AnchorStyles.Bottom;

this.btn[1].Text = "||";

this.btn[1].Click += new EventHandler( this.btn_Stop_Click);

this.Controls.Add( this.btn[1]);


this.btn[2] = new Button();

this.btn[2].SetBounds( 140, 300, 60, 40);

this.btn[2].Anchor = AnchorStyles.Bottom;

this.btn[2].Text = "Vol.-";

this.btn[2].Click += new EventHandler( this.btn_VolumeDown_Click);

this.Controls.Add( this.btn[2]);


this.btn[3] = new Button();

this.btn[3].SetBounds( 200, 300, 60, 40);

this.btn[3].Anchor = AnchorStyles.Bottom;

this.btn[3].Text = "Vol.+";

this.btn[3].Click += new EventHandler( this.btn_VolumeUp_Click);

this.Controls.Add( this.btn[3]);

}


/*--------------------------------------------------*/

private void Form_Load( object sender, EventArgs e)

{

Console.WriteLine( "Form_Load");


this.lst = new List<string>();


this.volume = 10;


this.tmr = new Timer();

this.tmr.Interval = 1000;

this.tmr.Tick += new EventHandler( this.timer_Tick);

}

private void Form_Closed( object sender, EventArgs e)

{

Console.WriteLine( "Form_Closed");


this.tmr.Enabled = false;


string cmd = "stop " + MusicPlayer.DeviceID;

int ret = mciSendString( cmd, null, 0, IntPtr.Zero);

Console.WriteLine( cmd);


cmd = "close " + MusicPlayer.DeviceID;

ret = mciSendString( cmd, null, 0, IntPtr.Zero);

Console.WriteLine( cmd);

}


/*--------------------------------------------------*/

private void Form_DragEnter( object sender, DragEventArgs e)

{

if( e.Data.GetDataPresent( DataFormats.FileDrop))

{

e.Effect = DragDropEffects.Move;

}

}

private void Form_DragDrop( object sender, DragEventArgs e)

{

string[] filenames = (string[]) e.Data.GetData( DataFormats.FileDrop, false);


this.lbx_Add( filenames);

}


/*--------------------------------------------------*/

private void CreateMenu()

{

this.ms = new MenuStrip();


this.tsmi = new ToolStripMenuItem[2][];

this.tsmi[0] = new ToolStripMenuItem[4];

this.tsmi[1] = new ToolStripMenuItem[3];


for( int i = 0; i < this.tsmi.Length; i++)

{

for( int j = 0; j < this.tsmi[i].Length; j++)

{

this.tsmi[i][j] = new ToolStripMenuItem();

}

}


this.tsmi[0][0].Text = "File";

this.tsmi[0][1].Text = "Select";

this.tsmi[0][2].Text = "Clear";

this.tsmi[0][3].Text = "Exit (&X)";

this.tsmi[1][0].Text = "MCI";

this.tsmi[1][1].Text = "Play";

this.tsmi[1][2].Text = "Stop";


for( int i = 0; i < this.tsmi.Length; i++)

{

this.ms.Items.Add( this.tsmi[i][0]);


for( int j = 1; j < this.tsmi[i].Length; j++)

{

this.tsmi[i][0].DropDownItems.Add( this.tsmi[i][j]);

this.tsmi[i][j].Click += new EventHandler( this.Menu_Click);

}

}


this.Controls.Add( this.ms);

this.MainMenuStrip = ms;

}


/*--------------------------------------------------*/

/* Menuのイベント処理 */

/*--------------------------------------------------*/

private void Menu_Click( object sender, EventArgs e)

{

Console.WriteLine( sender.ToString());


if( sender == this.tsmi[0][1])

{

OpenFileDialog ofd = new OpenFileDialog();

ofd.Filter = "All files | *.*";

ofd.Multiselect = true;


if( ofd.ShowDialog() == DialogResult.OK)

{

this.lbx_Add( ofd.FileNames);

}

}

else if( sender == this.tsmi[0][2])

{

this.lbx_Clear();

}

else if( sender == this.tsmi[0][3])

{

this.Close();

}

else if( sender == this.tsmi[1][1])

{

this.btn_Play_Click( null, null);

}

else if( sender == this.tsmi[1][2])

{

this.btn_Stop_Click( null, null);

}

}


/*--------------------------------------------------*/

/* リストの処理 */

/*--------------------------------------------------*/

private void lbx_Add( string[] filenames)

{

for( int i = 0; i < filenames.Length; i++)

{

Console.WriteLine( filenames[i]);


this.lst.Add( filenames[i]);

this.lbx.Items.Add( Path.GetFileName( filenames[i]));

this.lbx.SelectedIndex = this.lbx.Items.Count - 1;

}

}


private void lbx_Clear()

{

this.lst.Clear();

this.lbx.Items.Clear();

}


/*--------------------------------------------------*/

/* Buttonのイベント処理 */

/*--------------------------------------------------*/

private void btn_Play_Click( object sender, EventArgs e)

{

Console.WriteLine( "btn_Play_Click");


string status = this.mciGetStatus();


if( status == "")

{

if( this.lbx.SelectedIndex == -1)

{

return;

}


this.mciOpen( this.lst[this.lbx.SelectedIndex]);

this.mciPlay();

}

else if( status  == "playing")

{

return;

}

else if( status  == "stopped")

{

this.mciPlay();

}

}


private void btn_Stop_Click( object sender, EventArgs e)

{

Console.WriteLine( "btn_Stop_Click");

string status = this.mciGetStatus();


if( status == "")

{

return;

}

else if( status  == "playing")

{

this.mciStop();

}

else if( status  == "stopped")

{

this.mciClose();

}

}


private void btn_VolumeDown_Click( object sender, EventArgs e)

{

Console.WriteLine( "btn_VolumeDown_Click");


string status = this.mciGetStatus();


if( status != "")

{

this.mciVolumeDown();

}

}


private void btn_VolumeUp_Click( object sender, EventArgs e)

{

Console.WriteLine( "btn_VolumeUp_Click");


string status = this.mciGetStatus();


if( status != "")

{

this.mciVolumeUp();

}

}


/*--------------------------------------------------*/

/* TrackBarのイベント処理 */

/*--------------------------------------------------*/

private void tbr_MouseUp( object sender, MouseEventArgs e)

{

Console.WriteLine( "tbr_MouseUp");


string status = this.mciGetStatus();


if( status != "")

{

this.tmr.Enabled = false;

this.mciSeek( this.tbr.Value);

}

}


/*--------------------------------------------------*/

/* 再生中のタイマーイベント */

/*--------------------------------------------------*/

private void timer_Tick( object sender, EventArgs e)

{

Console.WriteLine( "timer tick");


/*--------------------------------------------------*/

string str = this.mciGetStatus();


/*--------------------------------------------------*/

StringBuilder retStr = new StringBuilder( 256);

string cmd = "status " + MusicPlayer.DeviceID + " position";

int ret = mciSendString( cmd, retStr, (uint) retStr.Capacity, IntPtr.Zero);


str += ", pos.:" + retStr.ToString();


this.tbr.Value = Convert.ToInt32( retStr.ToString());


cmd = "status " + MusicPlayer.DeviceID + " length";

ret = mciSendString( cmd, retStr, (uint) retStr.Capacity, IntPtr.Zero);


str += " / " + retStr.ToString();


/*--------------------------------------------------*/

cmd = "status " + MusicPlayer.DeviceID + " volume";

ret = mciSendString( cmd, retStr, (uint) retStr.Capacity, IntPtr.Zero);


str += ", vol.:" + retStr.ToString();


/*--------------------------------------------------*/

this.tbx.Text = str;

}


/*--------------------------------------------------*/

/* Notifyイベントの処理 */

/* 曲が終わったら、リストの次の曲を再生する (Stop or Seekから呼ばれた場合はreturn)

/*--------------------------------------------------*/

protected override void WndProc( ref Message m)

{

base.WndProc( ref m);


if( m.Msg == 0x03B9) //MM_MCINOTIFY message

{

Console.WriteLine( "Notify");


if( this.tmr.Enabled == false)

{

return;

}


this.mciStop();

this.mciClose();


if( ! ( 0 <= this.lbx.SelectedIndex && this.lbx.SelectedIndex < this.lbx.Items.Count - 1))

{

return;

}


this.lbx.SelectedIndex++;


this.mciOpen( this.lst[this.lbx.SelectedIndex]);

this.mciPlay();

}

}


/*--------------------------------------------------*/

/* MCIの状態を返す ("", "playing", "stopped"のいずれかになるはず) */

/*--------------------------------------------------*/

private string mciGetStatus()

{

StringBuilder retStr = new StringBuilder( 256);


string cmd = "status " + MusicPlayer.DeviceID + " mode";

int ret = mciSendString( cmd, retStr, (uint) retStr.Capacity, IntPtr.Zero);


Console.WriteLine( "mode : " + retStr);


return retStr.ToString();

}


/*--------------------------------------------------*/

/* MCI Open, Play, Stop, Close */

/*--------------------------------------------------*/

private void mciOpen( string filename)

{

/*--------------------------------------------------*/

string cmd = "open " + "\"" + filename + "\"" + " alias " + MusicPlayer.DeviceID;

int ret = mciSendString( cmd, null, 0, IntPtr.Zero);

Console.WriteLine( cmd);


/*--------------------------------------------------*/

cmd = "setaudio " + MusicPlayer.DeviceID + " volume to " + ( this.volume * 100).ToString();

ret = mciSendString( cmd, null, 0, IntPtr.Zero);

Console.WriteLine( cmd);


/*--------------------------------------------------*/

StringBuilder retStr = new StringBuilder( 256);


cmd = "status " + MusicPlayer.DeviceID + " length";

ret = mciSendString( cmd, retStr, (uint) retStr.Capacity, IntPtr.Zero);


this.tbr.Minimum = 0;

this.tbr.Maximum = Convert.ToInt32( retStr.ToString());

}


private void mciPlay()

{

string cmd = "play " + MusicPlayer.DeviceID + " notify";

int ret = mciSendString( cmd, null, 0, this.Handle);

Console.WriteLine( cmd);


this.tmr.Enabled = true;


this.timer_Tick( null, null);

}


private void mciStop()

{

this.tmr.Enabled = false;


string cmd = "stop " + MusicPlayer.DeviceID;

int ret = mciSendString( cmd, null, 0, IntPtr.Zero);

Console.WriteLine( cmd);


this.timer_Tick( null, null);

}


private void mciClose()

{

string cmd = "close " + MusicPlayer.DeviceID;

int ret = mciSendString( cmd, null, 0, IntPtr.Zero);

Console.WriteLine( cmd);


this.tbx.Text = "";

}


/*--------------------------------------------------*/

/* MCI Volume Down/Up */

/*--------------------------------------------------*/

private void mciVolumeDown()

{

this.volume = Math.Max( 0, this.volume - 1);

string cmd = "setaudio " + MusicPlayer.DeviceID + " volume to " + ( this.volume * 100).ToString();

int ret = mciSendString( cmd, null, 0, IntPtr.Zero);

Console.WriteLine( cmd);


this.timer_Tick( null, null);

}


private void mciVolumeUp()

{

this.volume = Math.Min( this.volume + 1, 10);

string cmd = "setaudio " + MusicPlayer.DeviceID + " volume to " + ( this.volume * 100).ToString();

int ret = mciSendString( cmd, null, 0, IntPtr.Zero);

Console.WriteLine( cmd);


this.timer_Tick( null, null);

}


/*--------------------------------------------------*/

/* MCI Seek */

/*--------------------------------------------------*/

private void mciSeek( int position)

{

string cmd = "seek " + MusicPlayer.DeviceID + " to " + position.ToString();

int ret = mciSendString( cmd, null, 0, IntPtr.Zero);

Console.WriteLine( cmd);


this.timer_Tick( null, null);

}

}


0 件のコメント:

コメントを投稿