Mountain LionでLimeChatの新着メッセージを読み上げる

MacLimeChatにはマクロ機能が付いてないのでした。
Mountain Lionには最初から読み上げ機能が付いてるのでKyokoに読んでもらう。
橋本商会 » Mac/Linuxに日本語を喋らせる

使い方

  1. Kyoko(日本語読み上げ)の設定
  2. rubygemsでfssmとdiffをインストール。
  3. LimeChatのPreferences->Log->Log transcriptsにチェック。
  4. kyokoSay.rbを起動。
ruby kyokoSay.rb "#Channel"

チャンネル名を指定しなければGUIで選択。

kyokoSay.rb

URLを「URL省略」って読んでくれるコードいつか書く(だるい)ていうか誰か書いて。
Code/kyokoSay.rb at master · juntk/Code · GitHub

環境

追記

このスクリプトもうずっと起動しっ放しだけど、kyokoが「:」を「ほーれん」って読むのが気になる・・・。

ターミナル(Bash)のウィンドウサイズが知りたい - Ruby

irbからだとENV['LINES']に行数、ENV['COLUMNS']に列数が入ってるんだけど、普通にrubyから実行するとnilになってる。
んで、何となくReadline.readline()したらENVにLINESとCOLUMNSが追加されてた。
何がしたいかっていうと、この画像の点線部分があるじゃん。
こんな風にウィンドウサイズぴったりに文字を出力するためにターミナルの横幅が知りたいわけなのですよ。
横幅っていうか正確には文字数なんだけども。

ソース

require 'readline'

def getEnv()
    lines = ENV['LINES']
    columns = ENV['COLUMNS']
    return lines, columns
end
def checkEnv()
    lines, columns = getEnv()
    print "ENV['LINES'] => ", lines
    puts
    print "ENV['COLUMNS'] => ", columns
    puts
end
def putLine()
    lines, columns = getEnv()
    columns.to_i.times do |t|
        print '-'
    end
    puts
end

checkEnv()
puts

Readline.readline('Readline>')
checkEnv()

putLine()
checkEnv()

GoogleAppEngineでPython2.6+Django1.4.2

Django スタートガイド  |  Python  |  Google Cloud

manage.pyのエラー

Google Code Archive - Long-term storage for Google Code Project Hosting.のr117で

$ ./manage.py startapp appName

やると

Traceback (most recent call last):
  File "./manage.py", line 18, in <module>
    InstallAppengineHelperForDjango()
  File "/Users/juntk/Downloads/appengine_helper_for_django/appengine_django/__init__.py", line 550, in InstallAppengineHelperForDjango
    LoadAppengineEnvironment()
  File "/Users/juntk/Downloads/appengine_helper_for_django/appengine_django/__init__.py", line 212, in LoadAppengineEnvironment
    appconfig, unused_matcher = dev_appserver.LoadAppConfig(PARENT_DIR, {})
ValueError: too many values to unpack

こんなエラー出たので、appengine_helper_for_django/appengine_django/__init__.pyの212行目

$ vim +212 appengine_django/__init__.py

を下のように修正。

       appconfig, unused_matcher, from_cache = dev_appserver.LoadAppConfig(PARENT_DIR, {})

Keys列挙体のメンバー名が分かりにくいから置換する

Keys Enum (System.Windows.Forms) | Microsoft Docs
これでキーの名前が分かるんだけど、MacBookはOME〜なんちゃらっていうマイナーなキーボードにあたるらしくて、キーコードも特殊なので対応しなきゃいけない。
あと数字キーはD1じゃなくて1、Multiplyとかも記号で扱いたいなあ、みたいな感じ。

