# -*- Mode: Python -*-
# vi:si:et:sw=4:sts=4:ts=4
#
# Istanbul - A desktop recorder
# Copyright (C) 2005 Zaheer Abbas Merali (zaheerabbas at merali dot org)
# Portions Copyright (C) 2004,2005 Fluendo, S.L. (www.fluendo.com).
# All rights reserved.

# This file may be distributed and/or modified under the terms of
# the GNU General Public License version 2 as published by
# the Free Software Foundation.
# This file is distributed without any warranty; without even the implied
# warranty of merchantability or fitness for a particular purpose.
# See "LICENSE.GPL" in the source distribution for more information.

# Headers in this file shall remain intact.

import optparse
import sys

import gobject
import gtk
import gst

from istanbul.extern import pytrayicon
from istanbul.main import prefs
from istanbul.configure import config

class Istanbul:
    # self.state = 0 if stopped
    # self.state = 1 if recording
    def __init__(self):
        self.state = 0
        self.tray_event_box = gtk.EventBox()
        self.tray_image = gtk.Image()
        self.tray_image.set_from_stock(gtk.STOCK_MEDIA_RECORD, gtk.ICON_SIZE_SMALL_TOOLBAR)
        self.tray_event_box.add(self.tray_image)
        self.tray_container = pytrayicon.TrayIcon("istanbul")
        self.tray_container.add(self.tray_event_box)
        self.tray_event_box.connect("button-press-event",
            self._trayicon_clicked)
        self.tray_container.show_all()
        # initialise preferences dialog
        self.settingsdialog = prefs.IstanbulPrefs(self)


    def _trayicon_clicked(self, widget, event):
        # left click triggers record/stop
        # right click shows popup menu
        if event.button == 1:
            if self.state == 0:
                self.tray_image.set_from_stock(gtk.STOCK_MEDIA_STOP, gtk.ICON_SIZE_SMALL_TOOLBAR)
                self.state = 1
                self._start_recording()
            elif self.state == 1:
                self._stop_recording()
                if self.settingsdialog.xml.get_widget('encode_later').get_active() and self.settingsdialog.xml.get_widget('encode_later').get_property('sensitive'):
                    # use hard disk icon to signify saving
                    self.tray_image.set_from_stock(gtk.STOCK_HARDDISK, gtk.ICON_SIZE_SMALL_TOOLBAR)
                    self.state = 2
                else:
                    self.tray_image.set_from_stock(gtk.STOCK_MEDIA_RECORD, gtk.ICON_SIZE_SMALL_TOOLBAR)
                    self.state = 0
        # only show popup if in idle state                    
        elif event.button == 3 and self.state == 0:
            self._show_popup_menu()

    def _show_popup_menu(self):
        self.popupmenu = gtk.Menu()
        # About
        self.popupmenu_aboutitem = gtk.ImageMenuItem(gtk.STOCK_ABOUT)
        self.popupmenu_aboutitem.connect('activate', self._about)
        self.popupmenu.add(self.popupmenu_aboutitem)
        # Settings
        self.popupmenu_settingsitem = gtk.ImageMenuItem(gtk.STOCK_PREFERENCES)
        self.popupmenu_settingsitem.connect('activate', self._settings)
        self.popupmenu.add(self.popupmenu_settingsitem)
        # Quit
        self.popupmenu_quititem = gtk.ImageMenuItem(gtk.STOCK_QUIT)
        self.popupmenu_quititem.connect('activate', self._quit)
        self.popupmenu.add(self.popupmenu_quititem)
        
        self.popupmenu.popup(None, None, None, 3, gtk.get_current_event_time())
        self.popupmenu.show_all()

    def _settings(self, button):
        # show settings dialog
        # only show settings when not recording or encoding
        if self.state == 0:
            self.settingsdialog.show_all()

    def _about(self, button):
        aboutdialog = gtk.AboutDialog()
        aboutdialog.set_name('istanbul')
        aboutdialog.set_version(config.version)
        aboutdialog.set_comments('Records a video of your desktop session')
        aboutdialog.set_copyright('Copyright (c) 2005 Zaheer Abbas Merali\nPortions Copyright (C) Fluendo S.L.')
        aboutdialog.set_authors(['Zaheer Abbas Merali'])
        aboutdialog.set_website('http://live.gnome.org/Istanbul')
        aboutdialog.show_all()

    def _quit(self, button):
        if self.state == 1:
            self._stop_recording()
        gtk.main_quit()
        
    def _start_recording(self):
        # mainpipeline is the core pipeline string
        # save_pipeline is for saving to disk
        # icecast_pipeline is for sending to an icecast server
        width = self.settingsdialog.xml.get_widget('widthSpin').get_value_as_int()
        height = self.settingsdialog.xml.get_widget('heightSpin').get_value_as_int()
        framerate = self.settingsdialog.xml.get_widget('framerateSpin').get_value()
        mainpipeline = 'ximagesrc ! ffmpegcolorspace ! videoscale ! video/x-raw-yuv,width=%d,height=%d,framerate=%f' % (width, height, framerate)

        save_pipeline = ''
        encode_pipeline = ''
        icecast_pipeline = ''

        if self.settingsdialog.xml.get_widget('save').get_active():
            if self.settingsdialog.xml.get_widget('encode_later').get_active():
                encode_pipeline = 'smokeenc ! multipartmux'
                filename = '%s.tmp' % self.settingsdialog.xml.get_widget('filenameEntry').get_text()
            else:
                encode_pipeline = 'theoraenc ! oggmux'
                filename = self.settingsdialog.xml.get_widget('filenameEntry').get_text()

            save_pipeline = 'filesink location=%s' % filename
        if self.settingsdialog.xml.get_widget('stream_icecast2').get_active() and (not self.settingsdialog.xml.get_widget('encode_later').get_active() or not self.settingsdialog.xml.get_widget('encode_later').get_property('sensitive')):
            ip = self.settingsdialog.xml.get_widget('shout_ip').get_text()
            port = self.settingsdialog.xml.get_widget('shout_port').get_value_as_int()
            mountpoint = self.settingsdialog.xml.get_widget('shout_mount').get_text()
            icecast_pipeline = 'shout2send ip=%s port=%s mount=%s password=%s' % (ip, port, mountpoint, password)
        if save_pipeline != '' and icecast_pipeline != '':
            final_pipeline = '%s ! %s ! tee name=t ! %s t. ! { queue ! %s }' % (mainpipeline, encode_pipeline, save_pipeline, icecast_pipeline)
        else:
            final_pipeline = '%s ! %s ! %s %s' % (mainpipeline,encode_pipeline, save_pipeline,icecast_pipeline)
        
        self._pipeline = gst.parse_launch(final_pipeline)
        self._pipeline.set_state(gst.STATE_PLAYING)
        gobject.idle_add(self._pipeline.iterate)

    def _encode_eos_cb(self, element, pipeline):
        pipeline.set_state(gst.STATE_NULL)
        self.state = 0
        self.tray_image.set_from_stock(gtk.STOCK_MEDIA_RECORD, gtk.ICON_SIZE_SMALL_TOOLBAR)

        
    def _stop_recording(self):
        # really should fire an eos event before setting state to null
        self._pipeline.set_state(gst.STATE_NULL)

        # check if we have to encode
        if self.settingsdialog.xml.get_widget('encode_later').get_active() and self.settingsdialog.xml.get_widget('encode_later').get_property('sensitive'):
            # ok we have to encode
            final_filename = self.settingsdialog.xml.get_widget('filenameEntry').get_text()
            temp_filename = '%s.tmp' % final_filename
            width = self.settingsdialog.xml.get_widget('widthSpin').get_value_as_int()
            height = self.settingsdialog.xml.get_widget('heightSpin').get_value_as_int()
            framerate = self.settingsdialog.xml.get_widget('framerateSpin').get_value()

            pipeline_str = 'filesrc location=%s ! multipartdemux ! video/x-smoke,width=%d,height=%d,framerate=%f ! smokedec ! theoraenc quick=0 ! oggmux ! filesink location=%s name=fsink' % (temp_filename, width, height, framerate, final_filename)

            pipeline = gst.parse_launch(pipeline_str)

            # connect to eos on the sink
            filesink = pipeline.get_by_name('fsink')
            filesink.connect('eos', self._encode_eos_cb, pipeline)
            pipeline.set_state(gst.STATE_PLAYING)
            gobject.idle_add(pipeline.iterate)


    
def main(args):
    parser = optparse.OptionParser()
    parser.add_option('', '--version',
                      action="store_true", dest="version",
                      default=False,
                      help="show version information")
    
    
    options, args = parser.parse_args(args)

    if options.version:
        print config.version
        return 0


    deskrec = Istanbul()
    gtk.main()


