1 /* 2 * Smuxi - Smart MUltipleXed Irc 3 * 4 * Copyright (c) 2005-2008, 2012-2013, 2015 Mirco Bauer <meebey@meebey.net> 5 * 6 * Full GPL License: <http://www.gnu.org/licenses/gpl.txt> 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 */ 22 23 using System; 24 using System.Runtime.Remoting; 25 using System.Reflection; 26 using Gtk.Extensions; 27 using NDesk.Options; 28 using Smuxi.Common; 29 30 namespace Smuxi.Frontend.Gnome 31 { 32 public class MainClass 33 { 34 #if LOG4NET 35 private static readonly log4net.ILog _Logger = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 36 #endif 37 static readonly string LibraryTextDomain = "smuxi-frontend-gnome"; 38 static SingleApplicationInstance<CommandLineInterface> Instance { get; set; } 39 Main(string[] args)40 public static void Main(string[] args) 41 { 42 var debug = false; 43 var link = String.Empty; 44 var engine = String.Empty; 45 var newInstance = false; 46 var options = new OptionSet(); 47 options.Add( 48 "d|debug", 49 _("Enable debug output"), 50 v => { 51 debug = true; 52 } 53 ); 54 options.Add( 55 "h|help", 56 _("Show this help"), 57 v => { 58 Console.WriteLine("Usage: smuxi-frontend-gnome [options]"); 59 Console.WriteLine(); 60 Console.WriteLine(_("Options:")); 61 options.WriteOptionDescriptions(Console.Out); 62 Environment.Exit(0); 63 } 64 ); 65 options.Add( 66 "e|engine=", 67 _("Connect to engine"), 68 v => { 69 engine = v; 70 } 71 ); 72 options.Add( 73 "open|open-link=", 74 _("Opens the specified link in Smuxi"), 75 v => { 76 link = v; 77 } 78 ); 79 options.Add( 80 "new-instance", 81 _("Starts a new Smuxi instance and ignores an existing one"), 82 v => { 83 newInstance = true; 84 } 85 ); 86 87 try { 88 options.Parse(args); 89 90 #if LOG4NET 91 // initialize log level 92 log4net.Repository.ILoggerRepository repo = log4net.LogManager.GetRepository(); 93 if (debug) { 94 repo.Threshold = log4net.Core.Level.Debug; 95 } else { 96 repo.Threshold = log4net.Core.Level.Info; 97 } 98 #endif 99 100 try { 101 Instance = new SingleApplicationInstance<CommandLineInterface>(); 102 if (Instance.IsFirstInstance) { 103 Instance.FirstInstance = new CommandLineInterface(); 104 if (!String.IsNullOrEmpty(link)) { 105 Instance.FirstInstance.OpenLink(link); 106 } 107 } else { 108 if (!String.IsNullOrEmpty(link)) { 109 var msg = _("Passing link to already running Smuxi instance..."); 110 #if LOG4NET 111 _Logger.Info(msg); 112 #else 113 Console.WriteLine(msg); 114 #endif 115 Instance.FirstInstance.OpenLink(link); 116 } else if (!newInstance) { 117 var msg = _("Bringing already running Smuxi instance to foreground..."); 118 #if LOG4NET 119 _Logger.Info(msg); 120 #else 121 Console.WriteLine(msg); 122 #endif 123 Instance.FirstInstance.PresentMainWindow(); 124 } 125 126 if (!newInstance) { 127 // don't initialize/spawn another instance 128 return; 129 } 130 } 131 } catch (Exception ex) { 132 #if LOG4NET 133 _Logger.Warn("Single application instance error, ignoring...", ex); 134 #endif 135 } 136 137 Frontend.Init(args, engine); 138 } catch (Exception e) { 139 #if LOG4NET 140 _Logger.Fatal(e); 141 #endif 142 // when Gtk# receives an exception it is not usable/relyable anymore! 143 // except the exception was thrown in Frontend.Init() itself 144 if (Frontend.IsGtkInitialized && !Frontend.InGtkApplicationRun) { 145 Frontend.ShowException(e); 146 } 147 148 // rethrow the exception for console output 149 throw; 150 } 151 } 152 _(string msg)153 static string _(string msg) 154 { 155 return LibraryCatalog.GetString(msg, LibraryTextDomain); 156 } 157 } 158 159 public class CommandLineInterface : SingleApplicationInterface 160 { 161 #if LOG4NET 162 static readonly log4net.ILog Logger = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 163 #endif 164 PresentMainWindow()165 public void PresentMainWindow() 166 { 167 if (!Frontend.IsGtkInitialized || !Frontend.InGtkApplicationRun) { 168 return; 169 } 170 171 Gtk.Application.Invoke(delegate { 172 var window = Frontend.MainWindow; 173 if (window == null) { 174 return; 175 } 176 window.PresentWithServerTime(); 177 }); 178 } 179 OpenLink(string link)180 public void OpenLink(string link) 181 { 182 if (Frontend.Session == null) { 183 // we don't have a session yet, probably local instance that is 184 // just starting or a remote engine that isn't connected yet 185 EventHandler handler = null; 186 handler = delegate { 187 if (Frontend.Session == null) { 188 return; 189 } 190 // we can't know which thread invokes SessionPropertyChanged 191 Gtk.Application.Invoke((o, e) => { 192 #if LOG4NET 193 Logger.Info("Opening the link..."); 194 #endif 195 Frontend.OpenLink(new Uri(link)); 196 }); 197 // only process the link once 198 Frontend.SessionPropertyChanged -= handler; 199 }; 200 #if LOG4NET 201 Logger.Info("Delaying opening the link as the session isn't initialized yet..."); 202 #endif 203 // install event handler and wait till the session gets initialized 204 Frontend.SessionPropertyChanged += handler; 205 } else { 206 Gtk.Application.Invoke((o, e) => { 207 Frontend.OpenLink(new Uri(link)); 208 }); 209 } 210 } 211 InitializeLifetimeService()212 public override object InitializeLifetimeService() 213 { 214 // live forever 215 return null; 216 } 217 } 218 } 219