System.Collections.Hashtable keyFix = new System.Collections.Hashtable();
keyFix.Add("D1", "1");
keyFix.Add("D2", "2");
keyFix.Add("D3", "3");
keyFix.Add("D4", "4");
keyFix.Add("D5", "5");
keyFix.Add("D6", "6");
keyFix.Add("D7", "7");
keyFix.Add("D8", "8");
keyFix.Add("D9", "9");
keyFix.Add("D0", "0");
keyFix.Add("Multiply", "*");
keyFix.Add("Separator", "|");
keyFix.Add("Subtract", "-");
keyFix.Add("Decimal", ".");
keyFix.Add("Divide", "/");
keyFix.Add("ShiftKey", "Shift");
keyFix.Add("ControlKey", "Ctrl");
keyFix.Add("Menu", "Alt");
keyFix.Add("Back", "BackSpace");
keyFix.Add("OemOpenBrackets", "[");
keyFix.Add("Oem4", "[");
keyFix.Add("OemCloseBrackets", "]");
keyFix.Add("Oem6", "]");
keyFix.Add("OemPipe", "|");
keyFix.Add("Oem5", "|");
keyFix.Add("OemQuotes", "'");
keyFix.Add("Oem7", "'");
keyFix.Add("OemSemicolon", ";");
keyFix.Add("Oem1", ";");
keyFix.Add("OemQuestion", "/");
keyFix.Add("Oem2", "/");
keyFix.Add("OemPeriod", ".");
keyFix.Add("Oemcomma", ",");
keyFix.Add("Oemtilde", "`");
keyFix.Add("Capital", "CapsLock");

やりたいこと

// キー入力とかが絡むイベントハンドラとかで
string key = e.KeyCode.ToString();
foreach(string k in keyFix.Keys)
{
    if (key.Equals(k))
    {
        key = key.Replace(k, keyFix[k].ToString());
    }
}

C#で非同期ソケット通信

ブラウザでlocalhost:portを開いてチェック。

Programs.cs

using System;
using System.Collections.Generic;
using System.Text;

namespace Spider
{
    class Program
    {
        static void Main(string[] args)
        {
            NetworkListener n = new NetworkListener();
            n.beginListener();
        }
    }
}

NetworkStateObject.cs

using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;

namespace Spider
{
    class NetworkStateObject
    {
        public Socket workSocker = null;
        public const int BufferSize = 1024;
        public byte[] buffer = new byte[BufferSize];
        public StringBuilder sb = new StringBuilder();
    }
}

Network.cs

using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;

