概要

ドラッグ&ドロップされたCSVファイルの内容にしたがって、複数のWMAファイルのタイトル、アルバムタイトル、アーティスト等を変更します。
元になるCSVファイルは、複数のWMAファイルアーティスト名・タイトルをCSVファイルに出力するGUIプログラム(32/64bit) で作成し、Excel等で編集して保存したものを使います。
様々なアーティストが含まれているアルバム等の変更に使えます。
本ソフト起動後、CSVファイルをドラッグ&ドロップしOKボタンをクリックするとファイル等を変更します。
CSVファイルの様式は以下のとおりです。

CSVファイルの例

,で列が区切られています。列の順番はCSVファイルの先頭行のとおりです。
ファイル名,トラック,タイトル,参加アーティスト,アーティスト,アルバム,フルパス
09 ~interlude~.wma,9,~interlude~,島谷ひとみ,島谷ひとみ,ヘネシー,D:\09 ~interlude~.wma
10 やさしいキスの見つけ方.wma,10,やさしいキスの見つけ方,島谷ひとみ,島谷ひとみ,ヘネシー,D:\10 やさしいキスの見つけ方.wma
11 freeze~失われた夏の日~.wma,11,freeze~失われた夏の日~,島谷ひとみ,島谷ひとみ,ヘネシー,D:\11 freeze~失われた夏の日~.wma
12 Hello!.wma,12,Hello!,島谷ひとみ,島谷ひとみ,ヘネシー,D:\12 Hello!.wma

テスト環境

コンパイラ

Visual C++ 2008/2013 Express 32/64bit UNICODE

実行環境

Windows XP Professional Service Pack 3 32bit(Virtual Box上の仮想マシーン)
Windows 7 Enterprise Service Pack 1 64bit

動作例

本プログラムの実行状態

プログラムソースの概要

gwmalist.cpp

_tWinMain

起動前にドラッグ&ドロップされた場合、そのファイル名を保存します。その後、ダイアログボックスを表示します。

DlgProc1

ダイアログボックスの初期化時にDlg1Proc関数にWM_INITDIALOGメッセージが発生するので、起動時にファイル名が指定されている場合リスとボックスに登録します。されていない場合は、ドラッグ&ドロップを許可します。
ドラッグ&ドロップ
本プログラム起動時に引数があった場合は、リストボックスにその内容を設定します。 ファイルがドラッグ&ドラッグされるとDlg1Proc関数にWM_DROPFILESメッセージが発生するので、DragQueryFile関数で最初にファイルの個数を取得し、次にファイル名を取得します。
取得されたファイル名をリスとボックスに登録します。
OKボタンクリック時
ボタンがクリックされると、DlgProc1関数にWM_COMMANDメッセージが発生するので、OKボタンのメッセージの場合、ダイアログボックスのリスとボックスよりファイル名を取得しCSVファイルを開きます。
CSVファイルを1行ずつ読み込みget_csv関数でカンマごとに区切ります。
wma_title_chg関数でタイトル等を変更します。

wma_title_chg

SetAttributeByName APIでWMAファイルのタイトル等を変更します。

ソースコード

gwmacsvtest.cpp

// ドラッグ&ドロップされたCSVファイルを元に複数のWMAファイルのタイトル等を一括変換する。

#include <windows.h>
#include <stdio.h>
#include <wmsdk.h>
#include <tchar.h>
#include "resource.h"

#pragma comment(lib,"wmvcore.lib")

enum CSV_INDEX{	FNAME=0,TRACK,TITLE,AUTHOR,ALBUM_ARTIST,ALBUM_TITLE,FULLPASS };

//	ダイアログボックスプロシージャー
LRESULT CALLBACK DlgProc1(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);

// WMAファイルのタイトル・アルバムタイトル・アーティスト名等を変更
bool wma_title_chg(IWMMetadataEditor* pEditor,TCHAR** argv);

// CSVファイルの読み込み
int get_csv(TCHAR* buf,TCHAR** token);

TCHAR* file=0;

int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPreInst,TCHAR* lpszCmdLine, int nCmdShow){
	TCHAR f[MAX_PATH];
	if(lpszCmdLine[0]){
		if(lpszCmdLine[0]==_T('\"')){
			_tcscpy_s(f,sizeof(f)/sizeof(TCHAR),lpszCmdLine+1);
			f[ _tcslen(f) -1]=_T('\0');
			file=f;
		}else
			file=lpszCmdLine;
	}
	if(DialogBox(hInstance, TEXT("DLG1"), 0, (DLGPROC)DlgProc1)){

	}
	return 0;
}

