やっぱり要らないや

先週末、梅田のヨドバシで買い物ついでにiPadを予約してきた。
だけど・・・これキャンセルしようと思ってます。もしたぶんその日に在庫があったら衝動買いしていたと思う。いや衝動していたはず。それだけ、触った感じの印象が良かった。

で、ほぼ1週間経とうとしているのですが、まだ手に入る気配は全然ない。正直、2日ほど前からiPad熱も覚めてしまった。

ふと、考えた。僕はiPadを買ったらそれで何をしようとしてたんだろう・・・と。

iPod Touchはメディアプレーヤーとして、Webブラウザとして、持ち歩き、また、寝床で眠りにつくまでの退屈しのぎに活躍(笑)している。で、iPadは?

そう考えると、iPadの落ち着く先がないんだ。。。

  • メディアプレイヤーとして・・・
    家で見るんだったら、わざわざiPadじゃなくて、テレビで見るよね。そもそも、あんなでかい画面で外でエッチな動画見れないし(笑)嘘です(^^;;;

  • Webやメールなどのインターネット接続端末として・・・
    そもそも外に持ち歩かない(重くてデカくて持ち歩けない)し、家じゃスリープ状態にしてあるパソコンがあるし・・・。寝床で横になりながらなんてサイズ的に無理だし・・・。

  • デジカメのフォトストレージとして・・・
    確かにノートPCよりいいんだけど・・・、そもそも人の目が気になるので撮影場所で画像なんかチェックできない。(どういう写真撮ってんの?というのは横に置いといて(^^;;;

  • 新聞・雑誌のビューアーとして・・・
    電子書籍ならダウンロードするだけで済むけど、既存の紙媒体の雑誌や本を取り込むには、ScanSnapのような連続スキャナーが必要だし、週刊雑誌をいちいち裁断してスキャンして取り込んで・・・とか毎週毎週やってらんない。そもそも雑誌なんて一回読み終わったら二度と見ないし。

僕のライフスタイル?では、どう理屈をこねようと、iPadに居場所がないんだ。

僕がiPadのような持ち運びできるサイズのコンピュータ端末に求めるものは、「汎用」である、ってこと。

iPadを実際に触って気付いた。汎用ってのは、要は、広く浅く何でもできるってこと。メールやウェブ巡回のためだけならiPodや携帯で充分。それ以上の「何か」をiPadに求めていたのかもしれない。でも、iPadはプログラムのソースをビルドすることも、HTMLでWebページやスクリプトソースを書くことも、それを実行することもできない。

ただ、見るだけ、聞くだけ、消費するだけ、何かを作りたい、何かを表現したい、といったことをやろうとすると、途端に、単なるカッコイイ、デジタルジャンクと化す。

IT系のニュース記事によると、iPadはiPhoneの3倍以上の初速で売れているんだそうだ。アップルは、というか、ジョブズは、今までにも増して、イヤなやつになっちゃってる。というか、この人、きっと M なんだろう(笑) わざと嫌われようとしているんじゃね? と思ってしまう。まぁ、そんなことはどうでもいい。ジョブズがどんなイヤな奴でも、アップルの価値はIT業界でナンバーワン!になり、いまや飛ぶ鳥を落とすが如く、強権的とも言えるぐらいの勢いで、イケイケ・ウハウハ状態だ。

iPadを手に入れた上司が呟いた「いつまで続くのかな・・・」印象的だった。

 
と、いうわけで・・・? iPad熱が冷めてしまった僕は、新しいケータイに熱を上げるのであった。。。これこそ、無駄だね・・・。いや、分かってるんだけど・・・。

3年近く使っている携帯をそろそろ買い換えようと・・・ドコモショップで昨日予約してきました(^^;;;

  • WiFi
  • Bluetooth
  • GPS
  • ワンセグ
  • カメラ
  • FullHDムービー
  • 防水
  • FMトランスミッター
  • おサイフケータイ
  • 指紋認証

等など・・・僕が望む機能、ほぼ全部入りです(^^

ガラケー

Xperiaのようなスマートフォンもいいんですが・・・やっぱりガラケーが一番使いやすいんじゃないかと。。。

かくして・・・物欲は尽きないのであった・・・

チャンチャン、と。

画像のプリロード

一昔前、Webページ上での画像のロールオーバー(画像の上にマウスポインタを重ねると画像が変わるアレです)にJavascriptが使われていましたね。でも、今は、Javascriptではなく、CSSで実現する方法が標準となりつつあります。
たとえば・・・

a      {background: url(xxx.jpg);}
a:hover{background: url(yyy.jpg);}

こんな感じですかね。IE6では、アンカータグ(<a>)しか対応してませんが、他のブラウザなら他のタグでも可能です。

で、ここで僕がはまったのが、ページに初めてアクセスしたとき、ロールオーバーさせる要素にマウスを持っていくと一瞬空白になってしまうんですよねぇ・・・。初めてページを表示させたときまだロールオーバーさせる画像が読み込まれていないのが原因で、解決方法は簡単、画像を先読みさせてブラウザのキャッシュに入れてしまえばいい。要するにプリロードさせればいい。んな、こたぁ、言われなくても分かるんです。

その方法は・・・頭の悪い僕では2つぐらいしか思いつきません・・・

  1. javascriptを使って (new Image()).src = “yyy.jpg”; とかしておく。
  2. HTML内に幅/高さを1にした<img>タグを書いておく。
  3. 画像を一枚用意して、width,height,background-positionを駆使して切り分ける

無駄なタグを含める後者は論外。画像を一枚に・・・というのは新規につくるページだと最適ですが、既存の組みあがっているページとなると無駄に工数がかかってしまう。一番簡単にできそうなのは・・・やはりスクリプトで。・・・せっかくロールオーバー処理からJavascriptを排除したのに・・・(--;;;
ブラウザの最適化処理で自動的に読み込んでくれれば問題ないんですけどね・・・。そもそも、css内にある画像は先読みしてほしい気もします。まぁ、無駄にメモリー消費が増えてしまう、パフォーマンスの問題も絡むので無理か・・・。

結局、

/**********************************************
  画像を読み込んでおく関数
  preload(画像1,画像2,....);
***********************************************/
function preload()
{
  var len = 0;

  if((len = arguments.length) &lt;= 0)
    return;

   for(var i=0;i&lt;len;i++)
    (new Image()).src = arguments[i];
}

preload('yyy.jpg','zzz.png');

とかやってしまうんだけど・・・。

う~ん・・・スクリプトを使わない上手いやり方はないものか・・・。

塵も積もればなんとやら

と、申しますが・・・500円玉は塵じゃないかな・・・(^^;;;

僕は小銭をジャラジャラ持つのが大嫌いで、2~3日に一度は小銭入れをガサッと貯金箱(ただの空ビンですが・・・)へ投入。っつーことをしていると、自然にその量がハンパじゃなくって・・・、銀行へ持って預入しようかと思い、硬貨別にやっと整理し終えました・・・。

塵も積もれば・・・


これって、ATMじゃ無理っぽそうですね・・・。

 
今週も(個人)撮影会へ~。帰りに梅田のヨドバシへ買い物しにいったら、なにやら行列が・・・行列の先には、iPadの予約受付カウンター・・・。行列にはなぜか並びたくなる習性があるみたいで、僕もその列へ・・・(笑)

あ、デジカメ売ったお金と、この硬貨で、充分買えそうです・・・。う~ん・・・発売前に、あれだけバカにしてたiPadも、実際触ってみると欲しくなるんですねぇ~。まぁ飽きたら売ればいいや(^^;;;

さようならオリンパス、さてiPadはどこに?

去年衝動買いして数回使っただけで今年に入って一回も使わなかったオリンパスの4/3機、E-P1を昨夜ヤフオクへ出品。即決価格をつけたら、その日のうちに落札(笑) ヤフオクで処分した中で一番落札が早かったです(^^;;; う~ん・・・もうちょっと高く設定した方が良かったのかな?(^^

で、昨日会社にiPadを持ってきている人がいて、触らしてもらいました・・・。

液晶がメチャクチャキレイですね~。動作も速いし、これで、pullpullpicとかぷるるんメーカーとかで遊ぶとちょっと興奮・・・・すみません、下品で・・・申し訳ない(笑)

難点は片手で持てないぐらい意外に重い・・・ということぐらいでしょうか・・・。Camera Connection Kit を使えばデジカメのストレージ・ビューアーとして充分使えそうですね~。

やっぱり、いいなぁ~、面白いなぁ~、欲しいなぁ・・・・ あ! そういえばE-P1を処分したお金で買えるな・・・、と思い会社帰りに某○ーズ○ンキに寄ってみたけど・・・

『あるわけないやろ!ボケ!』と言いたげな店員のハナで笑うような素っ気ない態度。まぁそりゃそうだ。アップルストアでさえ納期6月末といわれているのに(^^
だけど・・・何台も普通に展示して試すことができる状態だったので、きっと在庫はあるんだろう。。。おそらく客寄せパンダ的なツールとして使う気でしょうねぇ・・・。

と、いうわけで、売ったお金で、iPadを・・・・というもくろみは諦め、週末参加する予定の撮影会参加費用に消えるのであった・・・。

先週のん、一枚更新。

竹村美緒さん

コマンドプロンプトのログを取る (その2)

コンソール(CMD.EXE)のログを取る (不完全版) の続きです。

標準出力と標準エラー出力をファイルに書き出せたところまではできてタイムアップ。標準入力が書き出せていませんでした。今回は、入力バッファをファイルに書き出してから、リダイレクトしたパイプハンドルに書き出せば事は足ります。

で、あまりにもソースが汚くなってきたので整理して、テストコードが完成。パイプハンドルをラップした構造体とスレッドに渡すコンテキストを別ファイルにして整理。

/*******************************************************************

 ■コマンドプロンプトのすべての操作をテキストファイルへ書き出します。

  ※ほとんどエラーチェック・処理をしていないテストコード
  ※書き出すファイルは、#define LOGFILE TEXT("~") で指定。

********************************************************************/

#include <windows.h>

//Cランタイム
#include <tchar.h>
#include <stdio.h>

//パイプ、スレッドに渡すパラメータをラップした構造体を定義したヘッダー
#include "pipe.h"
#include "context.h"

#define CLOSEHANDLE(X) {if(X)CloseHandle(X);}
#define BUFFER_SIZE 1024
#define SPIN_COUNT 4000

//書き出すファイル名の指定
#define LOGFILE TEXT("cmdlog.txt")

//標準入出力・ファイルハンドルへの読取と書込スレッド
DWORD WINAPI ReadAndWriteProc(LPVOID lpParameter)
{
  Context *context = (Context*)lpParameter;

  TCHAR pBuffer[BUFFER_SIZE] = {0};
  DWORD dwRead = 0,dwWrite = 0;
  BOOL bRet = FALSE;
  while(!(context->bThreadMustTerminate))
    {
      do
        {
          bRet = ReadFile(context->hRead,(PVOID)pBuffer,BUFFER_SIZE,&dwRead,NULL);
          if(dwRead > 0)
            {
              EnterCriticalSection(&(context->CriticalSection));
              if(context->hFile)
                WriteFile(context->hFile,(PVOID)pBuffer,dwRead,&dwWrite,NULL);
              if(context->hWrite)
                WriteFile(context->hWrite,(PVOID)pBuffer,dwRead,&dwWrite,NULL);
              LeaveCriticalSection(&(context->CriticalSection));
            }
        }
      while(bRet == TRUE && dwRead > 0);
    }

  return 0;
}

//ファイルを書込用にオープン(同期)
HANDLE OpenLogFile(PCTSTR szLogName)
{
  return CreateFile(szLogName,
                    GENERIC_WRITE,
                    0,
                    NULL,
                    CREATE_ALWAYS,
                    FILE_ATTRIBUTE_NORMAL,
                    NULL);
}

//環境変数COMSPECからコマンドプロンプトのパスを得て起動
BOOL CreateCommandPrompt(STARTUPINFO& si,PROCESS_INFORMATION& pi)
{
  BOOL bRetVal = FALSE;

  //CMD.EXEのパスを格納するバッファ
  TCHAR szCmdPath[MAX_PATH+1] = {0};

  //CMD.EXEのパスを環境(システム)変数から得る。
  if(0 == GetEnvironmentVariable(TEXT("COMSPEC"),szCmdPath,MAX_PATH+1))
    goto cleanup;
  
  bRetVal = CreateProcess(NULL,
                          szCmdPath,
                          NULL,
                          NULL,
                          TRUE,
                          NORMAL_PRIORITY_CLASS,
                          NULL,
                          NULL,
                          &si,
                          &pi);

cleanup:
  return bRetVal;
}

//スタートアップ
int _tmain(int argc,_TCHAR **argv)
{
  UNREFERENCED_PARAMETER(argc);
  UNREFERENCED_PARAMETER(argv);
  
  /*------------------------------------------------------------
    スレッドハンドル、パイプ、スレッドに渡すコンテキスト
    配列はそれぞれ、0:標準入力用 1:標準出力用 2:標準エラー出力用
  --------------------------------------------------------------*/
  HANDLE hThreads[3] = {NULL};
  Pipe Std[3] = {PIPE_READ_INHERIT,PIPE_WRITE_INHERIT,PIPE_WRITE_INHERIT};
  Context ctx[3];

  //ログを書き込むファイル
  HANDLE hFile = NULL;
  
  //CreateProcessに必要な構造体
  STARTUPINFO si = {sizeof(STARTUPINFO)};
  PROCESS_INFORMATION pi = {NULL};

  //クリティカルセクション初期化
  InitializeCriticalSectionAndSpinCount(&Context::CriticalSection,SPIN_COUNT);

  if((hFile = OpenLogFile(LOGFILE)) == INVALID_HANDLE_VALUE)
    {
      _tprintf(TEXT("ログファイルのオープンが失敗しました"));
      goto cleanup;
    }

  //入出力ハンドルをリダイレクトしたコマンドプロンプトを生成
  si.dwFlags    = STARTF_USESTDHANDLES;
  si.hStdInput  = Std[0].hRead;   //パイプにリダイレクト
  si.hStdOutput = Std[1].hWrite; //パイプにリダイレクト
  si.hStdError  = Std[2].hWrite; //パイプにリダイレクト

  if(FALSE == CreateCommandPrompt(si,pi))
    {	
      _tprintf(TEXT("CreateProcess 失敗 : %d"),GetLastError());
      goto cleanup;
    }

  //コンテキスト構造体のメンバをセット
  ctx[0].Set(GetStdHandle(STD_INPUT_HANDLE),Std[0].hWrite);
  ctx[1].Set(Std[1].hRead,GetStdHandle(STD_OUTPUT_HANDLE),hFile);
  ctx[2].Set(Std[2].hRead,GetStdHandle(STD_ERROR_HANDLE),hFile);
  
  //スレッド作成
  for(int i=0;i<3;i++)
    hThreads[i] = CreateThread(NULL,0,ReadAndWriteProc,&ctx[i],0,NULL);
  
  //新しいコマンドプロンプトが終了するまで待機
  WaitForSingleObject(pi.hProcess,INFINITE);
  
  //スレッド終了通知をセット
  Context::bThreadMustTerminate = TRUE;

  //パイプハンドルのクローズ
  for(int i=0;i<3;i++)
    Std[i].Close();

  CloseHandle(GetStdHandle(STD_INPUT_HANDLE));

  //起動したスレッドが終了するまで待機
  WaitForMultipleObjects(3,hThreads,TRUE,INFINITE);

  //クリティカルセクションオブジェクトを削除
  DeleteCriticalSection(&Context::CriticalSection);

cleanup:
  //ハンドルを閉じる
  CLOSEHANDLE(hFile);
  CLOSEHANDLE(pi.hThread);
  
  for(int i=0;i<3;i++)
    CLOSEHANDLE(hThreads[i]);
  
  CLOSEHANDLE(pi.hProcess);

  return 0;
}

すべてのコードを固めたものはこちら。
全てのソースはこっちに移動
nmakeでcmdlog.exeが生成されます。

ただ、これは CTRL-Cとかすると・・・コマンドプロンプト自体がガサッと終了してしまいますし、入力した内容がエコーされるし(ファイルには出力されないので別に良いのですが・・・)、まだまだ不完全。
書き出すファイルパスはハードコードしとるし、エラー処理していないし、ファイルの書き出しは同期処理なので、遅いデバイスを指定すると(今更ないと思うけどフロッピーとか)書出処理から制御が戻ってこないので非常にマズイことになってます・・・。

また暇なときに完成度を高めたい・・・といっててそのままでずっと使うことが多いんですが(ーー;


コンソール(CMD.EXE)のログを取る (不完全版)
コマンドプロンプトのログを取る(その2)
コマンドプロンプトのログを取る(その3)
コマンドプロンプトのログを取る(完結)