2012年3月31日土曜日

日記ちゃん


 4月5日発売。
配信記念4日間限定で450円にて提供いたします。
※通常価格600円
 
 来週か。

2012年3月27日火曜日

CreateDialog + サブクラス化 + RegisterClassEx

ウィンドウプロシージャでthisポを使いたいってんでサブクラス化するんだけど、CreateDialogでウィンドウを作成する場合はどうすりゃいいんじゃろ? と試行錯誤してた。

 結局下のようになった。CreateWindow()みたいにlparamにデータを渡せればスマートなんだけど仕方なし。あとCreateDialog()なのにウィンドウプロシージャを使用するあたりやや気持ち悪いが。

[resource.h]

#pragma once
 
#define APP_CLASS_NAME  TEXT("test")
#define APP_TITLE    TEXT("test")
#define IDD_MAIN    101

[resource.rc]

#include "resource.h"
#include <windows.h>
 
IDD_MAIN DIALOG 0, 0, 310, 210
FONT 9, "MS Pゴシック"
STYLE WS_VISIBLE | WS_POPUPWINDOW
CAPTION APP_TITLE
{}

[main.cpp]

#include <windows.h>
#include "resource.h"
 
 
 
class WindowBase
{
protected:
  /** constructor */
  WindowBase() {}
  /** destructor */
  virtual ~WindowBase() {}
 
  static void attachWnd( HWND hWnd, LONG_PTR myWndData )
  {
    SetWindowLongPtr( hWnd, GWL_USERDATA, myWndData );
    SetWindowLongPtr( hWnd, GWL_WNDPROC, reinterpret_cast<LONG_PTR>(staticWndProc) );
  }
 
public:
  /** 初期化プロシージャ */
  static LRESULT CALLBACK initWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
  {
    if ( uMsg == WM_CREATE )
    {
      LPCREATESTRUCT cs = reinterpret_cast<LPCREATESTRUCT>( lParam );
      WindowBase* wb = static_cast<WindowBase*>( cs->lpCreateParams );
 
      attachWnd( hWnd, reinterpret_cast<LONG_PTR>(wb) );
      
      return wb->wndProc( hWnd, uMsg, wParam, lParam );
    }
    return DefWindowProc( hWnd, uMsg, wParam, lParam );
  }
 
  /** 間接参照プロシージャ */
  static LRESULT CALLBACK staticWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
  {
    return reinterpret_cast<WindowBase*>( GetWindowLongPtr(hWnd, GWL_USERDATA) )->wndProc( hWnd, uMsg, wParam, lParam );
  }
 
  /** オーバーライドして使用するプロシージャ */
  virtual LRESULT wndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
  {
    // サブクラス化でない場合は、デフォルトウィンドウプロシージャを呼び出す
    return DefWindowProc( hWnd, uMsg, wParam, lParam );
  }
};
 
 
 
/**
* Main
*/
class Main : public WindowBase
{
public:
  /**
   * constructor
   */
  Main()
    : m_hWnd( NULL )
  {}
 
  /**
   * destructor
   */
  ~Main() {}
 
 
 
  /**
   * override wndProc
   */
  LRESULT wndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
  {
    switch ( uMsg )
    {
    case WM_CREATE:
      break;
 
    case WM_CLOSE:
      DestroyWindow( hWnd );
      break;
 
    case WM_DESTROY:
      ShowWindow( hWnd, SW_HIDE );
      PostQuitMessage(0);
      break;
    }
 
    return DefWindowProc( hWnd, uMsg, wParam, lParam );
  }
 
 
  static LRESULT CALLBACK dummyProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
  {
    return DefWindowProc( hWnd, uMsg, wParam, lParam );
  }
 
