1 // -*- mode: cpp; mode: fold -*-
3 // $Id: acqprogress.cc,v 1.24 2003/04/27 01:56:48 doogie Exp $
4 /* ######################################################################
6 Acquire Progress - Command line progress meter
8 ##################################################################### */
10 // Include files /*{{{*/
11 #include "acqprogress.h"
12 #include <apt-pkg/acquire-item.h>
13 #include <apt-pkg/acquire-worker.h>
14 #include <apt-pkg/strutl.h>
15 #include <apt-pkg/error.h>
27 // AcqTextStatus::AcqTextStatus - Constructor /*{{{*/
28 // ---------------------------------------------------------------------
30 AcqTextStatus::AcqTextStatus(unsigned int &ScreenWidth,unsigned int Quiet) :
31 ScreenWidth(ScreenWidth), Quiet(Quiet)
35 // AcqTextStatus::Start - Downloading has started /*{{{*/
36 // ---------------------------------------------------------------------
38 void AcqTextStatus::Start()
40 pkgAcquireStatus::Start();
45 // AcqTextStatus::IMSHit - Called when an item got a HIT response /*{{{*/
46 // ---------------------------------------------------------------------
48 void AcqTextStatus::IMSHit(pkgAcquire::ItemDesc &Itm)
54 cout << '\r' << BlankLine << '\r';
56 cout << _("Hit ") << Itm.Description;
57 if (Itm.Owner->FileSize != 0)
58 cout << " [" << SizeToStr(Itm.Owner->FileSize) << "B]";
63 // AcqTextStatus::Fetch - An item has started to download /*{{{*/
64 // ---------------------------------------------------------------------
65 /* This prints out the short description and the expected size */
66 void AcqTextStatus::Fetch(pkgAcquire::ItemDesc &Itm)
69 if (Itm.Owner->Complete == true)
78 cout << '\r' << BlankLine << '\r';
80 cout << _("Get:") << Itm.Owner->ID << ' ' << Itm.Description;
81 if (Itm.Owner->FileSize != 0)
82 cout << " [" << SizeToStr(Itm.Owner->FileSize) << "B]";
86 // AcqTextStatus::Done - Completed a download /*{{{*/
87 // ---------------------------------------------------------------------
88 /* We don't display anything... */
89 void AcqTextStatus::Done(pkgAcquire::ItemDesc &Itm)
94 // AcqTextStatus::Fail - Called when an item fails to download /*{{{*/
95 // ---------------------------------------------------------------------
96 /* We print out the error text */
97 void AcqTextStatus::Fail(pkgAcquire::ItemDesc &Itm)
102 // Ignore certain kinds of transient failures (bad code)
103 if (Itm.Owner->Status == pkgAcquire::Item::StatIdle)
107 cout << '\r' << BlankLine << '\r';
109 if (Itm.Owner->Status == pkgAcquire::Item::StatDone)
111 cout << _("Ign ") << Itm.Description << endl;
115 cout << _("Err ") << Itm.Description << endl;
116 cout << " " << Itm.Owner->ErrorText << endl;
122 // AcqTextStatus::Stop - Finished downloading /*{{{*/
123 // ---------------------------------------------------------------------
124 /* This prints out the bytes downloaded and the overall average line
126 void AcqTextStatus::Stop()
128 pkgAcquireStatus::Stop();
133 cout << '\r' << BlankLine << '\r' << flush;
135 if (FetchedBytes != 0 && _error->PendingError() == false)
136 ioprintf(cout,_("Fetched %sB in %s (%sB/s)\n"),
137 SizeToStr(FetchedBytes).c_str(),
138 TimeToStr(ElapsedTime).c_str(),
139 SizeToStr(CurrentCPS).c_str());
142 // AcqTextStatus::Pulse - Regular event pulse /*{{{*/
143 // ---------------------------------------------------------------------
144 /* This draws the current progress. Each line has an overall percent
145 meter and a per active item status meter along with an overall
146 bandwidth and ETA indicator. */
147 bool AcqTextStatus::Pulse(pkgAcquire *Owner)
149 pkgAcquireStatus::Pulse(Owner);
154 enum {Long = 0,Medium,Short} Mode = Long;
156 char Buffer[sizeof(BlankLine)];
157 char *End = Buffer + sizeof(Buffer);
159 if (ScreenWidth >= sizeof(Buffer))
160 ScreenWidth = sizeof(Buffer)-1;
162 // Put in the percent done
163 sprintf(S,"%ld%%",long(double((CurrentBytes + CurrentItems)*100.0)/double(TotalBytes+TotalItems)));
166 for (pkgAcquire::Worker *I = Owner->WorkersBegin(); I != 0;
167 I = Owner->WorkerStep(I))
171 // There is no item running
172 if (I->CurrentItem == 0)
174 if (I->Status.empty() == false)
176 snprintf(S,End-S," [%s]",I->Status.c_str());
185 // Add in the short description
186 if (I->CurrentItem->Owner->ID != 0)
187 snprintf(S,End-S," [%lu %s",I->CurrentItem->Owner->ID,
188 I->CurrentItem->ShortDesc.c_str());
190 snprintf(S,End-S," [%s",I->CurrentItem->ShortDesc.c_str());
193 // Show the short mode string
194 if (I->CurrentItem->Owner->Mode != 0)
196 snprintf(S,End-S," %s",I->CurrentItem->Owner->Mode);
200 // Add the current progress
202 snprintf(S,End-S," %lu",I->CurrentSize);
205 if (Mode == Medium || I->TotalSize == 0)
206 snprintf(S,End-S," %sB",SizeToStr(I->CurrentSize).c_str());
210 // Add the total size and percent
211 if (I->TotalSize > 0 && I->CurrentItem->Owner->Complete == false)
214 snprintf(S,End-S," %lu%%",
215 long(double(I->CurrentSize*100.0)/double(I->TotalSize)));
217 snprintf(S,End-S,"/%sB %lu%%",SizeToStr(I->TotalSize).c_str(),
218 long(double(I->CurrentSize*100.0)/double(I->TotalSize)));
221 snprintf(S,End-S,"]");
226 snprintf(S,End-S,_(" [Working]"));
228 /* Put in the ETA and cps meter, block off signals to prevent strangeness
230 sigset_t Sigs,OldSigs;
232 sigaddset(&Sigs,SIGWINCH);
233 sigprocmask(SIG_BLOCK,&Sigs,&OldSigs);
238 unsigned long ETA = (unsigned long)((TotalBytes - CurrentBytes)/CurrentCPS);
239 sprintf(Tmp," %sB/s %s",SizeToStr(CurrentCPS).c_str(),TimeToStr(ETA).c_str());
240 unsigned int Len = strlen(Buffer);
241 unsigned int LenT = strlen(Tmp);
242 if (Len + LenT < ScreenWidth)
244 memset(Buffer + Len,' ',ScreenWidth - Len);
245 strcpy(Buffer + ScreenWidth - LenT,Tmp);
248 Buffer[ScreenWidth] = 0;
249 BlankLine[ScreenWidth] = 0;
250 sigprocmask(SIG_SETMASK,&OldSigs,0);
252 // Draw the current status
253 if (strlen(Buffer) == strlen(BlankLine))
254 cout << '\r' << Buffer << flush;
256 cout << '\r' << BlankLine << '\r' << Buffer << flush;
257 memset(BlankLine,' ',strlen(Buffer));
258 BlankLine[strlen(Buffer)] = 0;
265 // AcqTextStatus::MediaChange - Media need to be swapped /*{{{*/
266 // ---------------------------------------------------------------------
267 /* Prompt for a media swap */
268 bool AcqTextStatus::MediaChange(string Media,string Drive)
271 cout << '\r' << BlankLine << '\r';
272 ioprintf(cout,_("Media change: please insert the disc labeled\n"
274 "in the drive '%s' and press enter\n"),
275 Media.c_str(),Drive.c_str());
279 while (C != '\n' && C != '\r')
281 int len = read(STDIN_FILENO,&C,1);
282 if(C == 'c' || len <= 0)