diff -rupN vdr-1.7.22_gotoxx_patched//diseqc.c vdr-1.7.22_gotoxx_nessiedvb_patched//diseqc.c
--- vdr-1.7.22_gotoxx_patched//diseqc.c	2012-01-08 12:08:20.495922647 +0100
+++ vdr-1.7.22_gotoxx_nessiedvb_patched//diseqc.c	2012-01-08 12:12:37.381918105 +0100
@@ -250,7 +250,8 @@ cDiseqc::eDiseqcActions cDiseqc::Execute
           case 'V': return daVoltage18;
           case 'A': return daMiniA;
           case 'B': return daMiniB;
-	      case 'G': return daGotoX;          
+	      case 'G': return daGotoX;    
+          case 'g': return daGotoX_Virtual;	            
           case 'W': *CurrentAction = Wait(*CurrentAction); break;
           case 'S': *CurrentAction = GetScrBank(*CurrentAction); break;
           case '[': *CurrentAction = GetCodes(*CurrentAction, Codes, MaxCodes);
@@ -276,6 +277,7 @@ cDiseqc::eDiseqcActions cDiseqc::TestFor
         switch (*(*CurrentAction)++) {
           case ' ': break;
 	      case 'G': return daGotoX;    
+          case 'g': return daGotoX_Virtual;	            
           default: return daNone;
           }
         }
diff -rupN vdr-1.7.22_gotoxx_patched//diseqc.h vdr-1.7.22_gotoxx_nessiedvb_patched//diseqc.h
--- vdr-1.7.22_gotoxx_patched//diseqc.h	2012-01-08 12:08:20.495922647 +0100
+++ vdr-1.7.22_gotoxx_nessiedvb_patched//diseqc.h	2012-01-08 12:12:37.381918105 +0100
@@ -50,7 +50,8 @@ public:
     daVoltage18,
     daMiniA,
     daMiniB,
-    daGotoX,    
+    daGotoX,
+    daGotoX_Virtual,        
     daScr,
     daCodes,
     };
diff -rupN vdr-1.7.22_gotoxx_patched//dvbdevice.c vdr-1.7.22_gotoxx_nessiedvb_patched//dvbdevice.c
--- vdr-1.7.22_gotoxx_patched//dvbdevice.c	2012-01-08 12:10:21.273920511 +0100
+++ vdr-1.7.22_gotoxx_nessiedvb_patched//dvbdevice.c	2012-01-08 12:12:37.383918105 +0100
@@ -460,6 +460,56 @@ bool cDvbTuner::IsTunedTo(const cChannel
   return strcmp(channel.Parameters(), Channel->Parameters()) == 0;
 }
 
