001/**
002 * Copyright (c) 2011, The University of Southampton and the individual contributors.
003 * All rights reserved.
004 *
005 * Redistribution and use in source and binary forms, with or without modification,
006 * are permitted provided that the following conditions are met:
007 *
008 *   *  Redistributions of source code must retain the above copyright notice,
009 *      this list of conditions and the following disclaimer.
010 *
011 *   *  Redistributions in binary form must reproduce the above copyright notice,
012 *      this list of conditions and the following disclaimer in the documentation
013 *      and/or other materials provided with the distribution.
014 *
015 *   *  Neither the name of the University of Southampton nor the names of its
016 *      contributors may be used to endorse or promote products derived from this
017 *      software without specific prior written permission.
018 *
019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
020 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
021 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
022 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
023 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
025 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
026 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
027 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
028 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029 */
030/**
031 * 
032 */
033package org.openimaj.video.timecode;
034
035import java.util.regex.Matcher;
036import java.util.regex.Pattern;
037
038/**
039 *      A timecode representation that extends the standard frame count representation
040 *      to provide hours, minutes, seconds and frames timecode.
041 * 
042 *  @author David Dupplaw (dpd@ecs.soton.ac.uk)
043 *      
044 *      @created 6 Jun 2011
045 */
046public class HrsMinSecFrameTimecode extends FrameNumberVideoTimecode
047{
048        /**
049         *      Default constructor that takes the current (start) frame number
050         *      and the number of frames in one second.
051         * 
052         *  @param number The frame number.
053         *  @param framesPerSec The number of frames per second.
054         */
055        public HrsMinSecFrameTimecode( final long number, final double framesPerSec )
056        {
057                super( number, framesPerSec );
058        }
059
060        /**
061         *      Get the number of hours.
062         *  @return The number of hours.
063         */
064        public int getHours()
065        {
066                return (int)(this.getFrameNumber() / this.fps / 3600d);         
067        }
068        
069        /**
070         *      Get the number of minutes within the hour.
071         *  @return The number of minutes within the hour.
072         */
073        public int getMinutes()
074        {
075                return (int)(this.getFrameNumber() / this.fps / 60d) % 60;
076        }
077        
078        /**
079         *      Get the number of seconds within the minute.
080         *  @return The number of seconds within the minute.
081         */
082        public int getSeconds()
083        {
084                return (int)(this.getFrameNumber() / this.fps) % 60;
085        }
086        
087        /**
088         *      Get the number of frames within the second.
089         *  @return The number of frames within the second.
090         */
091        public int getFrames()
092        {
093                return (int)(this.getFrameNumber() % this.fps);
094        }
095
096        /**
097         *  {@inheritDoc}
098         *  @see org.openimaj.video.timecode.FrameNumberVideoTimecode#toString()
099         */
100        @Override
101        public String toString()
102        {
103            return this.getHours()+":"+this.getMinutes()+":"+this.getSeconds()+":"
104                        +this.getFrames()+"/"+this.fps;
105        }
106
107        /**
108         *      Parses a string (formatted as {@link #toString()}) back into a
109         *      timecode object.
110         * 
111         *      @param s The string to parse
112         *      @return A new {@link HrsMinSecFrameTimecode} or null if the string
113         *              couldn't be parsed.
114         */
115        public static HrsMinSecFrameTimecode fromString( final String s )
116        {
117                final Pattern p = Pattern.compile( "(\\d+):(\\d+):(\\d+):(\\d+)/([\\d.]+)");
118                final Matcher m = p.matcher( s );
119
120                // Check for a match
121                if( !m.find() )
122                        return null;
123                
124                // Extract all the bits and bobs
125                final double fps = Double.parseDouble(m.group(3));
126                final int hrs = Integer.parseInt( m.group(0) );
127                final int min = Integer.parseInt( m.group(1) );
128                final int sec = Integer.parseInt( m.group(2) );
129                final int frames = Integer.parseInt( m.group(3) );
130                
131                // Work out the frame number from the bits and bobs
132                final int frameNumber = (int)(frames + sec*fps + min*60*fps + hrs*3600*fps);
133                
134                // Create a new object
135                final HrsMinSecFrameTimecode h = new HrsMinSecFrameTimecode( frameNumber, fps );
136                return h;
137        }
138        
139        /**
140         *  {@inheritDoc}
141         *  @see java.lang.Object#hashCode()
142         */
143        @Override
144        public int hashCode()
145        {
146            return this.toString().hashCode();
147        }
148
149        /**
150         *  {@inheritDoc}
151         *  @see java.lang.Object#equals(java.lang.Object)
152         */
153        @Override
154        public boolean equals( final Object obj )
155        {
156                if( obj instanceof HrsMinSecFrameTimecode )
157                {
158                        final HrsMinSecFrameTimecode h = (HrsMinSecFrameTimecode)obj;
159                        return h.getHours() == this.getHours() &&
160                                h.getMinutes() == this.getMinutes() &&
161                                h.getSeconds() == this.getSeconds() &&
162                                h.getFrames() == this.getFrames();
163                }
164                
165                return false;
166        }
167        
168        /**
169         *      {@inheritDoc}
170         *      @see org.openimaj.video.timecode.FrameNumberVideoTimecode#clone()
171         */
172        @Override
173        public HrsMinSecFrameTimecode clone()
174        {
175                return new HrsMinSecFrameTimecode( this.getFrameNumber(), this.fps );
176        }
177}