//	ダイアログボックスプロシージャー

LRESULT CALLBACK DlgProc1(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam){
	TCHAR buf[1024];
	char sjis[2048];
	TCHAR* token[16];
	TCHAR csv_file[MAX_PATH*2];
	HDROP hDrop;
	UINT fmax;
	HRESULT hr;
	IWMMetadataEditor* pEditor=NULL;

	int	i,n;
	FILE* fp;
	switch (msg) {
		case WM_INITDIALOG:{
			if(file){
				SendMessage(GetDlgItem(hDlg,IDC_LISTBOX1) , LB_ADDSTRING , 0 , (LPARAM)file);
				EnableWindow(GetDlgItem(hDlg,IDC_LABEL1),FALSE);
				EnableWindow(GetDlgItem(hDlg,IDC_LISTBOX1),FALSE);
			}else
				DragAcceptFiles(hDlg, TRUE);
			SetWindowText(GetDlgItem(hDlg,IDC_EDIT_DIR) , _TEXT("C:"));
			return TRUE;
		}
		case WM_DROPFILES:
			hDrop = (HDROP)wParam;
			fmax = DragQueryFile((HDROP)wParam, 0xFFFFFFFF, NULL, 0);
			for(i = 0; i < (int)fmax; i++) {
				DragQueryFile(hDrop, i, buf, sizeof(buf)/sizeof(TCHAR));
				SendMessage(GetDlgItem(hDlg,IDC_LISTBOX1) , LB_ADDSTRING , 0 , (LPARAM)buf);
			}
			DragFinish(hDrop);
			fmax=(UINT)SendMessage(GetDlgItem(hDlg,IDC_LISTBOX1) ,LB_GETCOUNT,0,0);
			break;
		case WM_COMMAND:
			switch (LOWORD(wParam)) {
				case IDOK:
					SendMessage(GetDlgItem(hDlg, IDC_LISTBOX1), LB_GETTEXT, 0, (LPARAM)csv_file);
					if(_tfopen_s(&fp,csv_file,_TEXT("r"))==0){
						hr = WMCreateEditor(&pEditor);	// オブジェクトを作成
						n=0;
						while( fgets(sjis,sizeof(sjis),fp) ){
							MultiByteToWideChar(932,0,sjis,-1,buf,sizeof(buf)/sizeof(TCHAR));
							if(0<n++){
								n=get_csv(buf,token);
								wma_title_chg(pEditor,token);
								SendMessage(GetDlgItem(hDlg,IDC_LISTBOX2) , LB_ADDSTRING , 0 , (LPARAM)token[FULLPASS]);
							}
						}
						fclose(fp);
						MessageBox(hDlg,_TEXT("変換が終了しました"),_TEXT("メッセージ"),MB_OK);
					}
					EndDialog(hDlg, TRUE);
					return TRUE;
				case IDCANCEL:
					EndDialog(hDlg,FALSE);
					return FALSE;
				default:
					return FALSE;
			}
			default:
				return FALSE;
	}
	return TRUE;
}


// WMAファイルのタイトル・アルバムタイトル・アーティスト名等を変更

/* argv[n]
n:内容
0:ファイル名
1:トラック
2:タイトル
3:参加アーティスト
4:アーティスト
5:アルバム
6:フルパス
*/


