예제 #1
0
        private void DeleteBtn_Click(object sender, EventArgs e)
        {
            var btn = (RenderBtn <Track>)sender;

            Tracks.Remove(btn.Tag);

            var firstName = Tracks.FirstOrDefault()?.Name;

            DefaultTrackLeft.ReplaceAllValues(btn.Tag.Name, firstName);
            DefaultTrackRight.ReplaceAllValues(btn.Tag.Name, firstName);

            trackRemoves.Add(btn.Tag.Name);

            Invalidate();
        }
예제 #2
0
        /// <summary>
        ///     Gets a track from the library matching the specified filename.
        /// </summary>
        /// <param name="filename">The filename.</param>
        /// <returns>The associated track, or null if it doesn't exist</returns>
        public Track GetTrackByFilename(string filename)
        {
            filename = filename.ToLower().Trim();

            lock (Tracks)
            {
                var track = Tracks.FirstOrDefault(t => t.Filename.ToLower() == filename);
                if (track != null && !File.Exists(track.Filename))
                {
                    track = null;
                }

                return(track);
            }
        }
예제 #3
0
        private void OnMessageMyMusicChanged(MessageMyMusicChanged message)
        {
            if (!message.AddedTracks.IsNullOrEmpty())
            {
                foreach (var track in message.AddedTracks)
                {
                    Tracks.Insert(0, track);
                }
            }

            if (!message.RemovedTracks.IsNullOrEmpty())
            {
                foreach (var track in message.RemovedTracks)
                {
                    Tracks.Remove(Tracks.FirstOrDefault(t => t.Id == track.Id));
                }
            }
        }
        /// <summary>
        /// Called after undo/redo to make sure that no deleted blocks or tracks are in the selection.
        /// </summary>
        public void SanityCheckSelections()
        {
            // TODO: once we have a better ObservableCollection, use RemoveAll for better performance
            for (int i = SelectedBlocks.Count - 1; i >= 0; i--)
            {
                var block = SelectedBlocks[i].GetModel();
                if (!model.Blocks.Contains(block))
                {
                    SelectedBlocks.RemoveAt(i);
                }
            }

            if (!Tracks.Contains(SelectedTrack))
            {
                // At this point, we don't really know where the selected track was,
                // so just go with the first one.
                SelectedTrack = Tracks.FirstOrDefault();
            }
        }
예제 #5
0
        private void NextPlayTrack(Track track)
        {
            if (Tracks.Count > 0)
            {
                Track nextTrack;
                var   currentIndexTrack = Tracks.IndexOf(track);
                var   nextIndexTrack    = currentIndexTrack + 1;

                nextTrack = nextIndexTrack < Tracks.Count ?
                            Tracks[nextIndexTrack] :
                            Tracks.FirstOrDefault();

                CurrentTrack     = nextTrack;
                CurrentUri       = nextTrack.Path;
                CurrentTrackName = nextTrack.FullName;
                SliderMinimum    = SliderMaximum = SliderValue = 0.0;
                LoadedMode       = MediaState.Play;
            }
        }
예제 #6
0
        public bool WriteSectorsLong(byte[] data, ulong sectorAddress, uint length)
        {
            if (!IsWriting)
            {
                ErrorMessage = "Tried to write on a non-writable image";

                return(false);
            }

            Track track =
                Tracks.FirstOrDefault(trk => sectorAddress >= trk.TrackStartSector &&
                                      sectorAddress <= trk.TrackEndSector);

            if (track is null)
            {
                ErrorMessage = $"Can't found track containing {sectorAddress}";

                return(false);
            }

            if (sectorAddress + length > track.TrackEndSector + 1)
            {
                ErrorMessage = "Can't cross tracks";

                return(false);
            }

            if (data.Length % track.TrackRawBytesPerSector != 0)
            {
                ErrorMessage = "Incorrect data size";

                return(false);
            }

            _dataStream.
            Seek((long)(track.TrackFileOffset + ((sectorAddress - track.TrackStartSector) * (ulong)track.TrackRawBytesPerSector)),
                 SeekOrigin.Begin);

            _dataStream.Write(data, 0, data.Length);

            return(true);
        }
