Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > OOP
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Grupo de Teaming del ClubDelphi

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 16-01-2006
[Gunman] [Gunman] is offline
Miembro
 
Registrado: dic 2004
Ubicación: Pedreguer.
Posts: 355
Poder: 20
[Gunman] Va por buen camino
Eliminando items en TTimer...

Bueno, estaba perfeccionando un programita que tenía, algo así como una radio despertador de estas que a tal hora suena la radio, pues igual.
El programa comparaba cada 0,1 segundos el hora local con una hora en un fichero .ini donde estaba la programación, si la hora del sistema era una hora indicada como para iniciarse, el programa, cargaba una canción aleatoria de una lista de canciones. Bueno, ahora quería perfeccionar el programa de esta forma: cada vez que se reproduzca una canción, cuando termina de reproducirse, esta es eliminada de la lista de canciones. Si la lista de canciones, se queda con 0 items, carga las canciones de otra lista. Para esto he hecho dos listas, la songs.ls y la TEMP_songs.ls. El programa maneja la lista TEMP_songs.ls y sólo usa la songs.ls cuando los items se quedan a 0. Bueno, el problema viene que cuando debería eliminar la canción de la lista me crea una excepción, la típica (creo yo) en lista: List Index Out of Bounds (-1).
Bueno os pongo todo el código donde se maneja la variable SongsList (TStringList) y os indico donde creo que está el error:
Código Delphi [-]
  public
    { Public declarations }
    SongsList: TStringList; //Declaración de la variable
Código que se inicia al crear el programa.
Código Delphi [-]
procedure TMainFrm.FormCreate(Sender: TObject);
var
  Hnd: Integer;
  Reg: TRegistry;
begin
  SongsList := TStringList.Create;
  
  {...}

  Hnd := FileCreate('C:\AdMies\songs.ls');
  FileClose(Hnd);

  Hnd := FileCreate('C:\AdMies\TEMP_songs.ls');
  FileClose(Hnd);

  {La función AddFiles en la unidad AddCurDir sirve para añadir items al archivo songs.ls, no hay ningún problema con el, puesto que no lo he modificado...}
  AddCurDir.CurrentDir := ExtractFilePath(Application.ExeName);
  AddCurDir.AddFiles;

{Combrueba que el TEMP_songs.ls no este vacío, si es así añade las canciones de songs.ls}
  SongsList.LoadFromFile('C:\AdMies\TEMP_songs.ls');
  if SongsList.Count = 0 then
  begin
    SongsList.LoadFromFile('C:\AdMies\songs.ls');
    SongsList.SaveToFile('C:\AdMies\TEMP_songs.ls');
  end;

  {...}
end;
Bueno, éste es el código que se ejecuta cada 0,1 segundos:
Código Delphi [-]
procedure TMainFrm.TimerTimer(Sender: TObject);
var
  LocalTime: TSystemTime;
  Prog: TIniFile;
  ProgTable: TValueListEditor;
  i: Integer;
begin
  GetLocalTime(LocalTime);
  Prog := TIniFile.Create('C:\AdMies\prog.ini');
  ProgTable := TValueListEditor.Create(MainFrm);
  Prog.ReadSectionValues('Programació',ProgTable.Strings);

{Aquí comprueba que los items de SongsList.Count no sean 0, de serlo así carga los items de songs.ls y los guarda en TEMP_songs.ls, no creo que aquí este el problema porque antes, ya lo he usado y no me ha hecho fallo}
  if SongsList.Count = 0 then
  begin
    SongsList.LoadFromFile('C:\AdMies\songs.ls');
    SongsList.SaveToFile('C:\AdMies\TEMP_songs.ls');
  end;

  for i := 1 to ProgTable.RowCount-1 do
  begin
    {Este primer if, ni lo he tocado, no creo que el problema este aquí}
    if (SystemTimeToDateTime(LocalTime) = StrToTime(ProgTable.Keys[i]) and
       (SongsList.Count > 0) then
    begin
      Randomize;
      MPlayer.FileName := SongsList.Strings[Random(SongsList.Count)];
     {...}
      MPlayer.Open;
      MPlayer.Play;
    end
    else
    {Creo que el problema estará aquí, en el SongsList.Delete}
    if SystemTimeToDateTime(LocalTime) = StrToTime(ProgTable.Values[
       ProgTable.Keys[i]])) then
    begin
      if MPlayer.FileName <> '' then
      begin
        if SongsList.Count > 0 then
        SongsList.Delete(SongsList.IndexOf(MPlayer.FileName));

        MPlayer.Stop;
        SongsList.SaveToFile('C:\AdMies\TEMP_songs.ls');
      end;
      {...}
    end
    else
{Último if, en caso de no haber pasado el tiempo indicado y haberse terminado la canción, entonces pasa a otra canción}
    if (MPlayer.FileName <> '') and (MPlayer.Length = MPlayer.Position) then
    begin
      Randomize;

      if SongsList.Count > 0 then
      SongsList.Delete(SongsList.IndexOf(MPlayer.FileName));
      SongsList.SaveToFile('C:\AdMies\TEMP_songs.ls');

      MPlayer.FileName := SongsList.Strings[Random(SongsList.Count)];
      {...}
      MPlayer.Open;
      MPlayer.Play;
    end;
  end;
  ProgTable.Free;
  Prog.Free;