bool wma_title_chg(IWMMetadataEditor* pEditor,TCHAR** argv){
	bool flag=true;
	HRESULT hr;
	IWMHeaderInfo3* pHeaderInfo=NULL;

	hr=pEditor->Open(argv[FULLPASS]);
	pEditor->QueryInterface(IID_IWMHeaderInfo3,(void**)&pHeaderInfo);
	if(FAILED(hr)){
		MessageBox(0,argv[FULLPASS],_TEXT("ファイルが開けません"),MB_OK);
		return false;
	}
	WORD wStreamNum = 0;
	WMT_ATTR_DATATYPE Type;
	WORD cbLength=0;

	TCHAR* getname;
	TCHAR* pwszTitle;

//	タイトルを変更
	Type=WMT_TYPE_STRING;
	getname=_TEXT("Title");
	pwszTitle=argv[TITLE];
	cbLength=(WORD)_tcslen(pwszTitle)*sizeof(TCHAR);
	hr = pHeaderInfo->SetAttribute( wStreamNum, getname, Type,(BYTE *) pwszTitle, cbLength );

//	参加アーティストを変更
	Type=WMT_TYPE_STRING;
	getname=_TEXT("Author");
	pwszTitle=argv[AUTHOR];
	cbLength = (WORD)_tcslen(pwszTitle)*sizeof(TCHAR);
	hr = pHeaderInfo->SetAttribute( wStreamNum, getname, Type,(BYTE *) pwszTitle, cbLength );

//	アルバムアーティストを変更
	Type=WMT_TYPE_STRING;
	getname=_TEXT("WM/AlbumArtist");
	pwszTitle=argv[ALBUM_ARTIST];
	cbLength = (WORD)_tcslen(pwszTitle)*sizeof(TCHAR);
	hr = pHeaderInfo->SetAttribute( wStreamNum, getname, Type,(BYTE *) pwszTitle, cbLength );

//	アルバムタイトルを変更
	Type=WMT_TYPE_STRING;
	getname=_TEXT("WM/AlbumTitle");
	pwszTitle=argv[ALBUM_TITLE];
	cbLength = (WORD)_tcslen(pwszTitle)*sizeof(TCHAR);
	hr = pHeaderInfo->SetAttribute( wStreamNum, getname, Type,(BYTE *) pwszTitle, cbLength );

//	トラック番号を変更
	Type = WMT_TYPE_STRING;
	getname=_TEXT("WM/TrackNumber");
	pwszTitle=argv[TRACK];
	cbLength = (WORD)_tcslen(pwszTitle)*sizeof(TCHAR);
	hr = pHeaderInfo->SetAttribute(wStreamNum, getname, Type, (BYTE *)pwszTitle, cbLength);

	pHeaderInfo->Release();
	pEditor->Flush();
	return flag;
}

// CSVファイルの読み込み
int get_csv(TCHAR* buf,TCHAR** token){
	TCHAR* p=buf;
	bool dc_f=false;	//	ダブルコーテーションで開始している場合はtrue
	int n=0;
	if(p[0]!=_T('\"')){
		token[0]=p;
		++n;
	}

	while(*p){
		switch(*p){
			case _T('\"'):
				if(dc_f==false){	//	単語の開始
					token[n]=p+1;
					dc_f=true;
				}else{				//	単語の終了
					dc_f=false;
					++n;
				}
				*p=_T('\0');
				break;
			case _T(','):
				if(dc_f==false){	//	ダブルコーテーションの中のカンマでない
					if(p[1]!=_T('\"')){
						token[n]=p+1;
						++n;
					}
					*p=_T('\0');
				}
				break;
			case _T('\r'):
			case _T('\n'):
				*p=_T('\0');
				break;

		}
		++p;
	}
	token[n]=0;
	return n;
}

resource

#define IDC_LABEL1 2001
#define IDC_EDIT_DIR 2002
#define IDC_LISTBOX1 2003
#define IDC_LISTBOX2 2004

resource.rc

#include <windows.h>
#include "resource.h"


DLG1 DIALOG DISCARDABLE  0, 0, 380, 197
STYLE DS_MODALFRAME | WS_POPUP
CAPTION "CSVファイルで指定された内容でWMAファイルを一括変更"
FONT 9, "MS Pゴシック"
BEGIN
	CONTROL "", IDC_LISTBOX1, "LISTBOX", WS_CHILD | WS_VISIBLE | WS_VSCROLL | LBS_DISABLENOSCROLL , 7, 26, 366, 32
	LTEXT			"ここへCSVファイルをドラッグドロップしてください",IDC_LABEL1,7,7,222,10
	
	CONTROL "変換ファイル名", -1, "STATIC", WS_CHILD | WS_VISIBLE | SS_NOTIFY, 7, 63, 64, 18
	CONTROL "", IDC_LISTBOX2, "LISTBOX", WS_CHILD | WS_VISIBLE | WS_VSCROLL | LBS_DISABLENOSCROLL , 7, 82, 366, 87

	DEFPUSHBUTTON	"OK(&O)",IDOK,115,176,50,14
	PUSHBUTTON	"キャンセル(&C)",IDCANCEL,225,176,50,14
END

実行ファイルとソースファイルのダウンロード