  /**
   * WinMain
   */
  int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd )
  {
    // register
    {
      WNDCLASSEX wc = {0};
      wc.style    = CS_HREDRAW | CS_VREDRAW;
      wc.lpfnWndProc  = dummyProc;
      wc.cbClsExtra  = 0;
      wc.cbWndExtra  = DLGWINDOWEXTRA;
      wc.cbSize    = sizeof( WNDCLASSEX );
      wc.hInstance  = hInstance;
      wc.hIcon    = NULL;
      wc.hIconSm    = NULL;
      wc.hCursor    = LoadCursor( NULL, IDC_ARROW );
      wc.hbrBackground= reinterpret_cast<HBRUSH>( GetStockObject( WHITE_BRUSH ) );
      wc.lpszMenuName  = NULL;
      wc.lpszClassName= APP_CLASS_NAME;
 
      if ( !RegisterClassEx( &wc ) ) return 0;
    }
 
 
    m_hWnd = CreateDialog( hInstance, reinterpret_cast<LPCTSTR>(IDD_MAIN), NULL, NULL );
    if ( !m_hWnd ) return -1;
 
    attachWnd( m_hWnd, reinterpret_cast<LONG_PTR>(this) );
 
    ShowWindow( m_hWnd, SW_SHOWNORMAL );
    SendMessage( m_hWnd, WM_CREATE, 0, 0 );
 
    // message loop
    {
      MSG msg;
      while ( GetMessage(&msg , NULL , 0 , 0) )
      {
        if ( !IsDialogMessage(m_hWnd, &msg) )
        {
          TranslateMessage( &msg );
          DispatchMessage( &msg );
        }
      }
    }
 
 
    return 0;
  }
 
 
private:
  HWND m_hWnd;
};
 
 
 
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpsCmdLine, int nCmdShow)
{
  Main mainWindow;
  return mainWindow.WinMain( hInst, hPrevInst, lpsCmdLine, nCmdShow );
}


 迷う点は二つで、WNDCLASSEX のlpfnWndProcと、CreateDialog()の第4引数 lpDialogFunc。
CreateDialogParam()を使用すればLPARAMに好きなデータを渡せるから、INIT_DIALOGでGWL_USERDATAにthisポを保存する計画だった。
でもWNDCLASSEXに指定するプロシージャはLRESULT CALLBACK wndProc()、いわゆるウィンドウプロシージャで、CreateDialogに指定するのはBOOL CALLBACK wndProc()ってダイアログプロシージャと型が違うのね。
両方設定すべく、reinterpret_castで無理やり型変更して指定するもウィンドウが生成されない問題が出た。

 どちらかのプロシージャ設定でNULLを指定しなければならないようだけど、いろいろ試したが、WNDCLASSEXのプロシージャ設定をNULLにしちゃうとうまく処理できないようだった。というのもダイアログプロシージャのほうはDefWindowProc()とかで汎用処理を行わないから全うに動くはずもない。

2012年3月25日日曜日

ZenStyleM100-CreatePlayList v101


https://skydrive.live.com/redir.aspx?cid=8cd7cf5ea9fbca55&resid=8CD7CF5EA9FBCA55!387&parid=8CD7CF5EA9FBCA55!138&authkey=!ABffr6vVY5sxtMM
size: 7KB

■概要
ZenStyleM100にてフォルダ別にプレイリストを作成する

■使い方
お使いのZenStyleM100のルートフォルダにCreatePlayList101.vbsを置いて実行してください。
ファイル内の outputDirectory および searchDirectory のパスを書き換えれば
お好きな位置で実行することもできます。

Musicフォルダ直下にあるフォルダ名で、PlayListフォルダにプレイリストが出力されます。
(デフォルトの場合)

■使い方(詳しく)
1. お使いのM100のルートフォルダにダウンロードしたCreatePlayList.vbsを置いてください。



2. CreatePlayList.vbsを実行
(windowsならダブルクリックで実行される。ほかは知らん)
確認ウィンドウがでるので良ければ[OK]


3. しばし終わるのを待つ
終わったら[終了]と出ます


その後本体起動時にリストのチェックが入るのか起動時間が長くなります。
気長にお待ちくださいませ。


無事プレイリストの読み込みが完了した

Musicフォルダには以下画像のように配置しています。

完了後のPlayListフォルダはこんな感じに。




■仕様
設定したフォルダパス(デフォではMusic)内にあるフォルダの数だけm3uを作成します。
たとえば、

G:.
├─Music
│ ├─フォルダ1
│ │ ├─01.mp3
│ │ └─02.mp3
│ ├─フォルダ2
│ │ ├─disc1
│ │ │ ├─01.mp3
│ │ │ ├─02.mp3
│ │ │ └─03.mp3
│ │ └─disc2
│ │   ├─01.mp3
│ │   ├─02.mp3
│ │   └─03.mp3
│ └─フォルダ3
├─Pictures
├─Video
├─Recorded
└─Playlist

って構成になっていたら作成されるm3uは
フォルダ1.m3u
フォルダ2.m3u
の2つが、PlayListフォルダに出力されます。
フォルダ2は中にさらにフォルダがありますが、
まとめてフォルダ2.m3uに保存されることになります。
またフォルダ3には曲がないのでフォルダ3.m3uは出力されません。

