public bool TrySendNextLine2()
        {
            string logtext       = null;
            int    loglevel      = 0;
            float  logprogress   = -1;
            string printeraction = null;
            GCode  historygc     = null;
            GCode  hostCommand   = null;
            bool   lineInc       = false;

            if (!garbageCleared)
            {
                return(false);
            }
            try
            {
                lock (nextlineLock)
                {
                    if (pingpong && !readyForNextSend)
                    {
                        return(false);
                    }
                    if (!connected)
                    {
                        return(false);            // Not ready yet
                    }
                    GCode gc = null;
                    try
                    {
                        // then check for manual commands
                        if (injectCommands.Count > 0 && !job.exclusive)
                        {
                            lock (history)
                            {
                                gc = injectCommands.First.Value;
                                if (gc.hostCommand)
                                {
                                    hostCommand = gc;
                                }
                                else
                                {
                                    if (gc.M == 110)
                                    {
                                        lastline = gc.N;
                                    }
                                    else //if (gc.M != 117)
                                    {
                                        gc.N    = ++lastline;
                                        lineInc = true;
                                    }
                                    if (!pingpong && receivedCount() + gc.orig.Length > receiveCacheSize)
                                    {
                                        if (lineInc)
                                        {
                                            --lastline;
                                        }
                                        return(false);
                                    }                                                                                                                // printer cache full
                                    if (pingpong)
                                    {
                                        readyForNextSend = false;
                                    }
                                    else
                                    {
                                        lock (nackLines) { nackLines.AddLast(gc.orig.Length); }
                                    }
                                    virtualPrinter.receiveLine(gc);
                                    bytesSend += gc.orig.Length;
                                }
                                injectCommands.RemoveFirst();
                            }
                            if (!gc.hostCommand)
                            {
                                linesSend++;
                                lastCommandSend = DateTime.Now.Ticks;
                                historygc       = gc;
                            }
                            con.analyzer.Analyze(gc);
                            if (job.dataComplete == false)
                            {
                                if (injectCommands.Count == 0)
                                {
                                    printeraction = Trans.T("L_IDLE");
                                }
                                else
                                {
                                    printeraction = Trans.T1("L_X_COMMANDS_WAITING", injectCommands.Count.ToString());
                                }
                            }
                            return(true);
                        }
                        // do we have a printing job?
                        if (job.dataComplete && !paused)
                        {
                            lock (history)
                            {
                                gc = job.PeekData();
                                if (gc.hostCommand)
                                {
                                    hostCommand = gc;
                                }
                                else
                                {
                                    if (gc.M == 110)
                                    {
                                        lastline = gc.N;
                                    }
                                    else //if (gc.M != 117)
                                    {
                                        gc.N    = ++lastline;
                                        lineInc = true;
                                    }
                                    string cmd = gc.getAscii(true, true);
                                    if (!pingpong && receivedCount() + cmd.Length /*gc.orig.Length*/ > receiveCacheSize)
                                    {
                                        if (lineInc)
                                        {
                                            --lastline;
                                        }
                                        return(false);
                                    }                                                                                                                               // printer cache full
                                    if (pingpong)
                                    {
                                        readyForNextSend = false;
                                    }
                                    else
                                    {
                                        lock (nackLines) { nackLines.AddLast(cmd.Length /*gc.orig.Length*/); }
                                    }
                                    virtualPrinter.receiveLine(gc);
                                    bytesSend += cmd.Length; // gc.orig.Length;
                                }
                                job.PopData();
                            }
                            if (!gc.hostCommand)
                            {
                                linesSend++;
                                lastCommandSend = DateTime.Now.Ticks;
                                printeraction   = Trans.T1("L_PRINTING..ETA", job.ETA); //"Printing...ETA " + job.ETA;
                                if (job.maxLayer > 0)
                                {
                                    printeraction += " " + Trans.T2("L_LAYER_X/Y", con.analyzer.layer.ToString(), job.maxLayer.ToString()); // Layer " + analyzer.layer + "/" + job.maxLayer;
                                }
                                logprogress = job.PercentDone;
                            }
                            con.analyzer.Analyze(gc);
                            return(true);
                        }
                    }
                    catch (InvalidOperationException ex)
                    {
                        logtext  = Trans.T("L_ERROR_SENDING_DATA:") + ex; // "Error sending data:" + ex;
                        loglevel = 2;
                    }
                }
            }
            finally
            {
                // need to extract log/event calls because they cause deadlocks inside
                // the lock statement.
                if (hostCommand != null)
                {
                    Main.main.Invoke(Main.main.executeHostCall, hostCommand);
                }
                if (historygc != null)
                {
                    con.log(historygc.getAscii(true, true), false, 0);
                }
                if (logtext != null)
                {
                    con.log(logtext, false, loglevel);
                }
                if (printeraction != null)
                {
                    con.firePrinterAction(printeraction);
                }
                if (logprogress >= 0 && Math.Abs(lastlogprogress - logprogress) > 0.3)
                {
                    lastlogprogress = logprogress;
                    con.FireJobProgressAsync(job.PercentDone);
                }
            }
            return(false);
        }