예제 #7
0
 void OnContestLoaded(object sender, LoadedEventArgs <Contest> e)
 {
     if (e.Error != null)
     {
         this.ShowError(e.Error.Message);
     }
     else
     {
         this.contest = e.Result;
         foreach (var t in e.Result.Tracks)
         {
             var trackViewModel = new TrackViewModel(t);
             trackViewModel.AnonymousMode    = this.AnonCommand.AnonymousMode;
             trackViewModel.PropertyChanged += (s, args) => this.dirtyFlag = true;
             this.Tracks.Add(trackViewModel);
         }
         SelectedTrack = Tracks.FirstOrDefault(t => !t.IsExcluded);
     }
     this.IsLoading = false;
 }
        private async Task ExecuteFilterCommand(Page page)
        {
            if (IsBusy)
            {
                return;
            }

            var trackNames = new List <string>(Tracks.Select(t => t.Title));

            if (trackNames.Count == 0)
            {
                return;
            }
            trackNames.Insert(0, "Show All");

            if (Device.OS == TargetPlatform.Android)
            {
                DependencyService.Get <IDialogs>().DisplayActionSheet("Select Tracks", "Cancel",
                                                                      trackNames.ToArray(),
                                                                      which =>
                {
                    _selectedTrack = which == 0 ? null : Tracks[which - 1];
                    FilterSessions(_selectedTrack);
                });     //if show all pass null
            }
            else
            {
                string action = await page.DisplayActionSheet("Select Track", "Cancel", null, trackNames.ToArray());

                if (action == "Cancel")
                {
                    return;
                }

                _selectedTrack = Tracks.FirstOrDefault(t => t.Title == action);
                FilterSessions(_selectedTrack);
            }
        }
예제 #9
0
        /// <summary>
        /// Remove roller from this belt. All TrackWheel components previously
        /// added to the <paramref name="roller"/> will be removed.
        /// </summary>
        /// <param name="roller">Roller to remove.</param>
        /// <returns>True if successfully removed, otherwise false (check console log).</returns>
        public bool Remove(GameObject roller)
        {
            if (roller == null || !m_rollers.Contains(roller))
            {
                return(false);
            }

            var trackWheels = roller.GetComponents <TrackWheel>();

            // This shouldn't happen when/if undo is working.
            if (trackWheels.Length == 0)
            {
                Debug.LogWarning($"Roller {roller.name} doesn't contain any TrackWheel instances.");
                return(false);
            }

            using (BeginResourceRequests()) {
                foreach (var trackWheel in trackWheels)
                {
                    var track = Tracks.FirstOrDefault(subject => subject.Contains(trackWheel));
                    if (track == null)
                    {
                        Debug.Log("TrackWheel wasn't removed from any track but will be destroyed.", trackWheel);
                    }
                    else
                    {
                        AboutToChange(track);
                        track.Remove(trackWheel);
                    }
                    DestroyObjectImmediate(trackWheel);
                }

                m_rollers.Remove(roller);
            }

            return(true);
        }
예제 #10
0
 /// <summary>
 /// Gets the media track
 /// </summary>
 /// <param name="trackId">track identifier</param>
 /// <returns>the media track</returns>
 public MediaTrack?GetMediaTrack(string trackId)
 {
     return(Tracks?.FirstOrDefault(t => t.Id == trackId));
 }
예제 #11
0
        public bool WriteSectorsTag(byte[] data, ulong sectorAddress, uint length, SectorTagType tag)
        {
            if (!IsWriting)
            {
                ErrorMessage = "Tried to write on a non-writable image";

                return(false);
            }

            Track track =
                Tracks.FirstOrDefault(trk => sectorAddress >= trk.TrackStartSector &&
                                      sectorAddress <= trk.TrackEndSector);

            if (track is null)
            {
                ErrorMessage = $"Can't found track containing {sectorAddress}";

                return(false);
            }

            switch (tag)
            {
            case SectorTagType.CdTrackFlags:
            case SectorTagType.CdTrackIsrc: return(WriteSectorTag(data, sectorAddress, tag));

            case SectorTagType.CdSectorSubchannel:
            {
                if (track.TrackSubchannelType == 0)
                {
                    ErrorMessage =
                        $"Trying to write subchannel to track {track.TrackSequence}, that does not have subchannel";

                    return(false);
                }

                if (data.Length % 96 != 0)
                {
                    ErrorMessage = "Incorrect data size for subchannel";

                    return(false);
                }

                if (_subStream == null)
                {
                    try
                    {
                        _subStream = new FileStream(_writingBaseName + ".sub", FileMode.OpenOrCreate,
                                                    FileAccess.ReadWrite, FileShare.None);
                    }
                    catch (IOException e)
                    {
                        ErrorMessage = $"Could not create subchannel file, exception {e.Message}";

                        return(false);
                    }
                }

                _subStream.
                Seek((long)(track.TrackSubchannelOffset + ((sectorAddress - track.TrackStartSector) * 96)),
                     SeekOrigin.Begin);

                _subStream.Write(Subchannel.Deinterleave(data), 0, data.Length);

                return(true);
            }

            default:
                ErrorMessage = $"Unsupported tag type {tag}";

                return(false);
            }
        }
