2011/03/16
2011/03/14
■ [perl] Windows 環境にてコマンドで音量の調節をする
Windows 環境にて,コマンドで音量の調節をしたいと思ったのですが,有効なコマンドがわかりませんでした.
どうしようかなと思ったいたら,cpan で Win32::Sound - cpan というモジュールがあったのでこれを使ってみました.
さっそくこのモジュールを入れて,下記のコードを実行してみると,どうも左右のバランスがズレて設定される模様….
use Win32::Sound;
Win32::Sound::Volume('100%');
調べてみると,Win32::Sound の 0.49 以前にはバグがあるみたいで,下記のようにしないと左右の音量を均等に調節できませんでした.下記のコードで
perl vol-set.pl 100
などとすると音量を 100% にしたり 0% にすることができました.
#!/usr/bin/env perl
# vol-set.pl: perl vol-set.pl 50
use strict;
use Win32::Sound;
my $vol = shift @ARGV || 0;
if ($vol > 100 || $vol < 0) {
$vol = 50;
}
$vol .= "%";
print "vol set $vol\n";
win32_volume($vol);
sub win32_volume {
my(@in) = @_;
if (not scalar @in) {
my $volume = Win32::Sound::_Volume();
if (wantarray) {
my $left = ($volume >> 16) & 0x0000FFFF;
my $right = ($volume ) & 0x0000FFFF;
return ($left, $right);
}
return $volume;
}
# Allows '0%'..'100%'
$in[0] =~ s{ ([\d\.]+)%$ }{ int($1*65535/100) }ex if defined $in[0];
$in[1] =~ s{ ([\d\.]+)%$ }{ int($1*65535/100) }ex if defined $in[1];
$in[1] = $in[0] unless defined $in[1];
my $volume = (($in[0] & 0x0000FFFF) << 16) | ($in[1] & 0x0000FFFF);
return Win32::Sound::_Volume($volume, 0);
}
関連リンク
2011/03/10
■ [diary] 宇宙,人間,素粒子
本日は職場の近くで,2002 年にノーベル物理学賞を小柴先生の講演があるというので行ってきました.
講演のタイトルは「宇宙,人間,素粒子」.規模の違う 3 つが実は関係していて繋がっているんだということで話が始まりました.
この講演は大教室に立ち見が出るくらい大勢の方が来ていました.小柴先生は,
立っている人達,来賓の席で空いているところがあるから,気にせず座りなさい.
と言われ,会場は何度も笑いが起こっていました.
実は私はここ 2,3 年前から,なぜか宇宙の話に興味があって,図解雑学シリーズなどの一般向けの本で宇宙のことを知るのが好きでした.
なので本日の話で出てきた統一理論,半粒子,ハッブルの法則など興味津々で聞かせてもらいました.宇宙のスケールを考えると,いま目の前にある問題はかなり小さいことに思えて壮大な気分になれるのと,人の知識でこんなことまでわかるのかという限界に挑戦しているところが良いです.
関連リンク
2011/03/08
2011/03/01
■ [felica] felicalib を使ってカードにデータを書き込む
以前 pasori, felicalibを cygwin から使うという記事を書きましたが,書き込みはどうやってやるんだと職場の方に聞かれたのでやり方をまとめてみました.
私の環境は Windows XP + cygwin なので,あまり参考にならないかもしれませんが同じような感じで他の環境でも出来ると思います.
まず事前準備として,felicalib の felicalib.dll を cygwin からも利用できるように変換します.felicalib に同封されている felicalib.dll, felicalib.lib を同じディレクトリに置いておきます.
% ls felicalib.h dump.c felicalib.dll felicalib.lib
そして dlltool を使って cgywin と互換性のあるインポートライブラリを作成します.
% echo EXPORTS > cygfelicalib.def % nm felicalib.lib | grep ' T _' | sed 's/.* T _//' >> cygfelicalib.def % dlltool --def cygfelicalib.def --dllname felicalib.dll --output-lib cygfelicalib.dll
そして dump.c (felicalib 同封) を下記のようにコンパイルします.私のところでは tchar.h がないとエラーがでたので,/usr/include/mingw を追加しました.
% gcc-3 -mno-cygwin ./dump.c -o dump.exe -L. -lcygfelicalib -I/usr/include/mingw % ./dump.exe # IDm: XX XX XX XX XX XX XX XX # PMm: XX XX XX XX XX XX XX XX # System code: XXXX ....
そしてカードにデータの書き込みですが,たまたま私の持っている ID カード(職場の職員証)を dump してみると下記のようにサービスコード 39C9 に R/W が可能な領域がありました.どうも 32 x 12 byte 分のデータが書けるようです.
# Serivce code = 39C9 : Random Access R/W 39C9:0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 39C9:0001 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 39C9:0002 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 39C9:0003 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 39C9:0004 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 39C9:0005 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 39C9:0006 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 39C9:0007 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 39C9:0008 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 39C9:0009 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 39C9:000A 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 39C9:000B 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
ということで本記事の末尾のコード write-data.c をコンパイルして,カードにデータを書き込みします.データの書き込みは felica_write_without_encryption() を使いました.
コンパイル,実行すると下記のように,データが書き込みされたことがわかります.
% gcc-3 -mno-cygwin ./write-data.c -o write-data.exe -L. -lcygfelica -I/usr/include/mingw
% ./write-data.exe 1 0 255
write block: 0001 addr: 0 -> FF
reading card information
# Serivce code = 39C9 : Random Access R/W
39C9:0001 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
writing data...
result...
# Serivce code = 39C9 : Random Access R/W
39C9:0001 FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
^^ -> ここが FF になる
- コード
#include <stdio.h>
#include <stdlib.h>
#include "felicalib.h"
static void printserviceinfo(uint16 s);
static void hexdump(uint8 *addr, int n);
// file: write-data.c
// compile: gcc-3 -mno-cygwin ./write-data.c -o write-data.exe -L. -lcygfelicalib -I/usr/include/mingw
// usage: write-data.exe block addr num
int _tmain(int argc, _TCHAR *argv[])
{
pasori *p;
felica *f, *f2;
int i, j, k;
int block = atoi(argv[1]);
int addr = atoi(argv[2]);
uint8 num = atoi(argv[3]);
uint8 line[16];
uint8 data[16];
uint16 service;
p = pasori_open(NULL);
if (!p) {
fprintf(stderr, "PaSoRi open failed.\n");
exit(1);
}
pasori_init(p);
f = felica_polling(p, POLLING_ANY, 0, 0);
if (!f) {
fprintf(stderr, "Polling card failed.\n");
exit(1);
}
f = felica_enum_systemcode(p);
if (!f) {
exit(1);
}
printf("write block: %04X addr: %d -> %02X\n",
block, addr, num);
f2 = felica_enum_service(p, N2HS(f->system_code[1]));
service = f2->service_code[10];
if (service == 0x39c9) {
printf("reading card information\n");
printserviceinfo(service);
k = block;
felica_read_without_encryption02(f2, service, 0, (uint8)k, data);
printf("%04X:%04X ", service, k);
hexdump(data, 16);
printf("\n");
}
data[addr] = num;
f2 = felica_enum_service(p, N2HS(f->system_code[1]));
service = f2->service_code[10];
if (service == 0x39c9) {
printf("writing data...\n");
felica_write_without_encryption(f2, service, (uint8)k, data);
}
printf("result...\n");
f2 = felica_enum_service(p, N2HS(f->system_code[1]));
service = f2->service_code[10];
if (service == 0x39c9) {
printserviceinfo(service);
k = block;
felica_read_without_encryption02(f2, service, 0, (uint8)k, data);
printf("%04X:%04X ", service, k);
hexdump(data, 16);
printf("\n");
}
printf("\n");
felica_free(f2);
felica_free(f);
pasori_close(p);
return 0;
}
static void printserviceinfo(uint16 s)
{
char *ident;
switch ((s >> 1) & 0xf) {
case 0: ident = "Area Code"; break;
case 4: ident = "Random Access R/W"; break;
case 5: ident = "Random Access Read only"; break;
case 6: ident = "Cyclic Access R/W"; break;
case 7: ident = "Cyclic Access Read only"; break;
case 8: ident = "Purse (Direct)"; break;
case 9: ident = "Purse (Cashback/decrement)"; break;
case 10: ident = "Purse (Decrement)"; break;
case 11: ident = "Purse (Read only)"; break;
default: ident = "INVALID or UNKOWN"; break;
}
printf("# Serivce code = %04X : %s", s, ident);
if ((s & 0x1) == 0) {
printf(" (Protected)");
}
printf("\n");
}
static void hexdump(uint8 *addr, int n)
{
int i;
for (i = 0; i < n; i++) {
printf("%02X ", addr[i]);
}
}
関連リンク