CreatePlayList.vbsの中身を書き換えることで、
出力先フォルダ、入力フォルダを変更することができます。
デフォルトではPlayListフォルダに出力する設定になっていますが、
既存のプレイリストとごちゃごちゃになるのが気になる方は出力先を変更すると良いでしょう。



' Zen Style M100の曲ファイルをフォルダ別にm3uにして、PlayListに保存するプログラム
' 2012-03-25 ver 1.01
' author sumishiro@gmail.com
' 本プログラムのご利用に際し如何なる損失や損害が発生しても、一切の責任を負いかねます。ご了承ください。
'
' 1012-03-25 ver 1.01
'     フォルダとファイルのタイムスタンプ(作成日時、更新日時)、m3u内のファイルの有無、ファイル数をチェックする機能を追加
' 1012-03-21 ver 1.00
 
 
Option Explicit
 
 
 
Dim outputDirectory
Dim searchDirectory
Dim rootFileName
 
 
 
' m3u出力先。フォルダが存在しないと出力されないようなので注意
outputDirectory = ".\PlayList"
 
 
 
' 調べるディレクトリパス
' このディレクトリにあるフォルダ名でm3uファイルを作成し、
' 各フォルダ内にある音楽ファイルをm3uに突っ込む
' 同名のm3uは上書きされるので注意
searchDirectory = ".\Music"
 
 
 
' searchDirectoryに直接おいてある曲もm3uリストにしたい場合
' 以下に出力m3uファイル名を定義してね
' rootFileName = "root"
 
 
 
 
Dim fso
Set fso = WScript.CreateObject("Scripting.FileSystemObject")
 
 
 