예제 #12
0
        public bool Close()
        {
            if (!IsWriting)
            {
                ErrorMessage = "Image is not opened for writing";

                return(false);
            }

            _dataStream.Flush();
            _dataStream.Close();

            _subStream?.Flush();
            _subStream?.Close();

            FullTOC.CDFullTOC?nullableToc = null;
            FullTOC.CDFullTOC toc;

            // Easy, just decode the real toc
            if (_fulltoc != null)
            {
                byte[] tmp = new byte[_fulltoc.Length + 2];
                Array.Copy(BigEndianBitConverter.GetBytes((ushort)_fulltoc.Length), 0, tmp, 0, 2);
                Array.Copy(_fulltoc, 0, tmp, 2, _fulltoc.Length);
                nullableToc = FullTOC.Decode(tmp);
            }

            // Not easy, create a toc from scratch
            if (nullableToc == null)
            {
                toc = new FullTOC.CDFullTOC();
                Dictionary <byte, byte> sessionEndingTrack = new Dictionary <byte, byte>();
                toc.FirstCompleteSession = byte.MaxValue;
                toc.LastCompleteSession  = byte.MinValue;
                List <FullTOC.TrackDataDescriptor> trackDescriptors = new List <FullTOC.TrackDataDescriptor>();
                byte currentTrack = 0;

                foreach (Track track in Tracks.OrderBy(t => t.TrackSession).ThenBy(t => t.TrackSequence))
                {
                    if (track.TrackSession < toc.FirstCompleteSession)
                    {
                        toc.FirstCompleteSession = (byte)track.TrackSession;
                    }

                    if (track.TrackSession <= toc.LastCompleteSession)
                    {
                        currentTrack = (byte)track.TrackSequence;

                        continue;
                    }

                    if (toc.LastCompleteSession > 0)
                    {
                        sessionEndingTrack.Add(toc.LastCompleteSession, currentTrack);
                    }

                    toc.LastCompleteSession = (byte)track.TrackSession;
                }

                byte currentSession = 0;

                foreach (Track track in Tracks.OrderBy(t => t.TrackSession).ThenBy(t => t.TrackSequence))
                {
                    _trackFlags.TryGetValue((byte)track.TrackSequence, out byte trackControl);

                    if (trackControl == 0 &&
                        track.TrackType != TrackType.Audio)
                    {
                        trackControl = (byte)CdFlags.DataTrack;
                    }

                    // Lead-Out
                    if (track.TrackSession > currentSession &&
                        currentSession != 0)
                    {
                        (byte minute, byte second, byte frame)leadoutAmsf = LbaToMsf(track.TrackStartSector - 150);

                        (byte minute, byte second, byte frame)leadoutPmsf =
                            LbaToMsf(Tracks.OrderBy(t => t.TrackSession).ThenBy(t => t.TrackSequence).Last().
                                     TrackStartSector);

                        // Lead-out
                        trackDescriptors.Add(new FullTOC.TrackDataDescriptor
                        {
                            SessionNumber = currentSession,
                            POINT         = 0xB0,
                            ADR           = 5,
                            CONTROL       = 0,
                            HOUR          = 0,
                            Min           = leadoutAmsf.minute,
                            Sec           = leadoutAmsf.second,
                            Frame         = leadoutAmsf.frame,
                            PHOUR         = 2,
                            PMIN          = leadoutPmsf.minute,
                            PSEC          = leadoutPmsf.second,
                            PFRAME        = leadoutPmsf.frame
                        });

                        // This seems to be constant? It should not exist on CD-ROM but CloneCD creates them anyway
                        // Format seems like ATIP, but ATIP should not be as 0xC0 in TOC...
                        trackDescriptors.Add(new FullTOC.TrackDataDescriptor
                        {
                            SessionNumber = currentSession,
                            POINT         = 0xC0,
                            ADR           = 5,
                            CONTROL       = 0,
                            Min           = 128,
                            PMIN          = 97,
                            PSEC          = 25
                        });
                    }

                    // Lead-in
                    if (track.TrackSession > currentSession)
                    {
                        currentSession = (byte)track.TrackSession;
                        sessionEndingTrack.TryGetValue(currentSession, out byte endingTrackNumber);

                        (byte minute, byte second, byte frame)leadinPmsf =
                            LbaToMsf(Tracks.FirstOrDefault(t => t.TrackSequence == endingTrackNumber)?.TrackEndSector ??
                                     0 + 1);

                        // Starting track
                        trackDescriptors.Add(new FullTOC.TrackDataDescriptor
                        {
                            SessionNumber = currentSession,
                            POINT         = 0xA0,
                            ADR           = 1,
                            CONTROL       = trackControl,
                            PMIN          = (byte)track.TrackSequence
                        });

                        // Ending track
                        trackDescriptors.Add(new FullTOC.TrackDataDescriptor
                        {
                            SessionNumber = currentSession,
                            POINT         = 0xA1,
                            ADR           = 1,
                            CONTROL       = trackControl,
                            PMIN          = endingTrackNumber
                        });

                        // Lead-out start
                        trackDescriptors.Add(new FullTOC.TrackDataDescriptor
                        {
                            SessionNumber = currentSession,
                            POINT         = 0xA2,
                            ADR           = 1,
                            CONTROL       = trackControl,
                            PHOUR         = 0,
                            PMIN          = leadinPmsf.minute,
                            PSEC          = leadinPmsf.second,
                            PFRAME        = leadinPmsf.frame
                        });
                    }

                    (byte minute, byte second, byte frame)pmsf = LbaToMsf(track.TrackStartSector);

                    // Track
                    trackDescriptors.Add(new FullTOC.TrackDataDescriptor
                    {
                        SessionNumber = (byte)track.TrackSession,
                        POINT         = (byte)track.TrackSequence,
                        ADR           = 1,
                        CONTROL       = trackControl,
                        PHOUR         = 0,
                        PMIN          = pmsf.minute,
                        PSEC          = pmsf.second,
                        PFRAME        = pmsf.frame
                    });
                }

                toc.TrackDescriptors = trackDescriptors.ToArray();
            }
            else
            {
                toc = nullableToc.Value;
            }

            _descriptorStream.WriteLine("[CloneCD]");
            _descriptorStream.WriteLine("Version=2");
            _descriptorStream.WriteLine("[Disc]");
            _descriptorStream.WriteLine("TocEntries={0}", toc.TrackDescriptors.Length);
            _descriptorStream.WriteLine("Sessions={0}", toc.LastCompleteSession);
            _descriptorStream.WriteLine("DataTracksScrambled=0");
            _descriptorStream.WriteLine("CDTextLength=0");

            if (!string.IsNullOrEmpty(_catalog))
            {
                _descriptorStream.WriteLine("CATALOG={0}", _catalog);
            }

            for (int i = 1; i <= toc.LastCompleteSession; i++)
            {
                _descriptorStream.WriteLine("[Session {0}]", i);

                Track firstSessionTrack = Tracks.FirstOrDefault(t => t.TrackSession == i);

                switch (firstSessionTrack?.TrackType)
                {
                case TrackType.Audio:
                    // CloneCD always writes this value for first track in disc, however the Rainbow Books
                    // say the first track pregap is no different from other session pregaps, same mode as
                    // the track they belong to.
                    _descriptorStream.WriteLine("PreGapMode=0");

                    break;

                case TrackType.Data:
                case TrackType.CdMode1:
                    _descriptorStream.WriteLine("PreGapMode=1");

                    break;

                case TrackType.CdMode2Formless:
                case TrackType.CdMode2Form1:
                case TrackType.CdMode2Form2:
                    _descriptorStream.WriteLine("PreGapMode=2");

                    break;

                default: throw new ArgumentOutOfRangeException();
                }

                _descriptorStream.WriteLine("PreGapSubC=0");
            }

            for (int i = 0; i < toc.TrackDescriptors.Length; i++)
            {
                long alba = MsfToLba((toc.TrackDescriptors[i].Min, toc.TrackDescriptors[i].Sec,
                                      toc.TrackDescriptors[i].Frame));

                long plba = MsfToLba((toc.TrackDescriptors[i].PMIN, toc.TrackDescriptors[i].PSEC,
                                      toc.TrackDescriptors[i].PFRAME));

                if (alba > 405000)
                {
                    alba = ((alba - 405000) + 300) * -1;
                }

                if (plba > 405000)
                {
                    plba = ((plba - 405000) + 300) * -1;
                }

                _descriptorStream.WriteLine("[Entry {0}]", i);
                _descriptorStream.WriteLine("Session={0}", toc.TrackDescriptors[i].SessionNumber);
                _descriptorStream.WriteLine("Point=0x{0:x2}", toc.TrackDescriptors[i].POINT);
                _descriptorStream.WriteLine("ADR=0x{0:x2}", toc.TrackDescriptors[i].ADR);
                _descriptorStream.WriteLine("Control=0x{0:x2}", toc.TrackDescriptors[i].CONTROL);
                _descriptorStream.WriteLine("TrackNo={0}", toc.TrackDescriptors[i].TNO);
                _descriptorStream.WriteLine("AMin={0}", toc.TrackDescriptors[i].Min);
                _descriptorStream.WriteLine("ASec={0}", toc.TrackDescriptors[i].Sec);
                _descriptorStream.WriteLine("AFrame={0}", toc.TrackDescriptors[i].Frame);
                _descriptorStream.WriteLine("ALBA={0}", alba);

                _descriptorStream.WriteLine("Zero={0}",
                                            ((toc.TrackDescriptors[i].HOUR & 0x0F) << 4) +
                                            (toc.TrackDescriptors[i].PHOUR & 0x0F));

                _descriptorStream.WriteLine("PMin={0}", toc.TrackDescriptors[i].PMIN);
                _descriptorStream.WriteLine("PSec={0}", toc.TrackDescriptors[i].PSEC);
                _descriptorStream.WriteLine("PFrame={0}", toc.TrackDescriptors[i].PFRAME);
                _descriptorStream.WriteLine("PLBA={0}", plba);
            }

            _descriptorStream.Flush();
            _descriptorStream.Close();

            IsWriting    = false;
            ErrorMessage = "";

            return(true);
        }
