Volo di notte

お勉強の成果メモや日常のこと

夜間飛行へ移行中です

 

WindowsにSWIG導入

SWIG (Simplified Wrapper and Interface Generator) は、 C/C++ で書かれたプログラムやライブラリをPythonJavaなどのスクリプト言語から使えるようにするためのツール。PybindやCythonなど、類似品もありますが、2次元の物理エンジンpybox2dがSwig依存でしたので導入。

MINGW+MSYSの導入

まずSWIGをビルドする環境を整えます。

おおよその流れはこちら ⇒ MinGW+MSYSのインストール(2014年5月) | The Textbook of RayTracing @TDU

  • g++
  • MinGW AutoTools(autoconf, automake)
  • MYSYS ( bison / flex / tar / gzip / bzip2 / base / autoconf, automake)

は必ず必要なのでチェックを忘れないようにしましょう.

また、環境変数のPathに

の追加を忘れないように!

SWIGとPCREの準備

  1. Githubからswigをクローン (C:\MinGW\msys\1.0\home[ユーザー名]に展開)
  2. ~/Swig/直下にPCREからダウンロードしてきたtarファイルを置く (pcre-8.39.tar.gzまたはpcre-8.39.tar.bz2など)

SWIG/PCREのビルドとインストール

前項の続きから、

  1. “C:\MinGW\msys\1.0\msys.bat"を起動
  2. ~/Swig/Tools/pcre-build.shを実行し、PCREをビルド
  3. ~/Swig/autogen.shを実行⇒configureが生成される
  4. ~/Swig/configureを実行
  5. makeでビルド [make; make install]
$ cd ~/Swig
$ ~/Swig/Tools/pcre-build.sh
$ ~/Swig/autogen.sh
$ ./configure
$ make
$ make install

これで、C:\MinGW\msys\1.0\home[ユーザー名]\swig.exeが吐き出されるので、パスのとおる所に移せばインストール完了。 とりえあえず、C:\MinGW\binにコピーしておきました。

FAQ的な

Error: Unknown directive が出る

Error: Unknown directive ‘%exception'や Error: Unknown directive ’%pythoncode'が吐き出される場合ですが、~/Swig/Lib/の中身が参照できるところに入っていますか?
下記いずれかで直ると思います。

  1. make installを忘れない
  2. swig.exeからの相対パスが./Lib/になる場所にLib以下をコピー
  3. C:\MinGW\msys\1.0\local\share\swig\3.0.11以下にLibをコピー

参考の記事:// Swigが参照するパスについて

SWIG Library

Configure中にsyntax error near unexpected token ‘fi'がでる

syntax error near unexpected token ‘fi’ · Issue #815 · swig/swig · GitHub

環境によっては出るようです。

Line 5855 and line 5975 have “else” tokens that should be removed.

とあるようにfiの直前のelseを消しましょう。空のelseがあるのが良くありません。

代替手段(2017-03-01追記)

Anacondaでもswigの準備があるようです

conda install swig

いろいろ苦労したのがコマンド1つで解決

[Python] タスクトレイ アイコンのツールチップ テキストを取得する

タスクトレイ(通知領域)に収められているアイコンのツールチップには、タスク自動化などで使える情報がたくさんあります。 例えばGoogleフォトバックアップでは「写真100枚をバックアップしました」などとお知らせしてくれます。

これをPythonで取得して使えるようなlist形式にします。

ツールチップのイメージ

f:id:Chachay:20161004215724p:plain

2つの通知領域

Windows 7以降には、常時表示される通知アイコンと通常隠れていて表示をOn/Offできるものがあります。

(それぞれの切り替えには下記を参照してください)

Windows 10 タスクバーの通知領域のアイコンを非表示にする

それぞれのアイコンのツールチップは別々のWindowにぶら下がっており、Spy++などでハンドルを見ると

常時表示される通知領域
Shell_TrayWnd > TrayNotifyWnd > SysPager > ToolbarWindow32 以下の"ボタン"としての性格
通常非表示の通知領域
NotifyIconOverflowWindow > ToolbarWindow32 以下の"ボタン"としての性格

を持つことがわかります。

ツールチップテキストの取得

WindowsAPIをふんだんに使うので、まずPython for Windows Extensionsが必要になります。Anacondaの人は、最初から入っていると思います。

ツールバーのWindowハンドルをFindWindow/FindWindowExで取得したら、 あとはメモリからテキストを読み込んでいくだけの簡単なお仕事になります。

# -*- coding: utf-8 -*-
import win32gui, win32process, win32api, win32con
import ctypes, copy

PAGE_READWRITE = 0x04
MEM_COMMIT     = 0x1000
MEM_RESERVE    = 0x2000
MEM_RELEASE    = 0x8000
TB_BUTTONCOUNT = 0x418
TB_GETBUTTONTEXT = 0x42D

tipslist = []

def GetTips(hWnd):
    threadId, processId = win32process.GetWindowThreadProcessId(hWnd)

    pHandle = win32api.OpenProcess(win32con.PROCESS_ALL_ACCESS, 0, processId)
    VirtualM = ctypes.windll.kernel32.VirtualAllocEx(pHandle.handle, 0, 256, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE)

    # タスクアイコン数取得
    count = win32api.SendMessage(hWnd, TB_BUTTONCOUNT, 0, 0)

    for i in range(count):
        res = win32api.SendMessage(hWnd, TB_GETBUTTONTEXT, i, VirtualM)
        STR = ctypes.create_string_buffer(1024)
        print i,res, STR
        ctypes.windll.kernel32.ReadProcessMemory(pHandle.handle, VirtualM, STR, 1024, 0)
        tipslist.append(copy.copy(STR.value.decode('cp932')))
        print STR.value.decode('cp932')

    ctypes.windll.kernel32.VirtualFreeEx(pHandle.handle, VirtualM, 0, MEM_RELEASE)
    ctypes.windll.kernel32.CloseHandle(pHandle.handle)

# 常時表示のタスクトレイからWindow Handle取得
hW = win32gui.FindWindow("Shell_TrayWnd", None)
hW = win32gui.FindWindowEx(hW, 0, "TrayNotifyWnd", None)
hW = win32gui.FindWindowEx(hW, 0, "SysPager", None)
hW = win32gui.FindWindowEx(hW, 0, "ToolbarWindow32", None)
GetTips(hW)

# 通常非表示のタスクトレイからWindow Handle取得
hW = win32gui.FindWindow("NotifyIconOverflowWindow", None)
hW = win32gui.FindWindowEx(hW, 0, "ToolbarWindow32", None)
GetTips(hW)
    
# 取得した結果の表示
print("\nタスクアイコン数:", len(tipslist))
print(tipslist)

WAVファイル, MP3ファイルを無音部分で分割

仕事で音声ファイルを無音部分で分割する必要がでてきたけど、 Audacityでやっても分割前の空音が残ってしまったり、保存時のファイル名指定が面倒だったり、 なかなか思い通りにならなかったのでPythonで処理しました。

必要なものなどのメモ書き。

環境

ライブラリのインストール

AnacondaでFFMPEGmenpoさんが公開しているので、これを使った。

conda install -c menpo ffmpeg

また、pydubはpipでインストール.

pip install pydub

ファイルの読み込み~無音部分での分割

pydubにsplit_on_silenceというクラスがあるので、これを使うだけ。

from pydub import AudioSegment
from pydub.silence import split_on_silence

sound = AudioSegment.from_file("./untitled1.wav", format="wav")
chunks = split_on_silence(
    sound,

    # 1500ms以上の無音がある箇所で分割
    min_silence_len=1500,

    # -30dBFS以下で無音とみなす
    silence_thresh=-30, 

    # 分割後500msだけ、無音を残す
    keep_silence=500
)

# 分割数の表示
print len(chunks)

表示された分割数で所望数通り、分割されているか確認してね。 silence_threshやmin_silence_lenのパラメータで多少の調整は必要。

ファイル名リストの作成~保存

作成したいファイル名が連番でなかったので、リストで作成(ここは好きにすればよい)。 その名前に従って分割した音声ファイルを保存。前節の分割数とfilelistの要素数が同じになるように注意。

filelist = ["file_hoge1","hogegennhogehoge","foo_bar","lucky_you",]

for i, chunk in enumerate(chunks):
    chunk.export(u"./分割/"+filelist[i]+".wav", format="wav")

Easy peasy Japanesey!