+void HandleGotox_Virtual(int fd_frontend, int new_source)
+{
+  int gotoXTable[10] = { 0x00, 0x02, 0x03, 0x05, 0x06, 0x08, 0x0A, 0x0B, 0x0D, 0x0E };
+  int satlong;
+
+  if (Setup.UseGotox == 0)
+    return;
+
+  // Check if zapped into new source position?
+    if ((new_source & 0xFF000000) != 0x53000000) 
+      return; // Fail, not S type source
+    satlong = (new_source & 0x00000FFFF);
+    if (new_source & 0x00008000) {
+      satlong ^= 0x0000FFFF; satlong++; satlong *= (-1);
+    }
+    int Long=Setup.GotoxEW ? -Setup.GotoxLong : Setup.GotoxLong;
+    int Lat=Setup.GotoxSN ? -Setup.GotoxLat : Setup.GotoxLat;
+    double azimuth=M_PI+atan(tan((satlong-Long)*M_PI/1800)/sin(Lat*M_PI/1800));
+    double x=acos(cos((satlong-Long)*M_PI/1800)*cos(Lat*M_PI/1800));
+    double elevation=atan((cos(x)-0.1513)/sin(x));
+    double SatHourangle=180+atan((-cos(elevation)*sin(azimuth))/(sin(elevation)*cos(Lat*M_PI/1800)
+			   -cos(elevation)*sin(Lat*M_PI/1800)*cos(azimuth)))*180/M_PI;
+    int tmp=(int)(fabs(180-SatHourangle)*10);
+    tmp=(tmp/10)*0x10 + gotoXTable[ tmp % 10 ];
+    int p2=(tmp%0x0100);
+    int p1=(tmp/0x0100);
+    if (SatHourangle < 180)
+      p1 |= 0xe0;
+    else
+      p1 |= 0xd0;
+
+    // Send 1st GotoX command, then wait > 15ms
+    uchar gotox_bytes[5] = { 0xe0, 0x31, 0x6e, p1, p2};
+    struct dvb_diseqc_master_cmd gotox_cmd;
+    memcpy(gotox_cmd.msg, gotox_bytes, 5);
+    gotox_cmd.msg_len = 5;
+    CHECK(ioctl(fd_frontend, FE_DISEQC_SEND_MASTER_CMD, &gotox_cmd));
+    cCondWait::SleepMs(20);
+
+    // Send repeated GotoX command, then wait > 15ms
+    if (Setup.GotoxRepeat) {
+      gotox_bytes[0] = 0xe1;
+      memcpy(gotox_cmd.msg, gotox_bytes, 5);
+      CHECK(ioctl(fd_frontend, FE_DISEQC_SEND_MASTER_CMD, &gotox_cmd));
+      cCondWait::SleepMs(20);
+    }
+
+    dsyslog("DiSEqC GotoX_Virtual done.");
+}
+
 void HandleGotox(int fd_frontend, int new_source)
 {
   
@@ -738,15 +779,16 @@ void cDvbTuner::ExecuteDiseqc(const cDis
       if (da == cDiseqc::daNone)
          break;
       switch (da) {
-        case cDiseqc::daToneOff:   CHECK(ioctl(fd_frontend, FE_SET_TONE, SEC_TONE_OFF)); break;
-        case cDiseqc::daToneOn:    CHECK(ioctl(fd_frontend, FE_SET_TONE, SEC_TONE_ON)); break;
-        case cDiseqc::daVoltage13: CHECK(ioctl(fd_frontend, FE_SET_VOLTAGE, SEC_VOLTAGE_13)); break;
-        case cDiseqc::daVoltage18: CHECK(ioctl(fd_frontend, FE_SET_VOLTAGE, SEC_VOLTAGE_18)); break;
-        case cDiseqc::daMiniA:     CHECK(ioctl(fd_frontend, FE_DISEQC_SEND_BURST, SEC_MINI_A)); break;
-        case cDiseqc::daMiniB:     CHECK(ioctl(fd_frontend, FE_DISEQC_SEND_BURST, SEC_MINI_B)); break;
-        case cDiseqc::daGotoX:     HandleGotox(fd_frontend, channel.Source()); break;
-        case cDiseqc::daCodes:     CHECK(ioctl(fd_frontend, FE_DISEQC_SEND_MASTER_CMD, &cmd)); break;
-        default: esyslog("ERROR: unknown diseqc command %d", da);
+        case cDiseqc::daToneOff:        CHECK(ioctl(fd_frontend, FE_SET_TONE, SEC_TONE_OFF)); break;
+        case cDiseqc::daToneOn:         CHECK(ioctl(fd_frontend, FE_SET_TONE, SEC_TONE_ON)); break;
+        case cDiseqc::daVoltage13:      CHECK(ioctl(fd_frontend, FE_SET_VOLTAGE, SEC_VOLTAGE_13)); break;
+        case cDiseqc::daVoltage18:      CHECK(ioctl(fd_frontend, FE_SET_VOLTAGE, SEC_VOLTAGE_18)); break;
+        case cDiseqc::daMiniA:          CHECK(ioctl(fd_frontend, FE_DISEQC_SEND_BURST, SEC_MINI_A)); break;
+        case cDiseqc::daMiniB:          CHECK(ioctl(fd_frontend, FE_DISEQC_SEND_BURST, SEC_MINI_B)); break;
+        case cDiseqc::daGotoX:          HandleGotox(fd_frontend, channel.Source()); break;
+        case cDiseqc::daGotoX_Virtual:  HandleGotox_Virtual(fd_frontend, channel.Source()); break;
+        case cDiseqc::daCodes:          CHECK(ioctl(fd_frontend, FE_DISEQC_SEND_MASTER_CMD, &cmd)); break;
+        default:                        esyslog("ERROR: unknown diseqc command %d", da);
         }
       }
   if (scr)
@@ -762,7 +804,7 @@ bool cDvbTuner::TestDiseqcForGotoXX(cons
     cDiseqc::eDiseqcActions da = Diseqc->TestForGotoXX(&CurrentAction);
     if (da == cDiseqc::daNone)
       break;
-    if (da == cDiseqc::daGotoX)
+    if((da == cDiseqc::daGotoX) || (da == cDiseqc::daGotoX_Virtual))
       return true;
   }
   return false;