예제 #13
0
 /// <summary>
 /// Gets the track description
 /// </summary>
 /// <param name="trackId">track identifier</param>
 /// <returns>the track description</returns>
 public TrackDescription?GetTrackDescription(int trackId)
 {
     return(Tracks.FirstOrDefault(t => t.Id == trackId));
 }
예제 #14
0
 public Track GetTrackById(int trackId) => Tracks.FirstOrDefault(t => t.TrackId == trackId);
예제 #15
0
        public bool Close()
        {
            if (!IsWriting)
            {
                ErrorMessage = "Image is not opened for writing";
                return(false);
            }

            dataStream.Flush();
            dataStream.Close();

            subStream?.Flush();
            subStream?.Close();

            FullTOC.CDFullTOC?nullableToc = null;
            FullTOC.CDFullTOC toc;

            // Easy, just decode the real toc
            if (fulltoc != null)
            {
                nullableToc = FullTOC.Decode(fulltoc);
            }

            // Not easy, create a toc from scratch
            if (nullableToc == null)
            {
                toc = new FullTOC.CDFullTOC();
                Dictionary <byte, byte> sessionEndingTrack = new Dictionary <byte, byte>();
                toc.FirstCompleteSession = byte.MaxValue;
                toc.LastCompleteSession  = byte.MinValue;
                List <FullTOC.TrackDataDescriptor> trackDescriptors = new List <FullTOC.TrackDataDescriptor>();
                byte currentTrack = 0;

                foreach (Track track in Tracks.OrderBy(t => t.TrackSession).ThenBy(t => t.TrackSequence))
                {
                    if (track.TrackSession < toc.FirstCompleteSession)
                    {
                        toc.FirstCompleteSession = (byte)track.TrackSession;
                    }

                    if (track.TrackSession <= toc.LastCompleteSession)
                    {
                        currentTrack = (byte)track.TrackSequence;
                        continue;
                    }

                    if (toc.LastCompleteSession > 0)
                    {
                        sessionEndingTrack.Add(toc.LastCompleteSession, currentTrack);
                    }

                    toc.LastCompleteSession = (byte)track.TrackSession;
                }

                byte currentSession = 0;

                foreach (Track track in Tracks.OrderBy(t => t.TrackSession).ThenBy(t => t.TrackSequence))
                {
                    trackFlags.TryGetValue((byte)track.TrackSequence, out byte trackControl);

                    if (trackControl == 0 && track.TrackType != TrackType.Audio)
                    {
                        trackControl = (byte)CdFlags.DataTrack;
                    }

                    // Lead-Out
                    if (track.TrackSession > currentSession && currentSession != 0)
                    {
                        (byte minute, byte second, byte frame)leadoutAmsf = LbaToMsf(track.TrackStartSector - 150);
                        (byte minute, byte second, byte frame)leadoutPmsf =
                            LbaToMsf(Tracks.OrderBy(t => t.TrackSession).ThenBy(t => t.TrackSequence).Last()
                                     .TrackStartSector);

                        // Lead-out
                        trackDescriptors.Add(new FullTOC.TrackDataDescriptor
                        {
                            SessionNumber = currentSession,
                            POINT         = 0xB0,
                            ADR           = 5,
                            CONTROL       = 0,
                            HOUR          = 0,
                            Min           = leadoutAmsf.minute,
                            Sec           = leadoutAmsf.second,
                            Frame         = leadoutAmsf.frame,
                            PHOUR         = 2,
                            PMIN          = leadoutPmsf.minute,
                            PSEC          = leadoutPmsf.second,
                            PFRAME        = leadoutPmsf.frame
                        });

                        // This seems to be constant? It should not exist on CD-ROM but CloneCD creates them anyway
                        // Format seems like ATIP, but ATIP should not be as 0xC0 in TOC...
                        trackDescriptors.Add(new FullTOC.TrackDataDescriptor
                        {
                            SessionNumber = currentSession,
                            POINT         = 0xC0,
                            ADR           = 5,
                            CONTROL       = 0,
                            Min           = 128,
                            PMIN          = 97,
                            PSEC          = 25
                        });
                    }

                    // Lead-in
                    if (track.TrackSession > currentSession)
                    {
                        currentSession = (byte)track.TrackSession;
                        sessionEndingTrack.TryGetValue(currentSession, out byte endingTrackNumber);
                        (byte minute, byte second, byte frame)leadinPmsf =
                            LbaToMsf(Tracks.FirstOrDefault(t => t.TrackSequence == endingTrackNumber).TrackEndSector +
                                     1);

                        // Starting track
                        trackDescriptors.Add(new FullTOC.TrackDataDescriptor
                        {
                            SessionNumber = currentSession,
                            POINT         = 0xA0,
                            ADR           = 1,
                            CONTROL       = trackControl,
                            PMIN          = (byte)track.TrackSequence
                        });

                        // Ending track
                        trackDescriptors.Add(new FullTOC.TrackDataDescriptor
                        {
                            SessionNumber = currentSession,
                            POINT         = 0xA1,
                            ADR           = 1,
                            CONTROL       = trackControl,
                            PMIN          = endingTrackNumber
                        });

                        // Lead-out start
                        trackDescriptors.Add(new FullTOC.TrackDataDescriptor
                        {
                            SessionNumber = currentSession,
                            POINT         = 0xA2,
                            ADR           = 1,
                            CONTROL       = trackControl,
                            PHOUR         = 0,
                            PMIN          = leadinPmsf.minute,
                            PSEC          = leadinPmsf.second,
                            PFRAME        = leadinPmsf.frame
                        });
                    }

                    (byte minute, byte second, byte frame)pmsf = LbaToMsf(track.TrackStartSector);

                    // Track
                    trackDescriptors.Add(new FullTOC.TrackDataDescriptor
                    {
                        SessionNumber = (byte)track.TrackSession,
                        POINT         = (byte)track.TrackSequence,
                        ADR           = 1,
                        CONTROL       = trackControl,
                        PHOUR         = 0,
                        PMIN          = pmsf.minute,
                        PSEC          = pmsf.second,
                        PFRAME        = pmsf.frame
                    });
                }

                toc.TrackDescriptors = trackDescriptors.ToArray();
            }
            else
            {
                toc = nullableToc.Value;
            }

            descriptorStream.WriteLine("[CloneCD]");
            descriptorStream.WriteLine("Version=2");
            descriptorStream.WriteLine("[Disc]");
            descriptorStream.WriteLine("TocEntries={0}", toc.TrackDescriptors.Length);
            descriptorStream.WriteLine("Sessions={0}", toc.LastCompleteSession);
            descriptorStream.WriteLine("DataTracksScrambled=0");
            descriptorStream.WriteLine("CDTextLength=0");
            if (!string.IsNullOrEmpty(catalog))
            {
                descriptorStream.WriteLine("CATALOG={0}", catalog);
            }
            for (int i = 1; i <= toc.LastCompleteSession; i++)
            {
                // TODO: Use first track of session info
                descriptorStream.WriteLine("[Session {0}]", i);
                descriptorStream.WriteLine("PreGapMode=0");
                descriptorStream.WriteLine("PreGapSubC=0");
            }

            for (int i = 0; i < toc.TrackDescriptors.Length; i++)
            {
                long alba = MsfToLba((toc.TrackDescriptors[i].Min, toc.TrackDescriptors[i].Sec,
                                      toc.TrackDescriptors[i].Frame));
                long plba = MsfToLba((toc.TrackDescriptors[i].PMIN, toc.TrackDescriptors[i].PSEC,
                                      toc.TrackDescriptors[i].PFRAME));

                if (alba > 405000)
                {
                    alba = (alba - 405000 + 300) * -1;
                }
                if (plba > 405000)
                {
                    plba = (plba - 405000 + 300) * -1;
                }

                descriptorStream.WriteLine("[Entry {0}]", i);
                descriptorStream.WriteLine("Session={0}", toc.TrackDescriptors[i].SessionNumber);
                descriptorStream.WriteLine("Point=0x{0:x2}", toc.TrackDescriptors[i].POINT);
                descriptorStream.WriteLine("ADR=0x{0:x2}", toc.TrackDescriptors[i].ADR);
                descriptorStream.WriteLine("Control=0x{0:x2}", toc.TrackDescriptors[i].CONTROL);
                descriptorStream.WriteLine("TrackNo={0}", toc.TrackDescriptors[i].TNO);
                descriptorStream.WriteLine("AMin={0}", toc.TrackDescriptors[i].Min);
                descriptorStream.WriteLine("ASec={0}", toc.TrackDescriptors[i].Sec);
                descriptorStream.WriteLine("AFrame={0}", toc.TrackDescriptors[i].Frame);
                descriptorStream.WriteLine("ALBA={0}", alba);
                descriptorStream.WriteLine("Zero={0}",
                                           ((toc.TrackDescriptors[i].HOUR & 0x0F) << 4) +
                                           (toc.TrackDescriptors[i].PHOUR & 0x0F));
                descriptorStream.WriteLine("PMin={0}", toc.TrackDescriptors[i].PMIN);
                descriptorStream.WriteLine("PSec={0}", toc.TrackDescriptors[i].PSEC);
                descriptorStream.WriteLine("PFrame={0}", toc.TrackDescriptors[i].PFRAME);
                descriptorStream.WriteLine("PLBA={0}", plba);
            }

            descriptorStream.Flush();
            descriptorStream.Close();

            IsWriting    = false;
            ErrorMessage = "";
            return(true);
        }