namespace Spider
{
    class NetworkListener
    {
        private ManualResetEvent threadControl;
        public int port;
        public NetworkListener()
        {
            threadControl = new ManualResetEvent(false);
            port = 1111;
        }
        public void beginListener()
        {
            IPHostEntry ipHostEntry = Dns.GetHostEntry(Dns.GetHostName());
            // select IPv4 address
            IPAddress ipv4 = null;
            foreach (IPAddress ip in ipHostEntry.AddressList)
            {
                if (ip.AddressFamily == AddressFamily.InterNetwork)
                {
                    ipv4 = ip;
                }
            }
            if (ipv4 == null)
            {
                Console.WriteLine("IPv4 is not exist!");
                return;
            }
            IPEndPoint localEP = new IPEndPoint(ipv4, this.port);
            Socket listener = new Socket(localEP.Address.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

            try
            {
                listener.Bind(localEP);
                listener.Listen(100);
                while (true)
                {
                    threadControl.Reset();
                    listener.BeginAccept(new AsyncCallback(acceptCallback), listener);
                    threadControl.WaitOne();
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }
        public void acceptCallback(IAsyncResult aResult)
        {
            threadControl.Set();
            Socket socket = (Socket)aResult.AsyncState;
            Socket handler = socket.EndAccept(aResult);
            NetworkStateObject state = new NetworkStateObject();
            state.workSocker = handler;
            handler.BeginReceive(state.buffer, 0, NetworkStateObject.BufferSize, 0, new AsyncCallback(readCallback),state);
        }
        public void readCallback(IAsyncResult aResult)
        {
            NetworkStateObject state = (NetworkStateObject)aResult.AsyncState;
            Socket handler = state.workSocker;

            int read = handler.EndReceive(aResult);

            if (read > 0)
            {
                state.sb.Append(Encoding.UTF8.GetString(state.buffer, 0, read));
                handler.BeginReceive(state.buffer, 0, NetworkStateObject.BufferSize, 0, new AsyncCallback(readCallback), state);
            }
            else
            {
                if (state.sb.Length > 1)
                {
                    string content = state.sb.ToString();
                    Console.WriteLine("read: {0}", content);
                }
                handler.Close();
            }
        }
    }
}

Rubyでスレッドを簡単に扱うための何か

Rubyでスレッド使うときの雛形みたいなやつ - juntkの日記をちゃんと使えるようにしただけ。
スレッドの並列実行と待機、実行、破棄の管理を簡単に。詳しくは上の記事。

MyThreadTest.rb

つかいかた。
MyThread#addThreadでスレッドをテキトーに追加していく→MyThread#controlThreadが何とかしてくれる!!
永遠に実行状態に移らない待機スレッドが生まれても、放置という方向で・・・。

# encoding: utf-8
require "./MyThread.rb"

class MyThreadTest
    def initialize
        @thread = MyThread.new
        # スレッドの並列度(デフォルト1)
        @thread.threadConcurrency = 2
        # 待機状態からの復帰モード(1:先入先出/-1:後入先出/defalut:1)
        @thread.mode = 1
    end
    def main()
        begin
            point = [10,20]

            methodObject = self.method(:worker)
            # MyThread#addThreadにスレッドで行う処理をメソッドオブジェクトとして送る
            # 第一引数はメソッドオブジェクト、第二引数はスレッドからメソッドオブジェクトが呼ばれるときに渡されるオブジェクト
            @thread.addThread(methodObject, point)
            @thread.controlThread()

            @thread.dump()
            sleep 1
        end while true
    end
    def worker(aObject=nil)
        p aObject
        1000.times do |t|
            a = Math.sqrt(t) * Math.sqrt(t+1)
        end
    end
end

MyThreadTest.new.main()

MyThread.rb

本体

# encoding: utf-8
# ruby -v => 1.8.7
require "thread"

class MyThread
    attr_accessor :threadConcurrency, :mode
    def initialize()
        # スレッド管理用
        @t = []
        # スレッドの並列度(同時実行数)
        @threadConcurrency = 1
        # 先入先出: @mode = 1
        # 後入先出: @mode = -1
        @mode = 1
    end
    def dump()
        p @t
    end
    def addThread(aWorkerObject = nil, aObject)
        # スレッド管理用の配列にスレッド入れる
        @t << Thread.new do
            # Thread#wakeupでスレッドを開始したいので、スレッドを止めとく
            # Thread#stopするとThread#statusは"sleep"になる
            Thread.stop
            # なんか重い処理
            aWorkerObject.call(aObject)
        end
    end
    def controlThread()
        # スレッドの並列実行数の調整と終了したスレッドの破棄
        begin
            # 実行中のスレッド数のチェック用
            runThreadNum = 0
            # 停止中のスレッドリスト
            stopThreadList = []
            @t.each_with_index do |v,i|
                # 終了したスレッドをスレッド管理用配列から破棄
                # Thread#statusがfalseのときスレッドが正常終了してる
                if v.status == false or v.status == "abort" or v.status == nil then
                    @t.delete_at(i)
                elsif v.status == "run" then
                    runThreadNum += 1
                elsif v.status == "sleep" then
                    # Thread#stop?は終了(dead)または停止(stop)のときにtrueを返す
                    #   -> これ、スレッドで行う処理の中にsleep 10とかあるとtrueが返ってきます。
                    stopThreadList << v
                else
                end
            end
            # 実行中のスレッド数と停止中のスレッドが分かったので
            # 並列実行度を元に停止状態(stop)のスレッドを実行可能状態(run)にする。
            (@threadConcurrency - runThreadNum).times do |t|
                # 雑というか無駄すぎる^^;
                if stopThreadList.size > 0 then
                    if @mode == 1 then
                        stopThreadList.shift.run
                    elsif @mode == -1
                        stopThreadList.pop.run
                    else
                        print 'WARNING: This mode is not defined.(',@mode,')'
                        stopThreadList.shift.run
                    end
                end
            end
        rescue error
            p error
        end
    end
end