end;
Bueno, creo que no me dejado nada. ¡Ah si! Me dejava la liberación de la variable, la he puesto en el OnDestroy del Form.
Estoy perdido del todo, no sé porqué me da esta excepción. No estoy seguro de haberla localizarla correctamente.
Bueno, espero ansioso vuestras respuestas, y gracias por leer este rollo. :P
__________________
l2prog.co.nr
Responder Con Cita
  #2  
Antiguo 16-01-2006
Avatar de OSKR
OSKR OSKR is offline
Miembro
 
Registrado: nov 2004
Ubicación: San Cristóbal/Táchira/Venezuela
Posts: 389
Poder: 20
OSKR Va por buen camino
Por lo q veo el MPlayer es publico, q pasa si se ejecuta otro evento del TTimer sin haber terminado el anterior? yo empezaría por poner como primera instrucción el Enabled del Timer como falso.
__________________
Los Estados Unidos parecen destinados por la Providencia para plagar la América de miserias a nombre de la libertad."
Simón Bolívar
(Carta al Coronel Inglés Patricio Cambell 05/08/1829).
Responder Con Cita
  #3  
Antiguo 16-01-2006
Avatar de Lepe
[Lepe] Lepe is offline
Miembro Premium
 
Registrado: may 2003
Posts: 7.424
Poder: 28
Lepe Va por buen camino
El problema que yo le veo, es estar mirando cada 100 milisegundos la hora

Lo lógico, ver la tarea más cercana y programar el timer para esa fecha. Llegada esa hora, mostrar alerta al usuario y reprogramar el timer para la siguiente fecha de aviso.

Edito: El código que ha de ejecutarse cada 100 milisegundos es demasiado extenso, debería ser muy pocas lineas, de lo contrario, puedes perder eventos, porque uno llegue cuando el anterior no se ha terminado, y en el peor de los casos, puede que esté en un evento que no hay tareas definidas, pero en el siguiente evento, que se pierde por solaparse con el primero, si puede haber tareas. No sé si queda claro o no....

Mira estos hilos:
http://www.clubdelphi.com/foros/show...t=recordatorio

y los que allí se menciona.

saludos
__________________
Si usted entendió mi comentario, contácteme y gustosamente,
se lo volveré a explicar hasta que no lo entienda, Gracias.

Última edición por Lepe fecha: 16-01-2006 a las 18:18:58.
Responder Con Cita
  #4  
Antiguo 16-01-2006
[Gunman] [Gunman] is offline
Miembro
 
Registrado: dic 2004
Ubicación: Pedreguer.
Posts: 355
Poder: 20
[Gunman] Va por buen camino
Mmmm, CompareDate... Bonita función existe la CompareTime? Veo que si! Fantástico, esto me ayudará mucho, pero de todas formas. Cada X tiempo se deberá ejecutar la función compareTime no? No me evito el TTimer, creo...
__________________
l2prog.co.nr
Responder Con Cita
  #5  
Antiguo 17-01-2006
Avatar de Lepe
[Lepe] Lepe is offline
Miembro Premium
 
Registrado: may 2003
Posts: 7.424
Poder: 28
Lepe Va por buen camino
Como bien dices, el Timer lo necesitas, pero en lugar de ponerle un interval de 100 milisegundos, le pones el total que necesites, por ejemplo:

Código Delphi [-]
var FechaAviso:Tdatetime; // tendrá la fecha y hora de la nota o tarea
     miliseg:Word;
begin
milisegundos := MillisecondsBetween(fechaAviso, Now);
if miliseg > 1000 then
begin
 Timer1.Interval := miliseg;
 Timer1.Enabled := true;
end;
Como miliseg es de tipo Word, creo que permitía almacenar algo así como 9 semanas, es decir, puedes establecer 1 sola vez el timer para que te avise dentro de 9 semanas.

La función compareTime no la necesitas, una fecha y hora se guarda como un número en coma flotante, donde la parte entera corresponde a los dias que han pasado sobre la fecha base del calendario,(creo recordar que la fecha base de los calendarios es 01/01/1900, de hecho si asignas a una fecha el valor cero, te dará 31/12/1899, un día menos ). La parte fraccionaria de ese número es la hora.

