ちょっと硬派なコンピュータフリークのBlogです。

カスタム検索

2011-06-02

UnityでSkypeの多重起動を防ぐ

UbuntuでSkypeを使っているとき、ウィンドウを閉じてタスクトレイに格納している状態で、ランチャのアイコンをクリックすると多重起動してしまって「すでにSkypeが実行中です」という警告が出てログインできず、「多重起動ぐらい自分でチェックしやがれモルァッ!!」と言いながら舌打ちしつつ、すごすごとタスクトレイのアイコンをクリックしてSkypeを開いたという苦い経験はないだろうか。筆者の場合はうっかりとSkypeを多重起動してしまうことがたびたびあるのだが、ついにそのイライラが我慢できなくなってしまった。そこで、重い腰を上げて対策を施したので紹介したい。多重起動を回避しつつタスクトレイからSkypeを呼び出すところがミソである。

まず、次のプログラムを名前をつけて保存して欲しい。(筆者はskype_starterという名前にした。)実行権を与えて、パスの通ったディレクトリに置いておこう。

#!/usr/bin/env ruby

require 'dbus'

class SkypeStarter
  def run
    if skype_running?
      if skype_focused?
        minimize_skype_window
      else
        focus_skype_window
      end
    else
      system('skype')
    end
  end

  def skype_running?
    `pgrep -u #{ENV['USER']} skype`.size > 0
  end

  def skype_focused?
    active_win_id = `xprop -root|grep NET_ACTIVE|grep -v CUT_BUFFER|grep id|cut -f2 -d'#'`.chomp
    return false if active_win_id.size == 0
    `xwininfo -id #{active_win_id} -all|grep -i Skype`.size > 0
  end

  def init_dbus
    begin
      bus = DBus::SessionBus.instance
      service = bus.service('com.Skype.API')
      obj = service.object('/com/Skype')
      obj.introspect
      @skype_api = obj['com.Skype.API']
      @skype_api.Invoke("NAME #{File.basename($0)}")
      @skype_api.Invoke('PROTOCOL 7')
    rescue
      raise "Failed to initialize DBUS for Skype."
    end
  end

  def skype_cmd(cmd)
    init_dbus if @skype_api.nil?
    @skype_api.Invoke(cmd)
  end

  def skype_window_state
    stat = skype_cmd('GET WINDOWSTATE')[0]
    return 'UNKNOWN' unless stat =~ /^WINDOWSTATE\s+(\S+)/
    $1
  end

  def focus_skype_window
    raise "Failed to FOCUS Skype." unless skype_cmd('FOCUS') == 'OK'
    system('wmctrl -a skype')
  end

  def minimize_skype_window
    raise "Failed to MINIMIZE Skype." unless skype_cmd('MINIMIZE') == 'OK'
  end
end

if __FILE__ == $0
  SkypeStarter.new.run
end

Linux用Skypeは、D-BUSを介したAPIを提供しており、コイツを叩くことで各種操作が可能となっている。上記のプログラムはRubyなのだが、Ruby用のD-BUSライブラリはデフォルトではインストールされていない。次のようにコマンドを実行してインストールしよう。

shell> sudo aptitude install libdbus-ruby

このプログラムは、Skypeが起動していなかったら新たに起動し、既に起動していればウィンドウを全面に表示するという動作をする。ランチャのアイコンをクリックしたときはそのような動作が望ましい。面倒なのでプログラムの解説は省くので、興味のある人は「なんだよ、外部コマンド呼びまくりじゃねーか!超かっちょわりーな!」などとツッコミつつ内容を吟味して頂きたい。

次に、ランチャのSkypeアイコンをクリックしたときに、このスクリプトが呼ばれるようにする。ランチャのカスタマイズ方法は独学Linuxで解説されているので筆者も参考にさせて頂いた。感謝!Exec=skypeとなっているところを、Exec=skype_starterに変更しよう。

筆者のskype.desktopファイルの内容は次のとおり。

[Desktop Entry]
Name=Skype
Comment=Skype Internet Telephony
Exec=skype_starter
Icon=skype.png
Terminal=0
Type=Application
Encoding=UTF-8
Categories=Network;Application;

仕上げにログインをし直そう。ログイン後はランチャからSkypeのアイコンが消えてるので、もう一度登録し直そう。最初にSkype APIを叩いたときにはSkypeから確認を求められるので、skype_starterにアクセスの許可を与えよう。

かくして、Skypeが多重起動するというストレスから解放されたのであった。

Enjoy!!

0 コメント:

コメントを投稿