' 指定m3uファイルをチェック。
' ファイルがすべて存在してm3uとして問題がなければTrueを返す。
' 参照引数rLineNumに該当ファイルの行数(記述されたファイル数)を入れるが、
' 存在しないファイルがあった場合は最後までカウントしないので注意
Function checkPlayList( fileObj, rLineNum )
  Dim file
  Set file = fso.OpenTextFile( fileObj, 1, False, -1 )
 
  ' C: D:といったドライブ名を取得
  Dim driveName
  driveName = Left( searchDirectory, InStr(searchDirectory, "\") )
 
  rLineNum = 0
  Do Until file.AtEndOfStream=True
    Dim strLine
    strLine = file.ReadLine()
 
    If fso.FileExists(driveName & strLine)=False Then
      checkPlayList = False
      Exit Function
    End If
    
    rLineNum = rLineNum + 1
  Loop
 
  file.Close()
  checkPlayList = True
End Function
 
 
 
' m3uの作成が必要かどうかチェック。
' 指定した日時よりファイル日時のほうが新しければFalse, それ以外はTrue
' @return 作成の必要があるならばTrue
Function needCreatePlayListFile( filePath, dateTime, musicFileNum )
  If fso.FileExists(filePath) Then
    ' m3uが指定時刻より新しいかチェック。新しければ関数終了
    If fso.GetFile(filePath).DateLastModified < dateTime Then
      needCreatePlayListFile = True
      Exit Function
    End If
 
    ' m3uファイルの妥当性チェック
    Dim lineNum
    If checkPlayList(fso.GetFile(filePath), lineNum) Then
      ' 数チェック
      If lineNum=musicFileNum Then
        needCreatePlayListFile = False
        Exit Function
      End If
    End If
 
  End If
 
  needCreatePlayListFile = True
End Function
 
 
 
' 引数date, file.更新日時, file.作成日時の3つの中から一番最新の日時を返す
' fileにはFileオブジェクトかFolderオブジェクト
Function getMostNewDate( file, date )
  Dim tmp
  tmp = date
 
  If file.DateLastModified > tmp Then
    tmp = file.DateLastModified
  End If
 
  If file.DateCreated > tmp Then
    tmp = file.DateCreated
  End If
 
  getMostNewDate = tmp
End Function
 
 
 
' 指定ファイル名とoutputDirectoryからm3uファイルのパスを作成
Function createM3UFilePath( fileName )
  createM3UFilePath = fso.BuildPath( outputDirectory, fileName & ".m3u" )
End Function
 
 
 
' m3uファイル作成
' @param fileNameには拡張子はつけない
' あらかじめ設定した出力先にfileNameを結合してUNICODEで保存
Function createM3UFile( filePath, fileData )
  If Len(fileData) > 0 Then
    Dim file
    Set file = fso.OpenTextFile( filePath, 2, True, -1 )
    file.Write( fileData )
    file.Close
 
    createM3UFile = True
 
    WScript.Echo "create " & fso.GetAbsolutePathName(filePath)
  Else
    createM3UFile = False
  End If
End Function
 
 
 
' パスからドライブ名を除く
' [c:\folder\folder\file.ext]->[\folder\folder\file.ext]
Function delDriveName( filePath )
  Dim pos
  pos = InStr( filePath, "\" )
 
  Dim strLen
  strLen = Len( filePath )
 
  Dim ret
  ret = Right( filePath, strLen-pos+1 )
 
  delDriveName = ret
End Function
 
 
 
' ディレクトリ内にあるwmv, mp3, wav, ogg ファイルのパスをfileDataに列挙。
' そのときC:などのドライブ名は削除し\Music~といったファイルパスに変換されて保存する
Function scanMusicFile( dirObj, fileData, mostNewDate )
  Dim fileNum
  fileNum = 0
  
  Dim fileObj
  For Each fileObj In dirObj.Files
    Dim ext
    ext = LCase( fso.GetExtensionName(fileObj) )
    If ext="wmv" Or ext="mp3" Or ext="wav" Or ext="ogg" Then
      mostNewDate = getMostNewDate( fileObj, mostNewDate )
 
      fileData = fileData & delDriveName( fileObj ) & vbNewLine
      fileNum = fileNum + 1
    End If
  Next
  
  scanMusicFile = fileNum
End Function
 
 
 
' ディレクトリ走査
' 音楽ファイルへのパスをあつめるところまで
Sub scanDirectory( dirObj, fileData, mostNewDate, musicFileNum )
  mostNewDate = getMostNewDate( dirObj, mostNewDate )
 
  Dim subDirObj
  For Each subDirObj In dirObj.SubFolders
    Call scanDirectory( subDirObj, fileData, mostNewDate, musicFileNum )
  Next
 
  musicFileNum = musicFileNum + scanMusicFile( dirObj, fileData, mostNewDate )
End Sub
 
 
 
' searchDirectoryに定義したパスを走査
Sub scanRootDirectory( dirPath )
  Dim src
  Set src = fso.GetFolder( dirPath )
 
  Dim filePath
 
  Dim subDirObj
  For Each subDirObj In src.SubFolders
    Dim fileData
    Dim mostNewDate
    Dim musicFileNum
 
    fileData = ""
    mostNewDate = subDirObj.DateLastModified
    musicFileNum = 0
    Call scanDirectory( subDirObj, fileData, mostNewDate, musicFileNum )
    
    filePath = createM3UFilePath( fso.GetFileName(subDirObj) )
    If needCreatePlayListFile(filePath, mostNewDate, musicFileNum) Then
      Call createM3UFile( filePath, fileData )
    End If
  Next
 
  ' searchDirectoryにある曲をm3u出力する
  If Len(rootFileName) > 0 Then
    fileData = ""
    mostNewDate = src.DateLastModified
    musicFileNum = scanMusicFile( src, fileData, mostNewDate )
    
    filePath = createM3UFilePath( rootFileName )
    If needCreatePlayListFile(filePath, mostNewDate, musicFileNum) Then
      Call createM3UFile( filePath, fileData )
    End If
  End If
End Sub
 
 
 
' 処理の開始
outputDirectory = fso.GetAbsolutePathName( outputDirectory )
searchDirectory = fso.GetAbsolutePathName( searchDirectory )
 
Dim message
message = "処理を開始します" & vbNewLine & "input = " & searchDirectory & vbNewLine & "output = " & outputDirectory 
 
If MsgBox(message, 1, "確認")=1 Then
  Call scanRootDirectory( searchDirectory )
  MsgBox("終了")
End If


プレイリストの更新が必要ならば書き換えるのだけど、
フォルダのタイムスタンプは曲ファイルを削除やコピーしたときに更新されないので、
フォルダだけでなく曲ファイルのタイムスタンプも見る必要があった。
曲ファイルのタイムスタンプもコピーや削除では更新されないので、
結局、既存のプレイリストがあれば中身を見て、
パスがさすファイルの有無と、曲数が一致しているかをみることで
プレイリストを更新するかどうかを判断した。
全リスト書き換えるより精神衛生はいいが、処理時間は増えたような気がする。

2012年3月24日土曜日

日記ちゃんCheckPlayList

変更のあったものだけプレイリストの書き換えを行うよう修正しようと思ったのだけど、
フォルダの名前変更では更新日時が変更されずスルーしてしまったり、
曲ファイルを削除しただけではフォルダの更新日時が変更されずスルーされたりと、
なかなかうまいこといかない。(削除だとファイルの更新日時もチェックできない。当然だが)
プレイリストの中身を見てファイルがちゃんと存在するかチェックしてやる必要があるのかもしれないが、
いまですら結構処理時間がかかってるだけに踏ん切りがつかないのが現状だ。

本体の起動時にプレイリストをチェックしている節がみられるが、
特にプレイリスト事体編集しているわけではないようだ。
m3uをみてファイルの有無をチェックするプログラムを作ってもいいのかもしれない。



できた。
画像ではIkaruga.m3uの10行目に記述されたパスが存在していない。


https://skydrive.live.com/redir.aspx?cid=8cd7cf5ea9fbca55&resid=8CD7CF5EA9FBCA55!386&parid=8CD7CF5EA9FBCA55!138&authkey=!ADW8M0BZY_1qdTA
CheckPlayList.vbs
size: 2KB

■概要
 ZenStyleM100内のプレイリストに記述されている曲ファイルの有無をチェックする

■使い方
お使いのZenStyleM100、あるは親類のルートフォルダに
ダウンロードしたCheckPlayList.vbsを置いて実行してください。
あるいはファイル内のplayListDirをプレイリストのフォルダパスに書き換えて実行してください。

Zen Style M100ではプレイリスト内のパスを
\dir\dir\file.mp3
といったようにドライブ名を除去して記述するので、
チェックの際はドライブ名を付けてからファイルの有無確認をする必要があるぐらい。

' 指定フォルダ内のm3uファイルに記述されたファイルパスをチェック。
' ファイルが存在しなければ、行数と記述内容を出力する
' ただしZenStyleM100などのドライブ名のないパスを使用したプレイリストに限定
' auther sumishiro@gmail.com
 
Option Explicit
 
 
 
 
Dim playListDir
playListDir = ".\PlayList"
 
 
 
 
 
 
Dim fso
Set fso = WScript.CreateObject("Scripting.FileSystemObject")
 
 
 
 
 
' 指定m3uファイルをチェック。存在しないファイルがあれば標準出力
Sub checkPlayList( fileObj )
  Dim file
  Set file = fso.OpenTextFile( fileObj, 1, False, -1 )
 
  Dim outputStr
  outputStr = ""
 
  Dim lineNo
  lineNo = 1
  Do Until file.AtEndOfStream=True
    Dim strLine
    strLine = file.ReadLine()
    If fso.FileExists(fileObj.Drive & strLine)=False Then
      outputStr = outputStr &  "(" & lineNo & ") " & strLine & vbNewLine
    End If
    lineNo = lineNo + 1
  Loop
 
  file.Close()
 
  ' エラーがあればファイル名と行数、行内容などの情報を出力
  If Len(outputStr)>0 Then
    outputStr = "[" & fileObj & "]" & vbNewLine & outputStr
    WScript.Echo outputStr
  End If
End Sub
 
 
 
' 指定フォルダ以下を走査。m3uがあればチェック
Sub searchDir( dir )
  Dim subDir
  For Each subDir In dir.SubFolders
    Call searchDir( subDir )
  Next
 
  Dim file
  For Each file In dir.Files
    Dim ext
    ext = LCase( fso.GetExtensionName(file) )
    If ext="m3u" Then
      Call checkPlayList( file )
    End If
  Next
End Sub
 
 
 
Call searchDir( fso.GetFolder(playListDir) )
 

2012年3月21日水曜日

日記ちゃん Zen Style M100


 10年ほど使っているプレイヤーがフル充電から30分で電池切れするので、
適当にこれ買ったのだけど、これがなかなか癖の強いやつなんだ。
この子、曲をタグで管理するらしく、
いままでフォルダに分けるぐらいしかしてなかったから全部一緒くたにされてしまい目当ての曲を探すのが、もー大変! 
 そこでフォルダ別のプレイリストを作成するプログラムを書いた。
これなら曲を探しやすいし、管理方法も変えずにすむって寸法。


https://skydrive.live.com/redir.aspx?cid=8cd7cf5ea9fbca55&resid=8CD7CF5EA9FBCA55!385&parid=8CD7CF5EA9FBCA55!138&authkey=!ALp5f6JArx9PAW8
 CreatePlayList.vbs
 size: 4KB
 
 
 
■使い方
1. お使いのM100のルートフォルダにダウンロードしたCreatePlayList.vbsを置いてください。

 

2. CreatePlayList.vbsを実行
(windowsならダブルクリックで実行される。ほかは知らん)
確認ウィンドウがでるので良ければ[OK]

 
3. しばし終わるのを待つ
終わったら[終了]と出ます

 
 その後本体起動時にリストのチェックが入るのか起動時間が長くなります。
気長にお待ちくださいませ。
 

 無事プレイリストの読み込みが完了した
 
 Musicフォルダには以下画像のように配置しています。

 完了後のPlayListフォルダはこんな感じに。

 
 
 
■仕様
 設定したフォルダパス内にあるフォルダの数だけm3uを作成します。
たとえば、

G:.
├─Music
│ ├─フォルダ1
│ │ ├─01.mp3
│ │ └─02.mp3
│ ├─フォルダ2
│ │ ├─disc1
│ │ │ ├─01.mp3
│ │ │ ├─02.mp3
│ │ │ └─03.mp3
│ │ └─disc2
│ │   ├─01.mp3
│ │   ├─02.mp3
│ │   └─03.mp3
│ └─フォルダ3
├─Pictures
├─Video
├─Recorded
└─Playlist
 
って構成になっていたら作成されるm3uは
フォルダ1.m3u
フォルダ2.m3u
の2つが、PlayListフォルダに出力されます。
 フォルダ2は中にさらにフォルダがありますが、
まとめてフォルダ2.m3uに保存されることになります。
 またフォルダ3には曲がないのでフォルダ3.m3uは出力されません。
 
 CreatePlayList.vbsの中身を書き換えることで、
出力先フォルダ、入力フォルダを変更することができます。
デフォルトではPlayListフォルダに出力する設定になっていますが、
既存のプレイリストとごちゃごちゃになるのが気になる方は出力先を変更すると良いでしょう。
 以下vbsファイル内容

' Zen Style M100の曲ファイルをフォルダ別にm3uにして、PlayListに保存するプログラム
' 2012-03-21 ver 1.00
' author sumishiro@gmail.com
' 本プログラムのご利用に際し如何なる損失や損害が発生しても、一切の責任を負いかねます。ご了承ください。
 
Option Explicit
 
 
 
Dim outputDirectory
Dim searchDirectory
Dim rootFileName
 
 
 
' m3u出力先。フォルダが存在しないと出力されないようなので注意
outputDirectory = ".\Playlist"
 
 
 
' 調べるディレクトリパス
' このディレクトリにあるフォルダ名でm3uファイルを作成し、
' 各フォルダ内にある音楽ファイルをm3uに突っ込む
' 同名のm3uは上書きされるので注意
searchDirectory = ".\Music"
' searchDirectory = "./"
 
 
 
' searchDirectoryに直接おいてある曲もm3uリストにしたい場合
' 以下に出力m3uファイル名を定義してね
' rootFileName = "root"
 
 
 
 
Dim fso
Set fso = WScript.CreateObject("Scripting.FileSystemObject")
 
 
 
' m3uファイル作成
' あらかじめ設定した出力先にfileNameを結合してUNICODEで保存
Function createM3UFile( fileName, fileData )
  If Len(fileData) > 0 Then
    Dim filePath
    filePath = fso.BuildPath( outputDirectory, fileName & ".m3u" )
 
    Dim file
    Set file = fso.OpenTextFile( filePath, 2, True, -1 )
 
    file.Write( fileData )
 
    file.Close
    createM3UFile = True
  Else
    createM3UFile = False
  End If
End Function
 
 
 
' パスからドライブ名を除く
' [c:\folder\folder\file.ext]->[\folder\folder\file.ext]
Function delDriveName( filePath )
  Dim pos
  pos = InStr( filePath, "\" )
 
  Dim strLen
  strLen = Len( filePath )
 
  Dim ret
  ret = Right( filePath, strLen-pos+1 )
 
  delDriveName = ret
End Function
 
 
 
 
' ディレクトリ内にあるwmv, mp3, wav, ogg, flacファイルのパスをfileDataに列挙。
' そのときC:などのドライブ名は削除し\Music~といったファイルパスに変換されて保存する
Sub scanMusicFile( dirPath, fileData )
  Dim src
  Set src = fso.GetFolder( dirPath )
 
  Dim filePath
  For Each filePath In src.Files
    Dim ext
    ext = LCase( fso.GetExtensionName(filePath) )
    If ext="wmv" Or ext="mp3" Or ext="wav" Or ext="ogg" Or ext="flac" Then
      fileData = fileData & delDriveName( filePath ) & vbNewLine
    End If
  Next
End Sub
 
 
 
' ディレクトリ走査
' 音楽ファイルへのパスをあつめるところまで
Sub scanDirectory( dirPath, fileData )
  Dim src
  Set src = fso.GetFolder( dirPath )
 
  Dim subDirPath
  For Each subDirPath In src.SubFolders
    Call scanDirectory( subDirPath, fileData )
  Next
 
  Call scanMusicFile( dirPath, fileData )
End Sub
 
 
 
' searchDirectoryに定義したパスを走査
Sub scanRootDirectory( dirPath )
  Dim src
  Set src = fso.GetFolder( dirPath )
 
  Dim subDirPath
  For Each subDirPath In src.SubFolders
    Dim fileData
    fileData = ""
    Call scanDirectory( subDirPath, fileData )
 
    Dim fileName
    fileName = fso.GetFileName( subDirPath )
    Call createM3UFile( fileName, fileData )
  Next
 
  ' searchDirectoryにある曲をm3u出力する
  If Len(rootFileName) > 0 Then
    fileData = ""
    Call scanMusicFile( dirPath, fileData )
    Call createM3UFile( rootFileName, fileData )
  End If
End Sub
 
 
 
' 処理の開始
Dim message
message = "処理を開始します" & vbNewLine & "output=" & fso.GetAbsolutePathName(outputDirectory) & vbNewLine & "input=" & fso.GetAbsolutePathName(searchDirectory)
 
If MsgBox(message, 1, "確認")=1 Then
  Call scanRootDirectory( searchDirectory )
  MsgBox("終了")
End If

 
 普段は全曲シャッフルで聞くから問題ないんだけど、
ときどき狙って聞きたくなる。そんな時用。
製作時間二日。WSHは初めてだったが資料が豊富で学びやすい印象だ。
 M100はoggの再生が一応可能だが、
バッファリングがうまくいってないのかぶつぶつ途切れがちになるし、
ボタンの反応も悪くなるので使用はあまりお勧めできない。
自分は普段ogg使ってたけど、mp3に変換しなおした。mp3なら快適。
oggでもディスプレイが表示されてないときはぼちぼち再生可能なようだが。
 指紋がかなりつくが気にしたら負けだ。
 
■関連
生産がす: ZenStyleM100-CreatePlayList v102
生産がす: 日記ちゃんCheckPlayList

2012年3月11日日曜日

日記ちゃん

現在のActiveWindowRecorderの仕様では、
ウィンドウタイトルの保存に256Byte使っていてメモリに無駄がある。
そこでウィンドウタイトルの長さ分だけメモリを確保して使用メモリ量を減らそうと考えた。
newで確保する仕様でいったん組んだんだけど、これはこれでメモリが断片化しそうだ。
 一日分のウィンドウタイトルのログは追記されていくだけで途中で削除や挿入はされないから
vectorのpush_backを使えば、メモリを一箇所に固められ、
保存するときもそのまま吐き出せばいいから便利ね! 
と思いついて実装しているがドはまりした。
難航なう。
 
 解決した。メモリ管理部分の記述ミスとかありがち。

2012年3月9日金曜日

日記ちゃん虫姫さま360


 アレンジはアレンジのままなのね。
ノービス追加とグラ書き直しがPS2版との違いになる。
初回特典に1.5。アレンジ曲枠も1.5に使われるのかも。
 

 マキシマムも7日に発売され
youtubeにもいくつか動画がすでにアップされてる模様。
弾が大きいからか地味に違和感を覚えるが携帯機の宿命だろうか。

2012年3月2日金曜日

日記ちゃん

std::vector<int> v;
...
v.push_back( 100 );
int* p = &v[0];
v.push_back( 110 );
*p = 120;

 みたいなことして死んでた。
push_backで追加して、ひょっこりバッファが確保されなおされると
当然アドレスが変わってるので死ぬっつーオチ。