Si quieres saber si una fecha es más grande que otra...:
Código Delphi [-]
  if fechaAviso > Now() then

Sumar dias, horas o minutos a fechas:
Código Delphi [-]
  const UnDia = 1; 
           UnaHora = 1 / 24; // sumamos la parte fraccionaria de un dia (24 horas)
          UnMinuto = 1 /( 24 *60);
         UnSegundo = UnMinuto / 60;
begin
   FechaAviso := now() + undia; // la misma hora que hoy, pero con fecha de mañana

saludos
__________________
Si usted entendió mi comentario, contácteme y gustosamente,
se lo volveré a explicar hasta que no lo entienda, Gracias.
Responder Con Cita
  #6  
Antiguo 17-01-2006
[Gunman] [Gunman] is offline
Miembro
 
Registrado: dic 2004
Ubicación: Pedreguer.
Posts: 355
Poder: 20
[Gunman] Va por buen camino
Gente, ya he modificado el programilla. Os dejo el resultado, no me funciona. No encuentro el fallo (seguro que es una tontería...). Os lo explico un poco el código también.
Tenéis que saber, que el archivo prog.ini tiene la siguiente estructura:
[Programació]
HoraPlay=HoraStop
Lo primero que he hecho ha sido crear un tipo registro donde almacenaré el Intervalo que ha de tener el TTimer (se canculará posteriormente) y la tarea que ha de hacer, pues el programa ha de reproducir música durante X minutos, donde X lo configura el usuario en un .ini.
Código Delphi [-]
type
  TTask = (tPlay, tStop);
  TNextTime = record
    Interval: Cardinal;
    Item: Integer;
    Task: TTask;
  end;
He hecho un procedimiento que calcula el intervalo que ha de tener el TTime, dependiendo si se la siguiente tarea es reproducir o detener la reproducción. Aquí lo pongo:
Código Delphi [-]
procedure TMainFrm.CalcInterval(Task: TTask);
var
  Prog: TIniFile;
  ProgTable: TValueListEditor;
  ProgTime: Integer;
begin
  
  {Prog.ini, es donde se encuentra la programación horaria; ProgTable, 
   es la tabla donde se abrirá la programación, yo he creado una tabla 
   porqué me resulta más facil de manejar que con archivos Ini}
  Prog := TIniFile.Create('C:\AdMies\prog.ini');
  ProgTable := TValueListEditor.Create(MainFrm);
  Prog.ReadSectionValues('Programació',ProgTable.Strings);

  {Aquí es donde empieza el lío... Dependiendo si la tarea es 
   reproducir o parar ejecuta un código u otro}
  if Task = tPlay then
  {Recorre toda la programación con un for y...}
  for ProgTime := 1 to ProgTable.RowCount-1 do
  begin
    {Cuando se recorre el primer item, asigna al valor de NextTime.Interval,
      la diferencia en milisegundos de la hora a que va a empezar la música
      y la hora actual. También, asgina al valor de NextTime.Item, el valor 
      de 1, es decir, el primer item de la programación}
    if (ProgTime = 1) then
    begin
      NextTime.Interval := MillisecondsBetween(StrToTime(
      ProgTable.Keys[ProgTime]), Now);
      NextTime.Item := 1;
    end
    {Si no recorre el primer item de la programación, comprueba que la
     diferencia entre la hora programada y la actual sea menor, si es 
     así hace lo mismo que lo dicho anteriormente}
    else if MillisecondsBetween(StrToTime(ProgTable.Keys[ProgTime]),
    Now) < NextTime.Interval then
    begin
      NextTime.Interval := MillisecondsBetween(StrToTime(
        ProgTable.Keys[ProgTime]), Now);
      NextTime.Item := ProgTime;
    end;
  end
  else {En caso de que la tarea a realizar no sea la de reproducir, sino
  la de detener una reproducción, entonces, el próximo intervalo de 
  tiempo, será la diferencia entre la hora de detención de la reproducción
  y la actual}
  NextTime.Interval := MillisecondsBetween(StrToTime(
    ProgTable.Values[ProgTable.Keys[NextTime.Item]]), Now);

  Timer.Interval := NextTime.Interval;
  Prog.Free;
  ProgTable.Free;
end;

Bueno, he hecho dos pequeños procedimientos, uno de Play y otro de Stop, el de Stop no tiene secreto, de todas formas, aquí lo pongo:
Código Delphi [-]
procedure TMainFrm.Stop;
begin
  MPlayer.Stop;  //Detiene la reproducción en curso...
  NextTime.Task := tPlay; //Asigna el valor tPlay a la propiedad Task
  calcInterval(tPlay);  //Calcula el intervalo para la próxima reproducción
  {Más cosillas de la interfaz}
