if ($time - $row['start_time'] > 1.5 * ShuttleSchedule::get_interval($route_id))
	  continue;

	$stop_id = $row['stop_id'];
	$next_seconds = -1;
	$source = 'null';

	if ($route_preds = NextBusReader::get_predictions($route_id)) {
	  $stop_preds = $route_preds[$stop_id];
	  if ($stop_preds) {
	    $source = 'nextbus';
	    $next_seconds = $stop_preds[0];
	    $next_time = $time + $next_seconds;
	  }
	} else {
	  $stop_times = ShuttleSchedule::get_next_scheduled_loop($route_id, $row['start_time']);
	  foreach ($stop_times as $stop_time) {
	    if ($stop_time['nextBusId'] == $stop_id) {
	      $source = 'schedule';
	      $next_time = $stop_time['nextScheduled'];
	      $next_seconds = $next_time - $time;
	      $stopname = $stop_time['title'];
	      break;
	    }
	  }
	}

	if ($next_seconds > 0 && $next_seconds < SHUTTLE_NOTIFY_THRESHOLD) {
	  $shuttle = ShuttleSchedule::get_title($route_id);
	  $minutes = intval($next_seconds / 60);
	  $timestr = date('g:ia', $next_time);
function list_stop_times($route, $time, $gps_active, $singleStopId=NULL) {

  $stops = Array();

  $schedStops = ShuttleSchedule::get_next_scheduled_loop($route, $time);
  $nbStopsInfo = NextBusReader::get_route_info($route);
  $interval = ShuttleSchedule::get_interval($route);
  $end_time = ShuttleSchedule::get_last_run($route, $time) + $interval;

  // this array will contain the stops to be highlighted
  $upcoming_stops = Array();
  $previous_time = 0;

  if ($gps_active) {
    $nbPredictions = NextBusReader::get_predictions($route, $time);
  }

  if (!$nbPredictions) {
    // this condition might occur because we have a delay in 
    // deciding the gps is offline after the bus has actually
    // gone out of service
    $gps_active = FALSE;
  }

  // this gives an array of seconds until next arrival
  // at each stop
  foreach ($schedStops as $index => $stop) {
    $stopData = Array();
    $stopId = $stop['nextBusId'];
    $stopData['id'] = $stopId;
    $stopData['title'] = $stop['title'];
    $stopData['lat'] = $nbStopsInfo[$stopId]['lat'];
    $stopData['lon'] = $nbStopsInfo[$stopId]['lon'];
    $stopData['next'] = $stop['nextScheduled'];
    if ($gps_active && $stopData['next'] !== 0) {
      $stopData['predictions'] = Array();
      if (!$nbPredictions[$stopId]) {
	error_log("no predictions for $stopId on route $route. predictions:" . serialize($nbPredictions));
	continue;
      }
      sort($nbPredictions[$stopId]);
      $firstPrediction = array_shift($nbPredictions[$stopId]);
      $stopData['next'] = $time + $firstPrediction;
      foreach ($nbPredictions[$stopId] as $prediction) {
	if ($time + (int) $prediction > $end_time) {
	  break;
	}
	$stopData['predictions'][] = $prediction - $firstPrediction;
      }
    }

    // short circuit if a single stop is requested
    if ($stopId == $singleStopId) {
      return $stopData;
    }

    if ($stopData['next'] < $previous_time && $stopData['next'] - $time < $interval) {
      $stopData['upcoming'] = TRUE;
    }

    $stops[] = $stopData;
    $previous_time = $stopData['next'];
  }
  if ($stops[0]['next'] < $stops[count($stops) - 1]['next'] && $stops[0]['next'] - $time < $interval) {
    $stops[0]['upcoming'] = TRUE;
  }
  return $stops;
}