예제 #16
0
        protected override void OnPaint(PaintEventArgs e)
        {
            // Reset
            e.Graphics.Clear(bgColor);
            buttons.Clear();

            int midx = Width / 2;

            // Richtungsangaben ermitteln
            var route  = tt.GetRoute(routeIndex).Stations;
            var staIdx = route.IndexOf(station);
            var prev   = route.ElementAtOrDefault(staIdx - 1);
            var next   = route.ElementAtOrDefault(staIdx + 1);

            bool disableRight = tt.Type == TimetableType.Network && next == null;
            bool disableLeft  = tt.Type == TimetableType.Network && prev == null;

            // Richtungsangaben zeichnen
            if (prev != null)
            {
                e.Graphics.DrawText(font, textColor, 5, 5, T._("von {0}", prev.SName));
            }
            if (next != null)
            {
                var nextText = T._("nach {0}", next.SName);
                var nextSize = e.Graphics.MeasureString(font, nextText);
                e.Graphics.DrawText(font, textColor, Width - 5 - nextSize.Width, 5, nextText);
            }

            var leftdefaultTrack  = Tracks.IndexOf(Tracks.FirstOrDefault(t => t.Name == DefaultTrackLeft.GetValue(routeIndex)));
            var rightdefaultTrack = Tracks.IndexOf(Tracks.FirstOrDefault(t => t.Name == DefaultTrackRight.GetValue(routeIndex)));

            // Netzwerk: Falls noch keine Angabe: Standardgleise setzen
            if (tt.Type == TimetableType.Network && Tracks.Any())
            {
                if (disableLeft)
                {
                    leftdefaultTrack = 0;
                }
                else if (leftdefaultTrack == -1)
                {
                    MoveDefaultTrack(DefaultTrackLeft, Tracks.First(), 0);
                    leftdefaultTrack = 0;
                }

                if (disableRight)
                {
                    rightdefaultTrack = 0;
                }
                else if (rightdefaultTrack == -1)
                {
                    MoveDefaultTrack(DefaultTrackRight, Tracks.First(), 0);
                    rightdefaultTrack = 0;
                }
            }

            int y         = 30;
            int maxIndent = 0;

            foreach (var track in Tracks)
            {
                var trackIndex = Tracks.IndexOf(track);

                // Einrückung des Gleisvorfeldes berehcnen
                var leftIndent = Math.Abs(leftdefaultTrack - trackIndex) * INDENT + 60;
                if (leftdefaultTrack == trackIndex)
                {
                    leftIndent = disableLeft ? 30 : 0;
                }

                var rightIndent = Math.Abs(rightdefaultTrack - trackIndex) * INDENT + 60;
                if (rightdefaultTrack == trackIndex)
                {
                    rightIndent = disableRight ? 30 : 0;
                }
                maxIndent   = Math.Max(maxIndent, rightIndent + leftIndent);
                rightIndent = Width - rightIndent;

                // Gleiselinie zeichnen
                e.Graphics.DrawLine(textColor, leftIndent, y, rightIndent, y);

                // Gleisverbindungen zeichnen
                if (trackIndex < leftdefaultTrack)
                {
                    e.Graphics.DrawLine(textColor, leftIndent, y, leftIndent - INDENT, y + LINE_HEIGHT);
                }
                else if (trackIndex > leftdefaultTrack)
                {
                    e.Graphics.DrawLine(textColor, leftIndent, y, leftIndent - INDENT, y - LINE_HEIGHT);
                }

                if (trackIndex < rightdefaultTrack)
                {
                    e.Graphics.DrawLine(textColor, rightIndent, y, rightIndent + INDENT, y + LINE_HEIGHT);
                }
                else if (trackIndex > rightdefaultTrack)
                {
                    e.Graphics.DrawLine(textColor, rightIndent, y, rightIndent + INDENT, y - LINE_HEIGHT);
                }

                // Gleisnamen als Button hinzufügen
                var textSize = e.Graphics.MeasureString(font, track.Name);
                var nameBtn  = new RenderBtn <Track>(track, new Point(midx - (int)(textSize.Width / 2) - 5, y - 8), new Size((int)textSize.Width + 5, 16), bgColor, track.Name, textColor);
                nameBtn.Click += NameBtn_Click;
                buttons.Add(nameBtn);

                // Netzwerk: Standardgleise anderer Routen gestrichelt zeichnen.
                if (DefaultTrackLeft.ContainsValue(track.Name) && leftdefaultTrack != trackIndex)
                {
                    e.Graphics.DrawLine(dashedPen, 0, y, leftIndent, y);
                }
                if (DefaultTrackRight.ContainsValue(track.Name) && rightdefaultTrack != trackIndex)
                {
                    e.Graphics.DrawLine(dashedPen, rightIndent, y, Width, y);
                }

                // Aktions-Buttons hinzufügen
                var btnLeft   = midx + (int)(textSize.Width / 2) + 10;
                var deleteBtn = GetButton("X", track, btnLeft, y);
                deleteBtn.Click += DeleteBtn_Click;

                var upBtn = GetButton("▲", track, btnLeft + 20, y);
                upBtn.Click += UpBtn_Click;

                var downBtn = GetButton("▼", track, btnLeft + 40, y);
                downBtn.Click += DownBtn_Click;

                // Aktionsbuttons für Standardgleise
                if (trackIndex == leftdefaultTrack && !disableLeft)
                {
                    var leftUpBtn = GetButton("▲", track, 10, y);
                    leftUpBtn.Click += (s, x) => MoveDefaultTrack(DefaultTrackLeft, ((RenderBtn <Track>)s).Tag, -1);
                    var leftDownBtn = GetButton("▼", track, 30, y);
                    leftDownBtn.Click += (s, x) => MoveDefaultTrack(DefaultTrackLeft, ((RenderBtn <Track>)s).Tag, 1);
                }

                if (trackIndex == rightdefaultTrack && !disableRight)
                {
                    var rightUpButton = GetButton("▲", track, Width - 46, y);
                    rightUpButton.Click += (s, x) => MoveDefaultTrack(DefaultTrackRight, ((RenderBtn <Track>)s).Tag, -1);
                    var rightDownBtn = GetButton("▼", track, Width - 26, y);
                    rightDownBtn.Click += (s, x) => MoveDefaultTrack(DefaultTrackRight, ((RenderBtn <Track>)s).Tag, 1);
                }

                y += LINE_HEIGHT;
            }

            // Button für neue Gleise
            var addTrackText = T._("Neues Gleis hinzufügen");
            var textWidth    = (int)e.Graphics.MeasureString(font, addTrackText).Width;
            var addBtn       = new RenderBtn <Track>(null, new Point(midx - (textWidth / 2) - 5, y - 8), new Size(textWidth + 10, 16), Colors.LightGrey, addTrackText);

            buttons.Add(addBtn);
            addBtn.Click += AddBtn_Click;

            var newHeight = (Tracks.Count) * LINE_HEIGHT + 50;

            if (newHeight > Height)
            {
                this.Height = newHeight;
            }

            else if (maxIndent > Width - 30)
            {
                Width = maxIndent + 30;
            }

            foreach (var args in buttons)
            {
                args.Draw(e.Graphics);
            }

            base.OnPaint(e);
        }