end;
Ése era el stop, y ahora el play, un poco más larguito, pero sencillo:
Código Delphi [-]
procedure TMainFrm.Play(FileName: String);
begin
  {Elimina la canción que se va a reproducir de la lista de canciones para
   que no se vuelva a repetir hasta que todas se hayan reproducido, por
   lo menos, una vez}
  if SongsList.Count > 0 then
  begin
    SongsList.Delete(SongsList.IndexOf(FileName));
    SongsList.SaveToFile('C:\AdMies\TEMP_songs.ls');
  end;

  {En caso de que todas las canciones se hayan escuchado, vuelve a 
   cargar las canciones desde la lista songs.ls a la lista TEMP_songs.ls}
  if SongsList.Count = 0 then
  begin
    SongsList.LoadFromFile('C:\AdMies\songs.ls');
    SongsList.SaveToFile('C:\AdMies\TEMP_songs.ls');
  end;

  MPlayer.FileName := FileName;  //sin comentarios
  {Cosillas de la interfaz}
  MPlayer.Open;
  MPlayer.Play; 
  NextTime.Task := tStop;  //La próxima tarea será la de detener
  calcInterval(tStop);  //calcula cuantos milisegundos faltan para detener
end;
Después de estos tres procedimientos está el evento OnCreate del programa, aquí os dejo la parte que nos interesa del código:
Código Delphi [-]
procedure TMainFrm.FormCreate(Sender: TObject);
var
  Hnd: Integer;
  Reg: TRegistry;
begin
  SongsList := TStringList.Create;

  {Otras cosillas que no influyen}

  {Crea los archivos songs.ls y TEMP_songs.ls}
  Hnd := FileCreate('C:\AdMies\songs.ls');
  FileClose(Hnd);

  Hnd := FileCreate('C:\AdMies\TEMP_songs.ls');
  FileClose(Hnd);

  {Estas sentencias sirven para añadir las canciones de la carpeta donde 
   se encuentra el programa a la lista songs.ls}
  AddCurDir.CurrentDir := ExtractFilePath(Application.ExeName);
  AddCurDir.AddFiles;

  {Carga a la lista SongsList las canciones de TEMP_songs.ls}
  SongsList.LoadFromFile('C:\AdMies\TEMP_songs.ls');
  {En caso de que TEMP_songs.ls no tenga canciones, se añaden las del 
   archivo songs.ls}
  if SongsList.Count = 0 then
  begin
    SongsList.LoadFromFile('C:\AdMies\songs.ls');
    SongsList.SaveToFile('C:\AdMies\TEMP_songs.ls');
  end;

  {Otras cosillas}

  NextTime.Task := tPlay; //Empieza a reproducir
  calcInterval(tPlay); //Calcula el intervalo de tiempo para reproducir
  Timer.Enabled := True;  //Activa el temporizador

  {Cosillas de la interfaz}
end;
Y finalmente, el OnTimer del TTimer:
Código Delphi [-]
procedure TMainFrm.TimerTimer(Sender: TObject);
begin
  //Si la tarea a realizar es reproducir...
  if NextTime.Task = tPlay then
  Play(SongsList.Strings[Random(SongsList.Count)])  //Una canción 
                                                    //aleatoria de la lista SongsList
  {En caso de que la tarea sea la de detener...}
  else if NextTime.Task = tStop then
   Stop; //detiene la reproducción
end;

Siento haber puesto todo esto aquí, ahora no tenéis excusa de que os falta código... Bueno, voy a ver si resuelvo esto. Espero impaciente vuestra ayuda. Muchas grácias!
__________________
l2prog.co.nr
Responder Con Cita
  #7  
Antiguo 20-01-2006
[Gunman] [Gunman] is offline
Miembro
 
Registrado: dic 2004
Ubicación: Pedreguer.
Posts: 355
Poder: 20
[Gunman] Va por buen camino
Sigo sin conseguir solucionar esto... Estoy desesperado, habéis encontrado la solución ya? Bueno, sigo investigando... Seguro que al final era una tontería...
__________________
l2prog.co.nr
Responder Con Cita
  #8  
Antiguo 02-02-2006
[Gunman] [Gunman] is offline
Miembro
 
Registrado: dic 2004
Ubicación: Pedreguer.
Posts: 355
Poder: 20
[Gunman] Va por buen camino
Solucionado!
__________________
l2prog.co.nr
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Creación de una lista de items metalfox6383 Varios 2 19-09-2005 12:57:54
Contar Items en un MainMenu AGAG4 Varios 4 07-10-2004 17:59:01
ListBox Items Hint (MUY URGENTE !!!!) jymy788 Varios 2 17-09-2004 09:41:58
Crear DBComobox con items oliverinf OOP 4 14-09-2004 17:20:21
Componente que tenga checkboxes como items k_miragaya OOP 2 22-07-2004 09:55:54


La franja horaria es GMT +2. Ahora son las 21:12:04.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi