実は、先日 スマホを Android から iPhone に機種変更したんですが、PC上フォルダで管理していたMP3を iTune 経由でコピーしたところ、ただしく認識されなかったので、止む無くそれに対応する機能を追加しました。
今回は、何がどう困ったかという内容と、それに対して何処をどう修正したかという事について解説します。
このように、自分の用途に合わせて機能を追加したり変更できるのも、自作プログラムの強みです。
iTune に曲をドラッグ&ドロップするとバラバラに・・・
私は好きなアーティストのアルバムを丸ごと聞くという事はあまりありません。
多くの場合、「昼用」「夜用」「寝るとき用」などのカテゴリでフォルダを作って、その中にカテゴリに合ったMP3を入れて、カテゴリ単位で聞くことがほとんどです。
例えば以下の様なイメージです。

Androidの場合、フォルダを丸ごと内部メモリにコピーするだけで、メディアプレーヤーがフォルダ内の曲を順次再生してくれました。
iPhoneも同じだと思い、 iTune でフォルダをライブラリにドラッグ&ドロップしたところ、見事に期待を裏切られました。
何と、フォルダ内の曲が数曲づつ、バラバラに認識されてしまったのです。
例えば、【0.最新曲】_JPOP_BGM というフォルダにAKB48、嵐、EXILE、Flowerの曲を複数入れていたのですが、iTuneにドラッグ&ドロップしたところ、下記の様に4つに分割されて認識されました。

正直、愕然としました。
iTune はMP3タグでアルバムを分類していた
よくよく調べてみると、iTuneはMP3タグの「アルバム」で曲を分類していました。
iPhone 側でフォルダ再生が選べれば、それでも良かったんですが、どうもそういう機能は無さそう。
フォルダ再生に対応するプレーヤーソフトを別途インストールする必要があるようです。
ちなみに、PCのフォルダをライトニングケーブル経由でiPhone にコピーするソフトはいくつかありましたが、全て有料っぽいです。
Android だったら、USB接続した時点で内部メモリがフォルダとして認識されるので、コピーすれば良いだけだったんですが、iPhone はこういう仕様ではないようです。
で、これを機会にMP3のタグを正しく設定しようかと思った次第です。
フォルダ名をMP3タグのアルバムにコピーしたい
ということで、フォルダ名をMP3タグにコピーすれば良いのです。

前回作ったMP3タグ編集ツールでフォルダ名のコピーを試みたところ・・・・出来ませんでした。
正確に言うと、正規表現を駆使すれば出来そうなのですが、考えるのが面倒だったのと、この際だからバージョンアップしようかという結論に達しました。
フォーマット欄に フォルダ名が指定できる機能を追加
変更したのは、uxExecCopy_Click イベントハンドラ内の数行です。
前回公開したプロジェクトのuxExecCopy_Click を下記の内容にごっそり置き換えれば、フォーマット欄で {フォルダ名} が使える様になります。
/// <summary>
/// 置換ボタンクリック処理
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void uxExecCopy_Click(object sender, EventArgs e)
{
//対象項目が未入力ならエラーメッセージを表示
if(! uxMp3List.Columns.Contains(uxTargetColumn.Text))
{
MessageBox.Show("対象項目を指定して下さい", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
//フォーマットが未入力ならエラーメッセージを表示
if (uxFormat.Text.Trim() == "")
{
MessageBox.Show("フォーマットを入力して下さい", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
//連番の初期値を設定
int no = 1;
try
{
//DataGridViewに表示されている行をループ処理で取り出す
foreach (DataGridViewRow dgr in uxMp3List.Rows)
{
//フォーマットの中身に{列名}の記述があれば、列の値に置き換える
string str = replace(uxMp3List.Columns, dgr, uxFormat.Text);
//{連番}の記述があれば、連番に置き換える
str = str.Replace("{連番}", string.Format("{0:" + uxNumberFormat.Text + "}", no++));
//フォルダパスの値を\で分割
string[] items = dgr.Cells["ファイルパス"].Value.ToString().Split('\\');
//分割できたかチェック
if(items.Length > 1)
{
//最後から2番目のフォルダ名で置換
str = str.Replace("{フォルダ名}", items[items.Length - 2]);
}
//フォーマット加工した結果を対象項目の列に代入
dgr.Cells[uxTargetColumn.Text].Value = str;
}
//過去に使ったフォーマットならなら、ドロップダウンから一旦削除
string format = uxFormat.Text;
if (uxFormat.Items.Contains(format))
{
//ドロップダウンから削除
uxFormat.Items.Remove(format);
//RemoveするとText部がクリアされるので復旧
uxFormat.Text = format;
}
//ドロップダウンの先頭に登録
uxFormat.Items.Insert(0, format);
}
catch(Exception exp) //例外処理
{
//何らかのエラーが発生した場合、エラー内容を表示
MessageBox.Show(exp.Message, "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
return;
///{列名}の記述を列の値に置き換えるローカル関数
string replace(DataGridViewColumnCollection p_col,DataGridViewRow p_dgvr,string p_str)
{
for(int i = 0;i < p_col.Count;i ++)
{
// "{列名}"の文字列を作成
string l_sour = "{" + p_col[i].Name + "}";
// "{列名}"の文字列を列の値に置換
p_str = p_str.Replace(l_sour, p_dgvr.Cells[i].Value.ToString());
}
return p_str;
}
}
追加したのは35行~43行までの部分です。
//フォルダパスの値を\で分割
string[] items = dgr.Cells["ファイルパス"].Value.ToString().Split('\\');
//分割できたかチェック
if(items.Length > 1)
{
//最後から2番目のフォルダ名で置換
str = str.Replace("{フォルダ名}", items[items.Length - 2]);
}
DataGridVIewの右端にある「ファイルパス」列にMP3ファイルのフルパスが格納されています。
これを取り出して、パスの区切り文字であるバックスラッシュ '\' で分割してあげて、分割出来たら(分割した結果の個数が1より大きかったら)、右から2番目を取り出して{ファイル名} を置き換えています。
右から2番目と言うのは、分割した結果の一番右端にはファイル名が格納されているからです。
今回はファイル名の直上のフォルダ名をアルバム名として使いたかったので、このようにしています。
まとめ
如何でしたでしょうか。
イベントハンドラの一部を書き換えることで、フォルダ名をコピーできるようになりました。
この機能を作ったおかげで、無事 iPhone に曲を認識させることが出来ました。
みなさんも、自分の用途に合わせて自由に修正してお使いください。
いろんな機能を追加していって自作ソフトが成長していくのは楽しいものです。
プログラミングスキルの向上にも役立ちますので、是非チャレンジしてみて下さい。
コメント